Failed to save the file to the "xx" directory.

Failed to save the file to the "ll" directory.

Failed to save the file to the "mm" directory.

Failed to save the file to the "wp" directory.

403WebShell
403Webshell
Server IP : 66.29.132.124  /  Your IP : 3.147.46.174
Web Server : LiteSpeed
System : Linux business141.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64
User : wavevlvu ( 1524)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /proc/self/root/opt/cloudlinux/venv/lib/python3.11/site-packages/numpy/core/tests/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /proc/self/root/opt/cloudlinux/venv/lib/python3.11/site-packages/numpy/core/tests/test_datetime.py
import numpy
import numpy as np
import datetime
import pytest
from numpy.testing import (
    IS_WASM,
    assert_, assert_equal, assert_raises, assert_warns, suppress_warnings,
    assert_raises_regex, assert_array_equal,
    )
from numpy.compat import pickle

# Use pytz to test out various time zones if available
try:
    from pytz import timezone as tz
    _has_pytz = True
except ImportError:
    _has_pytz = False

try:
    RecursionError
except NameError:
    RecursionError = RuntimeError  # python < 3.5


class TestDateTime:
    def test_datetime_dtype_creation(self):
        for unit in ['Y', 'M', 'W', 'D',
                     'h', 'm', 's', 'ms', 'us',
                     'μs',  # alias for us
                     'ns', 'ps', 'fs', 'as']:
            dt1 = np.dtype('M8[750%s]' % unit)
            assert_(dt1 == np.dtype('datetime64[750%s]' % unit))
            dt2 = np.dtype('m8[%s]' % unit)
            assert_(dt2 == np.dtype('timedelta64[%s]' % unit))

        # Generic units shouldn't add [] to the end
        assert_equal(str(np.dtype("M8")), "datetime64")

        # Should be possible to specify the endianness
        assert_equal(np.dtype("=M8"), np.dtype("M8"))
        assert_equal(np.dtype("=M8[s]"), np.dtype("M8[s]"))
        assert_(np.dtype(">M8") == np.dtype("M8") or
                np.dtype("<M8") == np.dtype("M8"))
        assert_(np.dtype(">M8[D]") == np.dtype("M8[D]") or
                np.dtype("<M8[D]") == np.dtype("M8[D]"))
        assert_(np.dtype(">M8") != np.dtype("<M8"))

        assert_equal(np.dtype("=m8"), np.dtype("m8"))
        assert_equal(np.dtype("=m8[s]"), np.dtype("m8[s]"))
        assert_(np.dtype(">m8") == np.dtype("m8") or
                np.dtype("<m8") == np.dtype("m8"))
        assert_(np.dtype(">m8[D]") == np.dtype("m8[D]") or
                np.dtype("<m8[D]") == np.dtype("m8[D]"))
        assert_(np.dtype(">m8") != np.dtype("<m8"))

        # Check that the parser rejects bad datetime types
        assert_raises(TypeError, np.dtype, 'M8[badunit]')
        assert_raises(TypeError, np.dtype, 'm8[badunit]')
        assert_raises(TypeError, np.dtype, 'M8[YY]')
        assert_raises(TypeError, np.dtype, 'm8[YY]')
        assert_raises(TypeError, np.dtype, 'm4')
        assert_raises(TypeError, np.dtype, 'M7')
        assert_raises(TypeError, np.dtype, 'm7')
        assert_raises(TypeError, np.dtype, 'M16')
        assert_raises(TypeError, np.dtype, 'm16')
        assert_raises(TypeError, np.dtype, 'M8[3000000000ps]')

    def test_datetime_casting_rules(self):
        # Cannot cast safely/same_kind between timedelta and datetime
        assert_(not np.can_cast('m8', 'M8', casting='same_kind'))
        assert_(not np.can_cast('M8', 'm8', casting='same_kind'))
        assert_(not np.can_cast('m8', 'M8', casting='safe'))
        assert_(not np.can_cast('M8', 'm8', casting='safe'))

        # Can cast safely/same_kind from integer to timedelta
        assert_(np.can_cast('i8', 'm8', casting='same_kind'))
        assert_(np.can_cast('i8', 'm8', casting='safe'))
        assert_(np.can_cast('i4', 'm8', casting='same_kind'))
        assert_(np.can_cast('i4', 'm8', casting='safe'))
        assert_(np.can_cast('u4', 'm8', casting='same_kind'))
        assert_(np.can_cast('u4', 'm8', casting='safe'))

        # Cannot cast safely from unsigned integer of the same size, which
        # could overflow
        assert_(np.can_cast('u8', 'm8', casting='same_kind'))
        assert_(not np.can_cast('u8', 'm8', casting='safe'))

        # Cannot cast safely/same_kind from float to timedelta
        assert_(not np.can_cast('f4', 'm8', casting='same_kind'))
        assert_(not np.can_cast('f4', 'm8', casting='safe'))

        # Cannot cast safely/same_kind from integer to datetime
        assert_(not np.can_cast('i8', 'M8', casting='same_kind'))
        assert_(not np.can_cast('i8', 'M8', casting='safe'))

        # Cannot cast safely/same_kind from bool to datetime
        assert_(not np.can_cast('b1', 'M8', casting='same_kind'))
        assert_(not np.can_cast('b1', 'M8', casting='safe'))
        # Can cast safely/same_kind from bool to timedelta
        assert_(np.can_cast('b1', 'm8', casting='same_kind'))
        assert_(np.can_cast('b1', 'm8', casting='safe'))

        # Can cast datetime safely from months/years to days
        assert_(np.can_cast('M8[M]', 'M8[D]', casting='safe'))
        assert_(np.can_cast('M8[Y]', 'M8[D]', casting='safe'))
        # Cannot cast timedelta safely from months/years to days
        assert_(not np.can_cast('m8[M]', 'm8[D]', casting='safe'))
        assert_(not np.can_cast('m8[Y]', 'm8[D]', casting='safe'))
        # Can cast datetime same_kind from months/years to days
        assert_(np.can_cast('M8[M]', 'M8[D]', casting='same_kind'))
        assert_(np.can_cast('M8[Y]', 'M8[D]', casting='same_kind'))
        # Can't cast timedelta same_kind from months/years to days
        assert_(not np.can_cast('m8[M]', 'm8[D]', casting='same_kind'))
        assert_(not np.can_cast('m8[Y]', 'm8[D]', casting='same_kind'))
        # Can cast datetime same_kind across the date/time boundary
        assert_(np.can_cast('M8[D]', 'M8[h]', casting='same_kind'))
        # Can cast timedelta same_kind across the date/time boundary
        assert_(np.can_cast('m8[D]', 'm8[h]', casting='same_kind'))
        assert_(np.can_cast('m8[h]', 'm8[D]', casting='same_kind'))

        # Cannot cast safely if the integer multiplier doesn't divide
        assert_(not np.can_cast('M8[7h]', 'M8[3h]', casting='safe'))
        assert_(not np.can_cast('M8[3h]', 'M8[6h]', casting='safe'))
        # But can cast same_kind
        assert_(np.can_cast('M8[7h]', 'M8[3h]', casting='same_kind'))
        # Can cast safely if the integer multiplier does divide
        assert_(np.can_cast('M8[6h]', 'M8[3h]', casting='safe'))

        # We can always cast types with generic units (corresponding to NaT) to
        # more specific types
        assert_(np.can_cast('m8', 'm8[h]', casting='same_kind'))
        assert_(np.can_cast('m8', 'm8[h]', casting='safe'))
        assert_(np.can_cast('M8', 'M8[h]', casting='same_kind'))
        assert_(np.can_cast('M8', 'M8[h]', casting='safe'))
        # but not the other way around
        assert_(not np.can_cast('m8[h]', 'm8', casting='same_kind'))
        assert_(not np.can_cast('m8[h]', 'm8', casting='safe'))
        assert_(not np.can_cast('M8[h]', 'M8', casting='same_kind'))
        assert_(not np.can_cast('M8[h]', 'M8', casting='safe'))

    def test_datetime_prefix_conversions(self):
        # regression tests related to gh-19631;
        # test metric prefixes from seconds down to
        # attoseconds for bidirectional conversions
        smaller_units = ['M8[7000ms]',
                         'M8[2000us]',
                         'M8[1000ns]',
                         'M8[5000ns]',
                         'M8[2000ps]',
                         'M8[9000fs]',
                         'M8[1000as]',
                         'M8[2000000ps]',
                         'M8[1000000as]',
                         'M8[2000000000ps]',
                         'M8[1000000000as]']
        larger_units = ['M8[7s]',
                        'M8[2ms]',
                        'M8[us]',
                        'M8[5us]',
                        'M8[2ns]',
                        'M8[9ps]',
                        'M8[1fs]',
                        'M8[2us]',
                        'M8[1ps]',
                        'M8[2ms]',
                        'M8[1ns]']
        for larger_unit, smaller_unit in zip(larger_units, smaller_units):
            assert np.can_cast(larger_unit, smaller_unit, casting='safe')
            assert np.can_cast(smaller_unit, larger_unit, casting='safe')

    @pytest.mark.parametrize("unit", [
        "s", "ms", "us", "ns", "ps", "fs", "as"])
    def test_prohibit_negative_datetime(self, unit):
        with assert_raises(TypeError):
            np.array([1], dtype=f"M8[-1{unit}]")

    def test_compare_generic_nat(self):
        # regression tests for gh-6452
        assert_(np.datetime64('NaT') !=
                np.datetime64('2000') + np.timedelta64('NaT'))
        assert_(np.datetime64('NaT') != np.datetime64('NaT', 'us'))
        assert_(np.datetime64('NaT', 'us') != np.datetime64('NaT'))

    @pytest.mark.parametrize("size", [
        3, 21, 217, 1000])
    def test_datetime_nat_argsort_stability(self, size):
        # NaT < NaT should be False internally for
        # sort stability
        expected = np.arange(size)
        arr = np.tile(np.datetime64('NaT'), size)
        assert_equal(np.argsort(arr, kind='mergesort'), expected)

    @pytest.mark.parametrize("size", [
        3, 21, 217, 1000])
    def test_timedelta_nat_argsort_stability(self, size):
        # NaT < NaT should be False internally for
        # sort stability
        expected = np.arange(size)
        arr = np.tile(np.timedelta64('NaT'), size)
        assert_equal(np.argsort(arr, kind='mergesort'), expected)

    @pytest.mark.parametrize("arr, expected", [
        # the example provided in gh-12629
        (['NaT', 1, 2, 3],
         [1, 2, 3, 'NaT']),
        # multiple NaTs
        (['NaT', 9, 'NaT', -707],
         [-707, 9, 'NaT', 'NaT']),
        # this sort explores another code path for NaT
        ([1, -2, 3, 'NaT'],
         [-2, 1, 3, 'NaT']),
        # 2-D array
        ([[51, -220, 'NaT'],
          [-17, 'NaT', -90]],
         [[-220, 51, 'NaT'],
          [-90, -17, 'NaT']]),
        ])
    @pytest.mark.parametrize("dtype", [
        'M8[ns]', 'M8[us]',
        'm8[ns]', 'm8[us]'])
    def test_datetime_timedelta_sort_nat(self, arr, expected, dtype):
        # fix for gh-12629 and gh-15063; NaT sorting to end of array
        arr = np.array(arr, dtype=dtype)
        expected = np.array(expected, dtype=dtype)
        arr.sort()
        assert_equal(arr, expected)

    def test_datetime_scalar_construction(self):
        # Construct with different units
        assert_equal(np.datetime64('1950-03-12', 'D'),
                     np.datetime64('1950-03-12'))
        assert_equal(np.datetime64('1950-03-12T13', 's'),
                     np.datetime64('1950-03-12T13', 'm'))

        # Default construction means NaT
        assert_equal(np.datetime64(), np.datetime64('NaT'))

        # Some basic strings and repr
        assert_equal(str(np.datetime64('NaT')), 'NaT')
        assert_equal(repr(np.datetime64('NaT')),
                     "numpy.datetime64('NaT')")
        assert_equal(str(np.datetime64('2011-02')), '2011-02')
        assert_equal(repr(np.datetime64('2011-02')),
                     "numpy.datetime64('2011-02')")

        # None gets constructed as NaT
        assert_equal(np.datetime64(None), np.datetime64('NaT'))

        # Default construction of NaT is in generic units
        assert_equal(np.datetime64().dtype, np.dtype('M8'))
        assert_equal(np.datetime64('NaT').dtype, np.dtype('M8'))

        # Construction from integers requires a specified unit
        assert_raises(ValueError, np.datetime64, 17)

        # When constructing from a scalar or zero-dimensional array,
        # it either keeps the units or you can override them.
        a = np.datetime64('2000-03-18T16', 'h')
        b = np.array('2000-03-18T16', dtype='M8[h]')

        assert_equal(a.dtype, np.dtype('M8[h]'))
        assert_equal(b.dtype, np.dtype('M8[h]'))

        assert_equal(np.datetime64(a), a)
        assert_equal(np.datetime64(a).dtype, np.dtype('M8[h]'))

        assert_equal(np.datetime64(b), a)
        assert_equal(np.datetime64(b).dtype, np.dtype('M8[h]'))

        assert_equal(np.datetime64(a, 's'), a)
        assert_equal(np.datetime64(a, 's').dtype, np.dtype('M8[s]'))

        assert_equal(np.datetime64(b, 's'), a)
        assert_equal(np.datetime64(b, 's').dtype, np.dtype('M8[s]'))

        # Construction from datetime.date
        assert_equal(np.datetime64('1945-03-25'),
                     np.datetime64(datetime.date(1945, 3, 25)))
        assert_equal(np.datetime64('2045-03-25', 'D'),
                     np.datetime64(datetime.date(2045, 3, 25), 'D'))
        # Construction from datetime.datetime
        assert_equal(np.datetime64('1980-01-25T14:36:22.5'),
                     np.datetime64(datetime.datetime(1980, 1, 25,
                                                14, 36, 22, 500000)))

        # Construction with time units from a date is okay
        assert_equal(np.datetime64('1920-03-13', 'h'),
                     np.datetime64('1920-03-13T00'))
        assert_equal(np.datetime64('1920-03', 'm'),
                     np.datetime64('1920-03-01T00:00'))
        assert_equal(np.datetime64('1920', 's'),
                     np.datetime64('1920-01-01T00:00:00'))
        assert_equal(np.datetime64(datetime.date(2045, 3, 25), 'ms'),
                     np.datetime64('2045-03-25T00:00:00.000'))

        # Construction with date units from a datetime is also okay
        assert_equal(np.datetime64('1920-03-13T18', 'D'),
                     np.datetime64('1920-03-13'))
        assert_equal(np.datetime64('1920-03-13T18:33:12', 'M'),
                     np.datetime64('1920-03'))
        assert_equal(np.datetime64('1920-03-13T18:33:12.5', 'Y'),
                     np.datetime64('1920'))

    def test_datetime_scalar_construction_timezone(self):
        # verify that supplying an explicit timezone works, but is deprecated
        with assert_warns(DeprecationWarning):
            assert_equal(np.datetime64('2000-01-01T00Z'),
                         np.datetime64('2000-01-01T00'))
        with assert_warns(DeprecationWarning):
            assert_equal(np.datetime64('2000-01-01T00-08'),
                         np.datetime64('2000-01-01T08'))

    def test_datetime_array_find_type(self):
        dt = np.datetime64('1970-01-01', 'M')
        arr = np.array([dt])
        assert_equal(arr.dtype, np.dtype('M8[M]'))

        # at the moment, we don't automatically convert these to datetime64

        dt = datetime.date(1970, 1, 1)
        arr = np.array([dt])
        assert_equal(arr.dtype, np.dtype('O'))

        dt = datetime.datetime(1970, 1, 1, 12, 30, 40)
        arr = np.array([dt])
        assert_equal(arr.dtype, np.dtype('O'))

        # find "supertype" for non-dates and dates

        b = np.bool_(True)
        dm = np.datetime64('1970-01-01', 'M')
        d = datetime.date(1970, 1, 1)
        dt = datetime.datetime(1970, 1, 1, 12, 30, 40)

        arr = np.array([b, dm])
        assert_equal(arr.dtype, np.dtype('O'))

        arr = np.array([b, d])
        assert_equal(arr.dtype, np.dtype('O'))

        arr = np.array([b, dt])
        assert_equal(arr.dtype, np.dtype('O'))

        arr = np.array([d, d]).astype('datetime64')
        assert_equal(arr.dtype, np.dtype('M8[D]'))

        arr = np.array([dt, dt]).astype('datetime64')
        assert_equal(arr.dtype, np.dtype('M8[us]'))

    @pytest.mark.parametrize("unit", [
    # test all date / time units and use
    # "generic" to select generic unit
    ("Y"), ("M"), ("W"), ("D"), ("h"), ("m"),
    ("s"), ("ms"), ("us"), ("ns"), ("ps"),
    ("fs"), ("as"), ("generic") ])
    def test_timedelta_np_int_construction(self, unit):
        # regression test for gh-7617
        if unit != "generic":
            assert_equal(np.timedelta64(np.int64(123), unit),
                         np.timedelta64(123, unit))
        else:
            assert_equal(np.timedelta64(np.int64(123)),
                         np.timedelta64(123))

    def test_timedelta_scalar_construction(self):
        # Construct with different units
        assert_equal(np.timedelta64(7, 'D'),
                     np.timedelta64(1, 'W'))
        assert_equal(np.timedelta64(120, 's'),
                     np.timedelta64(2, 'm'))

        # Default construction means 0
        assert_equal(np.timedelta64(), np.timedelta64(0))

        # None gets constructed as NaT
        assert_equal(np.timedelta64(None), np.timedelta64('NaT'))

        # Some basic strings and repr
        assert_equal(str(np.timedelta64('NaT')), 'NaT')
        assert_equal(repr(np.timedelta64('NaT')),
                     "numpy.timedelta64('NaT')")
        assert_equal(str(np.timedelta64(3, 's')), '3 seconds')
        assert_equal(repr(np.timedelta64(-3, 's')),
                     "numpy.timedelta64(-3,'s')")
        assert_equal(repr(np.timedelta64(12)),
                     "numpy.timedelta64(12)")

        # Construction from an integer produces generic units
        assert_equal(np.timedelta64(12).dtype, np.dtype('m8'))

        # When constructing from a scalar or zero-dimensional array,
        # it either keeps the units or you can override them.
        a = np.timedelta64(2, 'h')
        b = np.array(2, dtype='m8[h]')

        assert_equal(a.dtype, np.dtype('m8[h]'))
        assert_equal(b.dtype, np.dtype('m8[h]'))

        assert_equal(np.timedelta64(a), a)
        assert_equal(np.timedelta64(a).dtype, np.dtype('m8[h]'))

        assert_equal(np.timedelta64(b), a)
        assert_equal(np.timedelta64(b).dtype, np.dtype('m8[h]'))

        assert_equal(np.timedelta64(a, 's'), a)
        assert_equal(np.timedelta64(a, 's').dtype, np.dtype('m8[s]'))

        assert_equal(np.timedelta64(b, 's'), a)
        assert_equal(np.timedelta64(b, 's').dtype, np.dtype('m8[s]'))

        # Construction from datetime.timedelta
        assert_equal(np.timedelta64(5, 'D'),
                     np.timedelta64(datetime.timedelta(days=5)))
        assert_equal(np.timedelta64(102347621, 's'),
                     np.timedelta64(datetime.timedelta(seconds=102347621)))
        assert_equal(np.timedelta64(-10234760000, 'us'),
                     np.timedelta64(datetime.timedelta(
                                            microseconds=-10234760000)))
        assert_equal(np.timedelta64(10234760000, 'us'),
                     np.timedelta64(datetime.timedelta(
                                            microseconds=10234760000)))
        assert_equal(np.timedelta64(1023476, 'ms'),
                     np.timedelta64(datetime.timedelta(milliseconds=1023476)))
        assert_equal(np.timedelta64(10, 'm'),
                     np.timedelta64(datetime.timedelta(minutes=10)))
        assert_equal(np.timedelta64(281, 'h'),
                     np.timedelta64(datetime.timedelta(hours=281)))
        assert_equal(np.timedelta64(28, 'W'),
                     np.timedelta64(datetime.timedelta(weeks=28)))

        # Cannot construct across nonlinear time unit boundaries
        a = np.timedelta64(3, 's')
        assert_raises(TypeError, np.timedelta64, a, 'M')
        assert_raises(TypeError, np.timedelta64, a, 'Y')
        a = np.timedelta64(6, 'M')
        assert_raises(TypeError, np.timedelta64, a, 'D')
        assert_raises(TypeError, np.timedelta64, a, 'h')
        a = np.timedelta64(1, 'Y')
        assert_raises(TypeError, np.timedelta64, a, 'D')
        assert_raises(TypeError, np.timedelta64, a, 'm')
        a = datetime.timedelta(seconds=3)
        assert_raises(TypeError, np.timedelta64, a, 'M')
        assert_raises(TypeError, np.timedelta64, a, 'Y')
        a = datetime.timedelta(weeks=3)
        assert_raises(TypeError, np.timedelta64, a, 'M')
        assert_raises(TypeError, np.timedelta64, a, 'Y')
        a = datetime.timedelta()
        assert_raises(TypeError, np.timedelta64, a, 'M')
        assert_raises(TypeError, np.timedelta64, a, 'Y')

    def test_timedelta_object_array_conversion(self):
        # Regression test for gh-11096
        inputs = [datetime.timedelta(28),
                  datetime.timedelta(30),
                  datetime.timedelta(31)]
        expected = np.array([28, 30, 31], dtype='timedelta64[D]')
        actual = np.array(inputs, dtype='timedelta64[D]')
        assert_equal(expected, actual)

    def test_timedelta_0_dim_object_array_conversion(self):
        # Regression test for gh-11151
        test = np.array(datetime.timedelta(seconds=20))
        actual = test.astype(np.timedelta64)
        # expected value from the array constructor workaround
        # described in above issue
        expected = np.array(datetime.timedelta(seconds=20),
                            np.timedelta64)
        assert_equal(actual, expected)

    def test_timedelta_nat_format(self):
        # gh-17552
        assert_equal('NaT', '{0}'.format(np.timedelta64('nat')))

    def test_timedelta_scalar_construction_units(self):
        # String construction detecting units
        assert_equal(np.datetime64('2010').dtype,
                     np.dtype('M8[Y]'))
        assert_equal(np.datetime64('2010-03').dtype,
                     np.dtype('M8[M]'))
        assert_equal(np.datetime64('2010-03-12').dtype,
                     np.dtype('M8[D]'))
        assert_equal(np.datetime64('2010-03-12T17').dtype,
                     np.dtype('M8[h]'))
        assert_equal(np.datetime64('2010-03-12T17:15').dtype,
                     np.dtype('M8[m]'))
        assert_equal(np.datetime64('2010-03-12T17:15:08').dtype,
                     np.dtype('M8[s]'))

        assert_equal(np.datetime64('2010-03-12T17:15:08.1').dtype,
                     np.dtype('M8[ms]'))
        assert_equal(np.datetime64('2010-03-12T17:15:08.12').dtype,
                     np.dtype('M8[ms]'))
        assert_equal(np.datetime64('2010-03-12T17:15:08.123').dtype,
                     np.dtype('M8[ms]'))

        assert_equal(np.datetime64('2010-03-12T17:15:08.1234').dtype,
                     np.dtype('M8[us]'))
        assert_equal(np.datetime64('2010-03-12T17:15:08.12345').dtype,
                     np.dtype('M8[us]'))
        assert_equal(np.datetime64('2010-03-12T17:15:08.123456').dtype,
                     np.dtype('M8[us]'))

        assert_equal(np.datetime64('1970-01-01T00:00:02.1234567').dtype,
                     np.dtype('M8[ns]'))
        assert_equal(np.datetime64('1970-01-01T00:00:02.12345678').dtype,
                     np.dtype('M8[ns]'))
        assert_equal(np.datetime64('1970-01-01T00:00:02.123456789').dtype,
                     np.dtype('M8[ns]'))

        assert_equal(np.datetime64('1970-01-01T00:00:02.1234567890').dtype,
                     np.dtype('M8[ps]'))
        assert_equal(np.datetime64('1970-01-01T00:00:02.12345678901').dtype,
                     np.dtype('M8[ps]'))
        assert_equal(np.datetime64('1970-01-01T00:00:02.123456789012').dtype,
                     np.dtype('M8[ps]'))

        assert_equal(np.datetime64(
                     '1970-01-01T00:00:02.1234567890123').dtype,
                     np.dtype('M8[fs]'))
        assert_equal(np.datetime64(
                     '1970-01-01T00:00:02.12345678901234').dtype,
                     np.dtype('M8[fs]'))
        assert_equal(np.datetime64(
                     '1970-01-01T00:00:02.123456789012345').dtype,
                     np.dtype('M8[fs]'))

        assert_equal(np.datetime64(
                    '1970-01-01T00:00:02.1234567890123456').dtype,
                     np.dtype('M8[as]'))
        assert_equal(np.datetime64(
                    '1970-01-01T00:00:02.12345678901234567').dtype,
                     np.dtype('M8[as]'))
        assert_equal(np.datetime64(
                    '1970-01-01T00:00:02.123456789012345678').dtype,
                     np.dtype('M8[as]'))

        # Python date object
        assert_equal(np.datetime64(datetime.date(2010, 4, 16)).dtype,
                     np.dtype('M8[D]'))

        # Python datetime object
        assert_equal(np.datetime64(
                        datetime.datetime(2010, 4, 16, 13, 45, 18)).dtype,
                     np.dtype('M8[us]'))

        # 'today' special value
        assert_equal(np.datetime64('today').dtype,
                     np.dtype('M8[D]'))

        # 'now' special value
        assert_equal(np.datetime64('now').dtype,
                     np.dtype('M8[s]'))

    def test_datetime_nat_casting(self):
        a = np.array('NaT', dtype='M8[D]')
        b = np.datetime64('NaT', '[D]')

        # Arrays
        assert_equal(a.astype('M8[s]'), np.array('NaT', dtype='M8[s]'))
        assert_equal(a.astype('M8[ms]'), np.array('NaT', dtype='M8[ms]'))
        assert_equal(a.astype('M8[M]'), np.array('NaT', dtype='M8[M]'))
        assert_equal(a.astype('M8[Y]'), np.array('NaT', dtype='M8[Y]'))
        assert_equal(a.astype('M8[W]'), np.array('NaT', dtype='M8[W]'))

        # Scalars -> Scalars
        assert_equal(np.datetime64(b, '[s]'), np.datetime64('NaT', '[s]'))
        assert_equal(np.datetime64(b, '[ms]'), np.datetime64('NaT', '[ms]'))
        assert_equal(np.datetime64(b, '[M]'), np.datetime64('NaT', '[M]'))
        assert_equal(np.datetime64(b, '[Y]'), np.datetime64('NaT', '[Y]'))
        assert_equal(np.datetime64(b, '[W]'), np.datetime64('NaT', '[W]'))

        # Arrays -> Scalars
        assert_equal(np.datetime64(a, '[s]'), np.datetime64('NaT', '[s]'))
        assert_equal(np.datetime64(a, '[ms]'), np.datetime64('NaT', '[ms]'))
        assert_equal(np.datetime64(a, '[M]'), np.datetime64('NaT', '[M]'))
        assert_equal(np.datetime64(a, '[Y]'), np.datetime64('NaT', '[Y]'))
        assert_equal(np.datetime64(a, '[W]'), np.datetime64('NaT', '[W]'))

        # NaN -> NaT
        nan = np.array([np.nan] * 8)
        fnan = nan.astype('f')
        lnan = nan.astype('g')
        cnan = nan.astype('D')
        cfnan = nan.astype('F')
        clnan = nan.astype('G')

        nat = np.array([np.datetime64('NaT')] * 8)
        assert_equal(nan.astype('M8[ns]'), nat)
        assert_equal(fnan.astype('M8[ns]'), nat)
        assert_equal(lnan.astype('M8[ns]'), nat)
        assert_equal(cnan.astype('M8[ns]'), nat)
        assert_equal(cfnan.astype('M8[ns]'), nat)
        assert_equal(clnan.astype('M8[ns]'), nat)

        nat = np.array([np.timedelta64('NaT')] * 8)
        assert_equal(nan.astype('timedelta64[ns]'), nat)
        assert_equal(fnan.astype('timedelta64[ns]'), nat)
        assert_equal(lnan.astype('timedelta64[ns]'), nat)
        assert_equal(cnan.astype('timedelta64[ns]'), nat)
        assert_equal(cfnan.astype('timedelta64[ns]'), nat)
        assert_equal(clnan.astype('timedelta64[ns]'), nat)

    def test_days_creation(self):
        assert_equal(np.array('1599', dtype='M8[D]').astype('i8'),
                (1600-1970)*365 - (1972-1600)/4 + 3 - 365)
        assert_equal(np.array('1600', dtype='M8[D]').astype('i8'),
                (1600-1970)*365 - (1972-1600)/4 + 3)
        assert_equal(np.array('1601', dtype='M8[D]').astype('i8'),
                (1600-1970)*365 - (1972-1600)/4 + 3 + 366)
        assert_equal(np.array('1900', dtype='M8[D]').astype('i8'),
                (1900-1970)*365 - (1970-1900)//4)
        assert_equal(np.array('1901', dtype='M8[D]').astype('i8'),
                (1900-1970)*365 - (1970-1900)//4 + 365)
        assert_equal(np.array('1967', dtype='M8[D]').astype('i8'), -3*365 - 1)
        assert_equal(np.array('1968', dtype='M8[D]').astype('i8'), -2*365 - 1)
        assert_equal(np.array('1969', dtype='M8[D]').astype('i8'), -1*365)
        assert_equal(np.array('1970', dtype='M8[D]').astype('i8'), 0*365)
        assert_equal(np.array('1971', dtype='M8[D]').astype('i8'), 1*365)
        assert_equal(np.array('1972', dtype='M8[D]').astype('i8'), 2*365)
        assert_equal(np.array('1973', dtype='M8[D]').astype('i8'), 3*365 + 1)
        assert_equal(np.array('1974', dtype='M8[D]').astype('i8'), 4*365 + 1)
        assert_equal(np.array('2000', dtype='M8[D]').astype('i8'),
                 (2000 - 1970)*365 + (2000 - 1972)//4)
        assert_equal(np.array('2001', dtype='M8[D]').astype('i8'),
                 (2000 - 1970)*365 + (2000 - 1972)//4 + 366)
        assert_equal(np.array('2400', dtype='M8[D]').astype('i8'),
                 (2400 - 1970)*365 + (2400 - 1972)//4 - 3)
        assert_equal(np.array('2401', dtype='M8[D]').astype('i8'),
                 (2400 - 1970)*365 + (2400 - 1972)//4 - 3 + 366)

        assert_equal(np.array('1600-02-29', dtype='M8[D]').astype('i8'),
                (1600-1970)*365 - (1972-1600)//4 + 3 + 31 + 28)
        assert_equal(np.array('1600-03-01', dtype='M8[D]').astype('i8'),
                (1600-1970)*365 - (1972-1600)//4 + 3 + 31 + 29)
        assert_equal(np.array('2000-02-29', dtype='M8[D]').astype('i8'),
                 (2000 - 1970)*365 + (2000 - 1972)//4 + 31 + 28)
        assert_equal(np.array('2000-03-01', dtype='M8[D]').astype('i8'),
                 (2000 - 1970)*365 + (2000 - 1972)//4 + 31 + 29)
        assert_equal(np.array('2001-03-22', dtype='M8[D]').astype('i8'),
                 (2000 - 1970)*365 + (2000 - 1972)//4 + 366 + 31 + 28 + 21)

    def test_days_to_pydate(self):
        assert_equal(np.array('1599', dtype='M8[D]').astype('O'),
                    datetime.date(1599, 1, 1))
        assert_equal(np.array('1600', dtype='M8[D]').astype('O'),
                    datetime.date(1600, 1, 1))
        assert_equal(np.array('1601', dtype='M8[D]').astype('O'),
                    datetime.date(1601, 1, 1))
        assert_equal(np.array('1900', dtype='M8[D]').astype('O'),
                    datetime.date(1900, 1, 1))
        assert_equal(np.array('1901', dtype='M8[D]').astype('O'),
                    datetime.date(1901, 1, 1))
        assert_equal(np.array('2000', dtype='M8[D]').astype('O'),
                    datetime.date(2000, 1, 1))
        assert_equal(np.array('2001', dtype='M8[D]').astype('O'),
                    datetime.date(2001, 1, 1))
        assert_equal(np.array('1600-02-29', dtype='M8[D]').astype('O'),
                    datetime.date(1600, 2, 29))
        assert_equal(np.array('1600-03-01', dtype='M8[D]').astype('O'),
                    datetime.date(1600, 3, 1))
        assert_equal(np.array('2001-03-22', dtype='M8[D]').astype('O'),
                    datetime.date(2001, 3, 22))

    def test_dtype_comparison(self):
        assert_(not (np.dtype('M8[us]') == np.dtype('M8[ms]')))
        assert_(np.dtype('M8[us]') != np.dtype('M8[ms]'))
        assert_(np.dtype('M8[2D]') != np.dtype('M8[D]'))
        assert_(np.dtype('M8[D]') != np.dtype('M8[2D]'))

    def test_pydatetime_creation(self):
        a = np.array(['1960-03-12', datetime.date(1960, 3, 12)], dtype='M8[D]')
        assert_equal(a[0], a[1])
        a = np.array(['1999-12-31', datetime.date(1999, 12, 31)], dtype='M8[D]')
        assert_equal(a[0], a[1])
        a = np.array(['2000-01-01', datetime.date(2000, 1, 1)], dtype='M8[D]')
        assert_equal(a[0], a[1])
        # Will fail if the date changes during the exact right moment
        a = np.array(['today', datetime.date.today()], dtype='M8[D]')
        assert_equal(a[0], a[1])
        # datetime.datetime.now() returns local time, not UTC
        #a = np.array(['now', datetime.datetime.now()], dtype='M8[s]')
        #assert_equal(a[0], a[1])

        # we can give a datetime.date time units
        assert_equal(np.array(datetime.date(1960, 3, 12), dtype='M8[s]'),
                     np.array(np.datetime64('1960-03-12T00:00:00')))

    def test_datetime_string_conversion(self):
        a = ['2011-03-16', '1920-01-01', '2013-05-19']
        str_a = np.array(a, dtype='S')
        uni_a = np.array(a, dtype='U')
        dt_a = np.array(a, dtype='M')

        # String to datetime
        assert_equal(dt_a, str_a.astype('M'))
        assert_equal(dt_a.dtype, str_a.astype('M').dtype)
        dt_b = np.empty_like(dt_a)
        dt_b[...] = str_a
        assert_equal(dt_a, dt_b)

        # Datetime to string
        assert_equal(str_a, dt_a.astype('S0'))
        str_b = np.empty_like(str_a)
        str_b[...] = dt_a
        assert_equal(str_a, str_b)

        # Unicode to datetime
        assert_equal(dt_a, uni_a.astype('M'))
        assert_equal(dt_a.dtype, uni_a.astype('M').dtype)
        dt_b = np.empty_like(dt_a)
        dt_b[...] = uni_a
        assert_equal(dt_a, dt_b)

        # Datetime to unicode
        assert_equal(uni_a, dt_a.astype('U'))
        uni_b = np.empty_like(uni_a)
        uni_b[...] = dt_a
        assert_equal(uni_a, uni_b)

        # Datetime to long string - gh-9712
        assert_equal(str_a, dt_a.astype((np.bytes_, 128)))
        str_b = np.empty(str_a.shape, dtype=(np.bytes_, 128))
        str_b[...] = dt_a
        assert_equal(str_a, str_b)

    @pytest.mark.parametrize("time_dtype", ["m8[D]", "M8[Y]"])
    def test_time_byteswapping(self, time_dtype):
        times = np.array(["2017", "NaT"], dtype=time_dtype)
        times_swapped = times.astype(times.dtype.newbyteorder())
        assert_array_equal(times, times_swapped)

        unswapped = times_swapped.view(np.int64).newbyteorder()
        assert_array_equal(unswapped, times.view(np.int64))

    @pytest.mark.parametrize(["time1", "time2"],
            [("M8[s]", "M8[D]"), ("m8[s]", "m8[ns]")])
    def test_time_byteswapped_cast(self, time1, time2):
        dtype1 = np.dtype(time1)
        dtype2 = np.dtype(time2)
        times = np.array(["2017", "NaT"], dtype=dtype1)
        expected = times.astype(dtype2)

        # Test that every byte-swapping combination also returns the same
        # results (previous tests check that this comparison works fine).
        res = times.astype(dtype1.newbyteorder()).astype(dtype2)
        assert_array_equal(res, expected)
        res = times.astype(dtype2.newbyteorder())
        assert_array_equal(res, expected)
        res = times.astype(dtype1.newbyteorder()).astype(dtype2.newbyteorder())
        assert_array_equal(res, expected)

    @pytest.mark.parametrize("time_dtype", ["m8[D]", "M8[Y]"])
    @pytest.mark.parametrize("str_dtype", ["U", "S"])
    def test_datetime_conversions_byteorders(self, str_dtype, time_dtype):
        times = np.array(["2017", "NaT"], dtype=time_dtype)
        # Unfortunately, timedelta does not roundtrip:
        from_strings = np.array(["2017", "NaT"], dtype=str_dtype)
        to_strings = times.astype(str_dtype)  # assume this is correct

        # Check that conversion from times to string works if src is swapped:
        times_swapped = times.astype(times.dtype.newbyteorder())
        res = times_swapped.astype(str_dtype)
        assert_array_equal(res, to_strings)
        # And also if both are swapped:
        res = times_swapped.astype(to_strings.dtype.newbyteorder())
        assert_array_equal(res, to_strings)
        # only destination is swapped:
        res = times.astype(to_strings.dtype.newbyteorder())
        assert_array_equal(res, to_strings)

        # Check that conversion from string to times works if src is swapped:
        from_strings_swapped = from_strings.astype(
                from_strings.dtype.newbyteorder())
        res = from_strings_swapped.astype(time_dtype)
        assert_array_equal(res, times)
        # And if both are swapped:
        res = from_strings_swapped.astype(times.dtype.newbyteorder())
        assert_array_equal(res, times)
        # Only destination is swapped:
        res = from_strings.astype(times.dtype.newbyteorder())
        assert_array_equal(res, times)

    def test_datetime_array_str(self):
        a = np.array(['2011-03-16', '1920-01-01', '2013-05-19'], dtype='M')
        assert_equal(str(a), "['2011-03-16' '1920-01-01' '2013-05-19']")

        a = np.array(['2011-03-16T13:55', '1920-01-01T03:12'], dtype='M')
        assert_equal(np.array2string(a, separator=', ',
                    formatter={'datetime': lambda x:
                            "'%s'" % np.datetime_as_string(x, timezone='UTC')}),
                     "['2011-03-16T13:55Z', '1920-01-01T03:12Z']")

        # Check that one NaT doesn't corrupt subsequent entries
        a = np.array(['2010', 'NaT', '2030']).astype('M')
        assert_equal(str(a), "['2010'  'NaT' '2030']")

    def test_timedelta_array_str(self):
        a = np.array([-1, 0, 100], dtype='m')
        assert_equal(str(a), "[ -1   0 100]")
        a = np.array(['NaT', 'NaT'], dtype='m')
        assert_equal(str(a), "['NaT' 'NaT']")
        # Check right-alignment with NaTs
        a = np.array([-1, 'NaT', 0], dtype='m')
        assert_equal(str(a), "[   -1 'NaT'     0]")
        a = np.array([-1, 'NaT', 1234567], dtype='m')
        assert_equal(str(a), "[     -1   'NaT' 1234567]")

        # Test with other byteorder:
        a = np.array([-1, 'NaT', 1234567], dtype='>m')
        assert_equal(str(a), "[     -1   'NaT' 1234567]")
        a = np.array([-1, 'NaT', 1234567], dtype='<m')
        assert_equal(str(a), "[     -1   'NaT' 1234567]")

    def test_pickle(self):
        # Check that pickle roundtripping works
        for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
            dt = np.dtype('M8[7D]')
            assert_equal(pickle.loads(pickle.dumps(dt, protocol=proto)), dt)
            dt = np.dtype('M8[W]')
            assert_equal(pickle.loads(pickle.dumps(dt, protocol=proto)), dt)
            scalar = np.datetime64('2016-01-01T00:00:00.000000000')
            assert_equal(pickle.loads(pickle.dumps(scalar, protocol=proto)),
                         scalar)
            delta = scalar - np.datetime64('2015-01-01T00:00:00.000000000')
            assert_equal(pickle.loads(pickle.dumps(delta, protocol=proto)),
                         delta)

        # Check that loading pickles from 1.6 works
        pkl = b"cnumpy\ndtype\np0\n(S'M8'\np1\nI0\nI1\ntp2\nRp3\n" + \
              b"(I4\nS'<'\np4\nNNNI-1\nI-1\nI0\n((dp5\n(S'D'\np6\n" + \
              b"I7\nI1\nI1\ntp7\ntp8\ntp9\nb."
        assert_equal(pickle.loads(pkl), np.dtype('<M8[7D]'))
        pkl = b"cnumpy\ndtype\np0\n(S'M8'\np1\nI0\nI1\ntp2\nRp3\n" + \
              b"(I4\nS'<'\np4\nNNNI-1\nI-1\nI0\n((dp5\n(S'W'\np6\n" + \
              b"I1\nI1\nI1\ntp7\ntp8\ntp9\nb."
        assert_equal(pickle.loads(pkl), np.dtype('<M8[W]'))
        pkl = b"cnumpy\ndtype\np0\n(S'M8'\np1\nI0\nI1\ntp2\nRp3\n" + \
              b"(I4\nS'>'\np4\nNNNI-1\nI-1\nI0\n((dp5\n(S'us'\np6\n" + \
              b"I1\nI1\nI1\ntp7\ntp8\ntp9\nb."
        assert_equal(pickle.loads(pkl), np.dtype('>M8[us]'))

    def test_setstate(self):
        "Verify that datetime dtype __setstate__ can handle bad arguments"
        dt = np.dtype('>M8[us]')
        assert_raises(ValueError, dt.__setstate__, (4, '>', None, None, None, -1, -1, 0, 1))
        assert_(dt.__reduce__()[2] == np.dtype('>M8[us]').__reduce__()[2])
        assert_raises(TypeError, dt.__setstate__, (4, '>', None, None, None, -1, -1, 0, ({}, 'xxx')))
        assert_(dt.__reduce__()[2] == np.dtype('>M8[us]').__reduce__()[2])

    def test_dtype_promotion(self):
        # datetime <op> datetime computes the metadata gcd
        # timedelta <op> timedelta computes the metadata gcd
        for mM in ['m', 'M']:
            assert_equal(
                np.promote_types(np.dtype(mM+'8[2Y]'), np.dtype(mM+'8[2Y]')),
                np.dtype(mM+'8[2Y]'))
            assert_equal(
                np.promote_types(np.dtype(mM+'8[12Y]'), np.dtype(mM+'8[15Y]')),
                np.dtype(mM+'8[3Y]'))
            assert_equal(
                np.promote_types(np.dtype(mM+'8[62M]'), np.dtype(mM+'8[24M]')),
                np.dtype(mM+'8[2M]'))
            assert_equal(
                np.promote_types(np.dtype(mM+'8[1W]'), np.dtype(mM+'8[2D]')),
                np.dtype(mM+'8[1D]'))
            assert_equal(
                np.promote_types(np.dtype(mM+'8[W]'), np.dtype(mM+'8[13s]')),
                np.dtype(mM+'8[s]'))
            assert_equal(
                np.promote_types(np.dtype(mM+'8[13W]'), np.dtype(mM+'8[49s]')),
                np.dtype(mM+'8[7s]'))
        # timedelta <op> timedelta raises when there is no reasonable gcd
        assert_raises(TypeError, np.promote_types,
                            np.dtype('m8[Y]'), np.dtype('m8[D]'))
        assert_raises(TypeError, np.promote_types,
                            np.dtype('m8[M]'), np.dtype('m8[W]'))
        # timedelta and float cannot be safely cast with each other
        assert_raises(TypeError, np.promote_types, "float32", "m8")
        assert_raises(TypeError, np.promote_types, "m8", "float32")
        assert_raises(TypeError, np.promote_types, "uint64", "m8")
        assert_raises(TypeError, np.promote_types, "m8", "uint64")

        # timedelta <op> timedelta may overflow with big unit ranges
        assert_raises(OverflowError, np.promote_types,
                            np.dtype('m8[W]'), np.dtype('m8[fs]'))
        assert_raises(OverflowError, np.promote_types,
                            np.dtype('m8[s]'), np.dtype('m8[as]'))

    def test_cast_overflow(self):
        # gh-4486
        def cast():
            numpy.datetime64("1971-01-01 00:00:00.000000000000000").astype("<M8[D]")
        assert_raises(OverflowError, cast)

        def cast2():
            numpy.datetime64("2014").astype("<M8[fs]")
        assert_raises(OverflowError, cast2)

    def test_pyobject_roundtrip(self):
        # All datetime types should be able to roundtrip through object
        a = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0,
                      -1020040340, -2942398, -1, 0, 1, 234523453, 1199164176],
                                                        dtype=np.int64)
        # With date units
        for unit in ['M8[D]', 'M8[W]', 'M8[M]', 'M8[Y]']:
            b = a.copy().view(dtype=unit)
            b[0] = '-0001-01-01'
            b[1] = '-0001-12-31'
            b[2] = '0000-01-01'
            b[3] = '0001-01-01'
            b[4] = '1969-12-31'
            b[5] = '1970-01-01'
            b[6] = '9999-12-31'
            b[7] = '10000-01-01'
            b[8] = 'NaT'

            assert_equal(b.astype(object).astype(unit), b,
                            "Error roundtripping unit %s" % unit)
        # With time units
        for unit in ['M8[as]', 'M8[16fs]', 'M8[ps]', 'M8[us]',
                     'M8[300as]', 'M8[20us]']:
            b = a.copy().view(dtype=unit)
            b[0] = '-0001-01-01T00'
            b[1] = '-0001-12-31T00'
            b[2] = '0000-01-01T00'
            b[3] = '0001-01-01T00'
            b[4] = '1969-12-31T23:59:59.999999'
            b[5] = '1970-01-01T00'
            b[6] = '9999-12-31T23:59:59.999999'
            b[7] = '10000-01-01T00'
            b[8] = 'NaT'

            assert_equal(b.astype(object).astype(unit), b,
                            "Error roundtripping unit %s" % unit)

    def test_month_truncation(self):
        # Make sure that months are truncating correctly
        assert_equal(np.array('1945-03-01', dtype='M8[M]'),
                     np.array('1945-03-31', dtype='M8[M]'))
        assert_equal(np.array('1969-11-01', dtype='M8[M]'),
             np.array('1969-11-30T23:59:59.99999', dtype='M').astype('M8[M]'))
        assert_equal(np.array('1969-12-01', dtype='M8[M]'),
             np.array('1969-12-31T23:59:59.99999', dtype='M').astype('M8[M]'))
        assert_equal(np.array('1970-01-01', dtype='M8[M]'),
             np.array('1970-01-31T23:59:59.99999', dtype='M').astype('M8[M]'))
        assert_equal(np.array('1980-02-01', dtype='M8[M]'),
             np.array('1980-02-29T23:59:59.99999', dtype='M').astype('M8[M]'))

    def test_different_unit_comparison(self):
        # Check some years with date units
        for unit1 in ['Y', 'M', 'D']:
            dt1 = np.dtype('M8[%s]' % unit1)
            for unit2 in ['Y', 'M', 'D']:
                dt2 = np.dtype('M8[%s]' % unit2)
                assert_equal(np.array('1945', dtype=dt1),
                             np.array('1945', dtype=dt2))
                assert_equal(np.array('1970', dtype=dt1),
                             np.array('1970', dtype=dt2))
                assert_equal(np.array('9999', dtype=dt1),
                             np.array('9999', dtype=dt2))
                assert_equal(np.array('10000', dtype=dt1),
                             np.array('10000-01-01', dtype=dt2))
                assert_equal(np.datetime64('1945', unit1),
                             np.datetime64('1945', unit2))
                assert_equal(np.datetime64('1970', unit1),
                             np.datetime64('1970', unit2))
                assert_equal(np.datetime64('9999', unit1),
                             np.datetime64('9999', unit2))
                assert_equal(np.datetime64('10000', unit1),
                             np.datetime64('10000-01-01', unit2))
        # Check some datetimes with time units
        for unit1 in ['6h', 'h', 'm', 's', '10ms', 'ms', 'us']:
            dt1 = np.dtype('M8[%s]' % unit1)
            for unit2 in ['h', 'm', 's', 'ms', 'us']:
                dt2 = np.dtype('M8[%s]' % unit2)
                assert_equal(np.array('1945-03-12T18', dtype=dt1),
                             np.array('1945-03-12T18', dtype=dt2))
                assert_equal(np.array('1970-03-12T18', dtype=dt1),
                             np.array('1970-03-12T18', dtype=dt2))
                assert_equal(np.array('9999-03-12T18', dtype=dt1),
                             np.array('9999-03-12T18', dtype=dt2))
                assert_equal(np.array('10000-01-01T00', dtype=dt1),
                             np.array('10000-01-01T00', dtype=dt2))
                assert_equal(np.datetime64('1945-03-12T18', unit1),
                             np.datetime64('1945-03-12T18', unit2))
                assert_equal(np.datetime64('1970-03-12T18', unit1),
                             np.datetime64('1970-03-12T18', unit2))
                assert_equal(np.datetime64('9999-03-12T18', unit1),
                             np.datetime64('9999-03-12T18', unit2))
                assert_equal(np.datetime64('10000-01-01T00', unit1),
                             np.datetime64('10000-01-01T00', unit2))
        # Check some days with units that won't overflow
        for unit1 in ['D', '12h', 'h', 'm', 's', '4s', 'ms', 'us']:
            dt1 = np.dtype('M8[%s]' % unit1)
            for unit2 in ['D', 'h', 'm', 's', 'ms', 'us']:
                dt2 = np.dtype('M8[%s]' % unit2)
                assert_(np.equal(np.array('1932-02-17', dtype='M').astype(dt1),
                     np.array('1932-02-17T00:00:00', dtype='M').astype(dt2),
                     casting='unsafe'))
                assert_(np.equal(np.array('10000-04-27', dtype='M').astype(dt1),
                     np.array('10000-04-27T00:00:00', dtype='M').astype(dt2),
                     casting='unsafe'))

        # Shouldn't be able to compare datetime and timedelta
        a = np.array('2012-12-21', dtype='M8[D]')
        b = np.array(3, dtype='m8[D]')
        assert_raises(TypeError, np.less, a, b)
        # not even if "unsafe"
        assert_raises(TypeError, np.less, a, b, casting='unsafe')

    def test_datetime_like(self):
        a = np.array([3], dtype='m8[4D]')
        b = np.array(['2012-12-21'], dtype='M8[D]')

        assert_equal(np.ones_like(a).dtype, a.dtype)
        assert_equal(np.zeros_like(a).dtype, a.dtype)
        assert_equal(np.empty_like(a).dtype, a.dtype)
        assert_equal(np.ones_like(b).dtype, b.dtype)
        assert_equal(np.zeros_like(b).dtype, b.dtype)
        assert_equal(np.empty_like(b).dtype, b.dtype)

    def test_datetime_unary(self):
        for tda, tdb, tdzero, tdone, tdmone in \
                [
                 # One-dimensional arrays
                 (np.array([3], dtype='m8[D]'),
                  np.array([-3], dtype='m8[D]'),
                  np.array([0], dtype='m8[D]'),
                  np.array([1], dtype='m8[D]'),
                  np.array([-1], dtype='m8[D]')),
                 # NumPy scalars
                 (np.timedelta64(3, '[D]'),
                  np.timedelta64(-3, '[D]'),
                  np.timedelta64(0, '[D]'),
                  np.timedelta64(1, '[D]'),
                  np.timedelta64(-1, '[D]'))]:
            # negative ufunc
            assert_equal(-tdb, tda)
            assert_equal((-tdb).dtype, tda.dtype)
            assert_equal(np.negative(tdb), tda)
            assert_equal(np.negative(tdb).dtype, tda.dtype)

            # positive ufunc
            assert_equal(np.positive(tda), tda)
            assert_equal(np.positive(tda).dtype, tda.dtype)
            assert_equal(np.positive(tdb), tdb)
            assert_equal(np.positive(tdb).dtype, tdb.dtype)

            # absolute ufunc
            assert_equal(np.absolute(tdb), tda)
            assert_equal(np.absolute(tdb).dtype, tda.dtype)

            # sign ufunc
            assert_equal(np.sign(tda), tdone)
            assert_equal(np.sign(tdb), tdmone)
            assert_equal(np.sign(tdzero), tdzero)
            assert_equal(np.sign(tda).dtype, tda.dtype)

            # The ufuncs always produce native-endian results
            assert_

    def test_datetime_add(self):
        for dta, dtb, dtc, dtnat, tda, tdb, tdc in \
                    [
                     # One-dimensional arrays
                     (np.array(['2012-12-21'], dtype='M8[D]'),
                      np.array(['2012-12-24'], dtype='M8[D]'),
                      np.array(['2012-12-21T11'], dtype='M8[h]'),
                      np.array(['NaT'], dtype='M8[D]'),
                      np.array([3], dtype='m8[D]'),
                      np.array([11], dtype='m8[h]'),
                      np.array([3*24 + 11], dtype='m8[h]')),
                     # NumPy scalars
                     (np.datetime64('2012-12-21', '[D]'),
                      np.datetime64('2012-12-24', '[D]'),
                      np.datetime64('2012-12-21T11', '[h]'),
                      np.datetime64('NaT', '[D]'),
                      np.timedelta64(3, '[D]'),
                      np.timedelta64(11, '[h]'),
                      np.timedelta64(3*24 + 11, '[h]'))]:
            # m8 + m8
            assert_equal(tda + tdb, tdc)
            assert_equal((tda + tdb).dtype, np.dtype('m8[h]'))
            # m8 + bool
            assert_equal(tdb + True, tdb + 1)
            assert_equal((tdb + True).dtype, np.dtype('m8[h]'))
            # m8 + int
            assert_equal(tdb + 3*24, tdc)
            assert_equal((tdb + 3*24).dtype, np.dtype('m8[h]'))
            # bool + m8
            assert_equal(False + tdb, tdb)
            assert_equal((False + tdb).dtype, np.dtype('m8[h]'))
            # int + m8
            assert_equal(3*24 + tdb, tdc)
            assert_equal((3*24 + tdb).dtype, np.dtype('m8[h]'))
            # M8 + bool
            assert_equal(dta + True, dta + 1)
            assert_equal(dtnat + True, dtnat)
            assert_equal((dta + True).dtype, np.dtype('M8[D]'))
            # M8 + int
            assert_equal(dta + 3, dtb)
            assert_equal(dtnat + 3, dtnat)
            assert_equal((dta + 3).dtype, np.dtype('M8[D]'))
            # bool + M8
            assert_equal(False + dta, dta)
            assert_equal(False + dtnat, dtnat)
            assert_equal((False + dta).dtype, np.dtype('M8[D]'))
            # int + M8
            assert_equal(3 + dta, dtb)
            assert_equal(3 + dtnat, dtnat)
            assert_equal((3 + dta).dtype, np.dtype('M8[D]'))
            # M8 + m8
            assert_equal(dta + tda, dtb)
            assert_equal(dtnat + tda, dtnat)
            assert_equal((dta + tda).dtype, np.dtype('M8[D]'))
            # m8 + M8
            assert_equal(tda + dta, dtb)
            assert_equal(tda + dtnat, dtnat)
            assert_equal((tda + dta).dtype, np.dtype('M8[D]'))

            # In M8 + m8, the result goes to higher precision
            assert_equal(np.add(dta, tdb, casting='unsafe'), dtc)
            assert_equal(np.add(dta, tdb, casting='unsafe').dtype,
                         np.dtype('M8[h]'))
            assert_equal(np.add(tdb, dta, casting='unsafe'), dtc)
            assert_equal(np.add(tdb, dta, casting='unsafe').dtype,
                         np.dtype('M8[h]'))

            # M8 + M8
            assert_raises(TypeError, np.add, dta, dtb)

    def test_datetime_subtract(self):
        for dta, dtb, dtc, dtd, dte, dtnat, tda, tdb, tdc in \
                    [
                     # One-dimensional arrays
                     (np.array(['2012-12-21'], dtype='M8[D]'),
                      np.array(['2012-12-24'], dtype='M8[D]'),
                      np.array(['1940-12-24'], dtype='M8[D]'),
                      np.array(['1940-12-24T00'], dtype='M8[h]'),
                      np.array(['1940-12-23T13'], dtype='M8[h]'),
                      np.array(['NaT'], dtype='M8[D]'),
                      np.array([3], dtype='m8[D]'),
                      np.array([11], dtype='m8[h]'),
                      np.array([3*24 - 11], dtype='m8[h]')),
                     # NumPy scalars
                     (np.datetime64('2012-12-21', '[D]'),
                      np.datetime64('2012-12-24', '[D]'),
                      np.datetime64('1940-12-24', '[D]'),
                      np.datetime64('1940-12-24T00', '[h]'),
                      np.datetime64('1940-12-23T13', '[h]'),
                      np.datetime64('NaT', '[D]'),
                      np.timedelta64(3, '[D]'),
                      np.timedelta64(11, '[h]'),
                      np.timedelta64(3*24 - 11, '[h]'))]:
            # m8 - m8
            assert_equal(tda - tdb, tdc)
            assert_equal((tda - tdb).dtype, np.dtype('m8[h]'))
            assert_equal(tdb - tda, -tdc)
            assert_equal((tdb - tda).dtype, np.dtype('m8[h]'))
            # m8 - bool
            assert_equal(tdc - True, tdc - 1)
            assert_equal((tdc - True).dtype, np.dtype('m8[h]'))
            # m8 - int
            assert_equal(tdc - 3*24, -tdb)
            assert_equal((tdc - 3*24).dtype, np.dtype('m8[h]'))
            # int - m8
            assert_equal(False - tdb, -tdb)
            assert_equal((False - tdb).dtype, np.dtype('m8[h]'))
            # int - m8
            assert_equal(3*24 - tdb, tdc)
            assert_equal((3*24 - tdb).dtype, np.dtype('m8[h]'))
            # M8 - bool
            assert_equal(dtb - True, dtb - 1)
            assert_equal(dtnat - True, dtnat)
            assert_equal((dtb - True).dtype, np.dtype('M8[D]'))
            # M8 - int
            assert_equal(dtb - 3, dta)
            assert_equal(dtnat - 3, dtnat)
            assert_equal((dtb - 3).dtype, np.dtype('M8[D]'))
            # M8 - m8
            assert_equal(dtb - tda, dta)
            assert_equal(dtnat - tda, dtnat)
            assert_equal((dtb - tda).dtype, np.dtype('M8[D]'))

            # In M8 - m8, the result goes to higher precision
            assert_equal(np.subtract(dtc, tdb, casting='unsafe'), dte)
            assert_equal(np.subtract(dtc, tdb, casting='unsafe').dtype,
                         np.dtype('M8[h]'))

            # M8 - M8 with different goes to higher precision
            assert_equal(np.subtract(dtc, dtd, casting='unsafe'),
                         np.timedelta64(0, 'h'))
            assert_equal(np.subtract(dtc, dtd, casting='unsafe').dtype,
                         np.dtype('m8[h]'))
            assert_equal(np.subtract(dtd, dtc, casting='unsafe'),
                         np.timedelta64(0, 'h'))
            assert_equal(np.subtract(dtd, dtc, casting='unsafe').dtype,
                         np.dtype('m8[h]'))

            # m8 - M8
            assert_raises(TypeError, np.subtract, tda, dta)
            # bool - M8
            assert_raises(TypeError, np.subtract, False, dta)
            # int - M8
            assert_raises(TypeError, np.subtract, 3, dta)

    def test_datetime_multiply(self):
        for dta, tda, tdb, tdc in \
                    [
                     # One-dimensional arrays
                     (np.array(['2012-12-21'], dtype='M8[D]'),
                      np.array([6], dtype='m8[h]'),
                      np.array([9], dtype='m8[h]'),
                      np.array([12], dtype='m8[h]')),
                     # NumPy scalars
                     (np.datetime64('2012-12-21', '[D]'),
                      np.timedelta64(6, '[h]'),
                      np.timedelta64(9, '[h]'),
                      np.timedelta64(12, '[h]'))]:
            # m8 * int
            assert_equal(tda * 2, tdc)
            assert_equal((tda * 2).dtype, np.dtype('m8[h]'))
            # int * m8
            assert_equal(2 * tda, tdc)
            assert_equal((2 * tda).dtype, np.dtype('m8[h]'))
            # m8 * float
            assert_equal(tda * 1.5, tdb)
            assert_equal((tda * 1.5).dtype, np.dtype('m8[h]'))
            # float * m8
            assert_equal(1.5 * tda, tdb)
            assert_equal((1.5 * tda).dtype, np.dtype('m8[h]'))

            # m8 * m8
            assert_raises(TypeError, np.multiply, tda, tdb)
            # m8 * M8
            assert_raises(TypeError, np.multiply, dta, tda)
            # M8 * m8
            assert_raises(TypeError, np.multiply, tda, dta)
            # M8 * int
            assert_raises(TypeError, np.multiply, dta, 2)
            # int * M8
            assert_raises(TypeError, np.multiply, 2, dta)
            # M8 * float
            assert_raises(TypeError, np.multiply, dta, 1.5)
            # float * M8
            assert_raises(TypeError, np.multiply, 1.5, dta)

        # NaTs
        with suppress_warnings() as sup:
            sup.filter(RuntimeWarning, "invalid value encountered in multiply")
            nat = np.timedelta64('NaT')
            def check(a, b, res):
                assert_equal(a * b, res)
                assert_equal(b * a, res)
            for tp in (int, float):
                check(nat, tp(2), nat)
                check(nat, tp(0), nat)
            for f in (float('inf'), float('nan')):
                check(np.timedelta64(1), f, nat)
                check(np.timedelta64(0), f, nat)
                check(nat, f, nat)

    @pytest.mark.parametrize("op1, op2, exp", [
        # m8 same units round down
        (np.timedelta64(7, 's'),
         np.timedelta64(4, 's'),
         1),
        # m8 same units round down with negative
        (np.timedelta64(7, 's'),
         np.timedelta64(-4, 's'),
         -2),
        # m8 same units negative no round down
        (np.timedelta64(8, 's'),
         np.timedelta64(-4, 's'),
         -2),
        # m8 different units
        (np.timedelta64(1, 'm'),
         np.timedelta64(31, 's'),
         1),
        # m8 generic units
        (np.timedelta64(1890),
         np.timedelta64(31),
         60),
        # Y // M works
        (np.timedelta64(2, 'Y'),
         np.timedelta64('13', 'M'),
         1),
        # handle 1D arrays
        (np.array([1, 2, 3], dtype='m8'),
         np.array([2], dtype='m8'),
         np.array([0, 1, 1], dtype=np.int64)),
        ])
    def test_timedelta_floor_divide(self, op1, op2, exp):
        assert_equal(op1 // op2, exp)

    @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm")
    @pytest.mark.parametrize("op1, op2", [
        # div by 0
        (np.timedelta64(10, 'us'),
         np.timedelta64(0, 'us')),
        # div with NaT
        (np.timedelta64('NaT'),
         np.timedelta64(50, 'us')),
        # special case for int64 min
        # in integer floor division
        (np.timedelta64(np.iinfo(np.int64).min),
         np.timedelta64(-1)),
        ])
    def test_timedelta_floor_div_warnings(self, op1, op2):
        with assert_warns(RuntimeWarning):
            actual = op1 // op2
            assert_equal(actual, 0)
            assert_equal(actual.dtype, np.int64)

    @pytest.mark.parametrize("val1, val2", [
        # the smallest integer that can't be represented
        # exactly in a double should be preserved if we avoid
        # casting to double in floordiv operation
        (9007199254740993, 1),
        # stress the alternate floordiv code path where
        # operand signs don't match and remainder isn't 0
        (9007199254740999, -2),
        ])
    def test_timedelta_floor_div_precision(self, val1, val2):
        op1 = np.timedelta64(val1)
        op2 = np.timedelta64(val2)
        actual = op1 // op2
        # Python reference integer floor
        expected = val1 // val2
        assert_equal(actual, expected)

    @pytest.mark.parametrize("val1, val2", [
        # years and months sometimes can't be unambiguously
        # divided for floor division operation
        (np.timedelta64(7, 'Y'),
         np.timedelta64(3, 's')),
        (np.timedelta64(7, 'M'),
         np.timedelta64(1, 'D')),
        ])
    def test_timedelta_floor_div_error(self, val1, val2):
        with assert_raises_regex(TypeError, "common metadata divisor"):
            val1 // val2

    @pytest.mark.parametrize("op1, op2", [
        # reuse the test cases from floordiv
        (np.timedelta64(7, 's'),
         np.timedelta64(4, 's')),
        # m8 same units round down with negative
        (np.timedelta64(7, 's'),
         np.timedelta64(-4, 's')),
        # m8 same units negative no round down
        (np.timedelta64(8, 's'),
         np.timedelta64(-4, 's')),
        # m8 different units
        (np.timedelta64(1, 'm'),
         np.timedelta64(31, 's')),
        # m8 generic units
        (np.timedelta64(1890),
         np.timedelta64(31)),
        # Y // M works
        (np.timedelta64(2, 'Y'),
         np.timedelta64('13', 'M')),
        # handle 1D arrays
        (np.array([1, 2, 3], dtype='m8'),
         np.array([2], dtype='m8')),
        ])
    def test_timedelta_divmod(self, op1, op2):
        expected = (op1 // op2, op1 % op2)
        assert_equal(divmod(op1, op2), expected)

    @pytest.mark.skipif(IS_WASM, reason="does not work in wasm")
    @pytest.mark.parametrize("op1, op2", [
        # reuse cases from floordiv
        # div by 0
        (np.timedelta64(10, 'us'),
         np.timedelta64(0, 'us')),
        # div with NaT
        (np.timedelta64('NaT'),
         np.timedelta64(50, 'us')),
        # special case for int64 min
        # in integer floor division
        (np.timedelta64(np.iinfo(np.int64).min),
         np.timedelta64(-1)),
        ])
    def test_timedelta_divmod_warnings(self, op1, op2):
        with assert_warns(RuntimeWarning):
            expected = (op1 // op2, op1 % op2)
        with assert_warns(RuntimeWarning):
            actual = divmod(op1, op2)
        assert_equal(actual, expected)

    def test_datetime_divide(self):
        for dta, tda, tdb, tdc, tdd in \
                    [
                     # One-dimensional arrays
                     (np.array(['2012-12-21'], dtype='M8[D]'),
                      np.array([6], dtype='m8[h]'),
                      np.array([9], dtype='m8[h]'),
                      np.array([12], dtype='m8[h]'),
                      np.array([6], dtype='m8[m]')),
                     # NumPy scalars
                     (np.datetime64('2012-12-21', '[D]'),
                      np.timedelta64(6, '[h]'),
                      np.timedelta64(9, '[h]'),
                      np.timedelta64(12, '[h]'),
                      np.timedelta64(6, '[m]'))]:
            # m8 / int
            assert_equal(tdc / 2, tda)
            assert_equal((tdc / 2).dtype, np.dtype('m8[h]'))
            # m8 / float
            assert_equal(tda / 0.5, tdc)
            assert_equal((tda / 0.5).dtype, np.dtype('m8[h]'))
            # m8 / m8
            assert_equal(tda / tdb, 6 / 9)
            assert_equal(np.divide(tda, tdb), 6 / 9)
            assert_equal(np.true_divide(tda, tdb), 6 / 9)
            assert_equal(tdb / tda, 9 / 6)
            assert_equal((tda / tdb).dtype, np.dtype('f8'))
            assert_equal(tda / tdd, 60)
            assert_equal(tdd / tda, 1 / 60)

            # int / m8
            assert_raises(TypeError, np.divide, 2, tdb)
            # float / m8
            assert_raises(TypeError, np.divide, 0.5, tdb)
            # m8 / M8
            assert_raises(TypeError, np.divide, dta, tda)
            # M8 / m8
            assert_raises(TypeError, np.divide, tda, dta)
            # M8 / int
            assert_raises(TypeError, np.divide, dta, 2)
            # int / M8
            assert_raises(TypeError, np.divide, 2, dta)
            # M8 / float
            assert_raises(TypeError, np.divide, dta, 1.5)
            # float / M8
            assert_raises(TypeError, np.divide, 1.5, dta)

        # NaTs
        with suppress_warnings() as sup:
            sup.filter(RuntimeWarning,  r".*encountered in divide")
            nat = np.timedelta64('NaT')
            for tp in (int, float):
                assert_equal(np.timedelta64(1) / tp(0), nat)
                assert_equal(np.timedelta64(0) / tp(0), nat)
                assert_equal(nat / tp(0), nat)
                assert_equal(nat / tp(2), nat)
            # Division by inf
            assert_equal(np.timedelta64(1) / float('inf'), np.timedelta64(0))
            assert_equal(np.timedelta64(0) / float('inf'), np.timedelta64(0))
            assert_equal(nat / float('inf'), nat)
            # Division by nan
            assert_equal(np.timedelta64(1) / float('nan'), nat)
            assert_equal(np.timedelta64(0) / float('nan'), nat)
            assert_equal(nat / float('nan'), nat)

    def test_datetime_compare(self):
        # Test all the comparison operators
        a = np.datetime64('2000-03-12T18:00:00.000000')
        b = np.array(['2000-03-12T18:00:00.000000',
                      '2000-03-12T17:59:59.999999',
                      '2000-03-12T18:00:00.000001',
                      '1970-01-11T12:00:00.909090',
                      '2016-01-11T12:00:00.909090'],
                      dtype='datetime64[us]')
        assert_equal(np.equal(a, b), [1, 0, 0, 0, 0])
        assert_equal(np.not_equal(a, b), [0, 1, 1, 1, 1])
        assert_equal(np.less(a, b), [0, 0, 1, 0, 1])
        assert_equal(np.less_equal(a, b), [1, 0, 1, 0, 1])
        assert_equal(np.greater(a, b), [0, 1, 0, 1, 0])
        assert_equal(np.greater_equal(a, b), [1, 1, 0, 1, 0])

    def test_datetime_compare_nat(self):
        dt_nat = np.datetime64('NaT', 'D')
        dt_other = np.datetime64('2000-01-01')
        td_nat = np.timedelta64('NaT', 'h')
        td_other = np.timedelta64(1, 'h')

        for op in [np.equal, np.less, np.less_equal,
                   np.greater, np.greater_equal]:
            assert_(not op(dt_nat, dt_nat))
            assert_(not op(dt_nat, dt_other))
            assert_(not op(dt_other, dt_nat))

            assert_(not op(td_nat, td_nat))
            assert_(not op(td_nat, td_other))
            assert_(not op(td_other, td_nat))

        assert_(np.not_equal(dt_nat, dt_nat))
        assert_(np.not_equal(dt_nat, dt_other))
        assert_(np.not_equal(dt_other, dt_nat))

        assert_(np.not_equal(td_nat, td_nat))
        assert_(np.not_equal(td_nat, td_other))
        assert_(np.not_equal(td_other, td_nat))

    def test_datetime_minmax(self):
        # The metadata of the result should become the GCD
        # of the operand metadata
        a = np.array('1999-03-12T13', dtype='M8[2m]')
        b = np.array('1999-03-12T12', dtype='M8[s]')
        assert_equal(np.minimum(a, b), b)
        assert_equal(np.minimum(a, b).dtype, np.dtype('M8[s]'))
        assert_equal(np.fmin(a, b), b)
        assert_equal(np.fmin(a, b).dtype, np.dtype('M8[s]'))
        assert_equal(np.maximum(a, b), a)
        assert_equal(np.maximum(a, b).dtype, np.dtype('M8[s]'))
        assert_equal(np.fmax(a, b), a)
        assert_equal(np.fmax(a, b).dtype, np.dtype('M8[s]'))
        # Viewed as integers, the comparison is opposite because
        # of the units chosen
        assert_equal(np.minimum(a.view('i8'), b.view('i8')), a.view('i8'))

        # Interaction with NaT
        a = np.array('1999-03-12T13', dtype='M8[2m]')
        dtnat = np.array('NaT', dtype='M8[h]')
        assert_equal(np.minimum(a, dtnat), dtnat)
        assert_equal(np.minimum(dtnat, a), dtnat)
        assert_equal(np.maximum(a, dtnat), dtnat)
        assert_equal(np.maximum(dtnat, a), dtnat)
        assert_equal(np.fmin(dtnat, a), a)
        assert_equal(np.fmin(a, dtnat), a)
        assert_equal(np.fmax(dtnat, a), a)
        assert_equal(np.fmax(a, dtnat), a)

        # Also do timedelta
        a = np.array(3, dtype='m8[h]')
        b = np.array(3*3600 - 3, dtype='m8[s]')
        assert_equal(np.minimum(a, b), b)
        assert_equal(np.minimum(a, b).dtype, np.dtype('m8[s]'))
        assert_equal(np.fmin(a, b), b)
        assert_equal(np.fmin(a, b).dtype, np.dtype('m8[s]'))
        assert_equal(np.maximum(a, b), a)
        assert_equal(np.maximum(a, b).dtype, np.dtype('m8[s]'))
        assert_equal(np.fmax(a, b), a)
        assert_equal(np.fmax(a, b).dtype, np.dtype('m8[s]'))
        # Viewed as integers, the comparison is opposite because
        # of the units chosen
        assert_equal(np.minimum(a.view('i8'), b.view('i8')), a.view('i8'))

        # should raise between datetime and timedelta
        #
        # TODO: Allowing unsafe casting by
        #       default in ufuncs strikes again... :(
        a = np.array(3, dtype='m8[h]')
        b = np.array('1999-03-12T12', dtype='M8[s]')
        #assert_raises(TypeError, np.minimum, a, b)
        #assert_raises(TypeError, np.maximum, a, b)
        #assert_raises(TypeError, np.fmin, a, b)
        #assert_raises(TypeError, np.fmax, a, b)
        assert_raises(TypeError, np.minimum, a, b, casting='same_kind')
        assert_raises(TypeError, np.maximum, a, b, casting='same_kind')
        assert_raises(TypeError, np.fmin, a, b, casting='same_kind')
        assert_raises(TypeError, np.fmax, a, b, casting='same_kind')

    def test_hours(self):
        t = np.ones(3, dtype='M8[s]')
        t[0] = 60*60*24 + 60*60*10
        assert_(t[0].item().hour == 10)

    def test_divisor_conversion_year(self):
        assert_(np.dtype('M8[Y/4]') == np.dtype('M8[3M]'))
        assert_(np.dtype('M8[Y/13]') == np.dtype('M8[4W]'))
        assert_(np.dtype('M8[3Y/73]') == np.dtype('M8[15D]'))

    def test_divisor_conversion_month(self):
        assert_(np.dtype('M8[M/2]') == np.dtype('M8[2W]'))
        assert_(np.dtype('M8[M/15]') == np.dtype('M8[2D]'))
        assert_(np.dtype('M8[3M/40]') == np.dtype('M8[54h]'))

    def test_divisor_conversion_week(self):
        assert_(np.dtype('m8[W/7]') == np.dtype('m8[D]'))
        assert_(np.dtype('m8[3W/14]') == np.dtype('m8[36h]'))
        assert_(np.dtype('m8[5W/140]') == np.dtype('m8[360m]'))

    def test_divisor_conversion_day(self):
        assert_(np.dtype('M8[D/12]') == np.dtype('M8[2h]'))
        assert_(np.dtype('M8[D/120]') == np.dtype('M8[12m]'))
        assert_(np.dtype('M8[3D/960]') == np.dtype('M8[270s]'))

    def test_divisor_conversion_hour(self):
        assert_(np.dtype('m8[h/30]') == np.dtype('m8[2m]'))
        assert_(np.dtype('m8[3h/300]') == np.dtype('m8[36s]'))

    def test_divisor_conversion_minute(self):
        assert_(np.dtype('m8[m/30]') == np.dtype('m8[2s]'))
        assert_(np.dtype('m8[3m/300]') == np.dtype('m8[600ms]'))

    def test_divisor_conversion_second(self):
        assert_(np.dtype('m8[s/100]') == np.dtype('m8[10ms]'))
        assert_(np.dtype('m8[3s/10000]') == np.dtype('m8[300us]'))

    def test_divisor_conversion_fs(self):
        assert_(np.dtype('M8[fs/100]') == np.dtype('M8[10as]'))
        assert_raises(ValueError, lambda: np.dtype('M8[3fs/10000]'))

    def test_divisor_conversion_as(self):
        assert_raises(ValueError, lambda: np.dtype('M8[as/10]'))

    def test_string_parser_variants(self):
        # Allow space instead of 'T' between date and time
        assert_equal(np.array(['1980-02-29T01:02:03'], np.dtype('M8[s]')),
                     np.array(['1980-02-29 01:02:03'], np.dtype('M8[s]')))
        # Allow positive years
        assert_equal(np.array(['+1980-02-29T01:02:03'], np.dtype('M8[s]')),
                     np.array(['+1980-02-29 01:02:03'], np.dtype('M8[s]')))
        # Allow negative years
        assert_equal(np.array(['-1980-02-29T01:02:03'], np.dtype('M8[s]')),
                     np.array(['-1980-02-29 01:02:03'], np.dtype('M8[s]')))
        # UTC specifier
        with assert_warns(DeprecationWarning):
            assert_equal(
                np.array(['+1980-02-29T01:02:03'], np.dtype('M8[s]')),
                np.array(['+1980-02-29 01:02:03Z'], np.dtype('M8[s]')))
        with assert_warns(DeprecationWarning):
            assert_equal(
                np.array(['-1980-02-29T01:02:03'], np.dtype('M8[s]')),
                np.array(['-1980-02-29 01:02:03Z'], np.dtype('M8[s]')))
        # Time zone offset
        with assert_warns(DeprecationWarning):
            assert_equal(
                np.array(['1980-02-29T02:02:03'], np.dtype('M8[s]')),
                np.array(['1980-02-29 00:32:03-0130'], np.dtype('M8[s]')))
        with assert_warns(DeprecationWarning):
            assert_equal(
                np.array(['1980-02-28T22:32:03'], np.dtype('M8[s]')),
                np.array(['1980-02-29 00:02:03+01:30'], np.dtype('M8[s]')))
        with assert_warns(DeprecationWarning):
            assert_equal(
                np.array(['1980-02-29T02:32:03.506'], np.dtype('M8[s]')),
                np.array(['1980-02-29 00:32:03.506-02'], np.dtype('M8[s]')))
        with assert_warns(DeprecationWarning):
            assert_equal(np.datetime64('1977-03-02T12:30-0230'),
                         np.datetime64('1977-03-02T15:00'))

    def test_string_parser_error_check(self):
        # Arbitrary bad string
        assert_raises(ValueError, np.array, ['badvalue'], np.dtype('M8[us]'))
        # Character after year must be '-'
        assert_raises(ValueError, np.array, ['1980X'], np.dtype('M8[us]'))
        # Cannot have trailing '-'
        assert_raises(ValueError, np.array, ['1980-'], np.dtype('M8[us]'))
        # Month must be in range [1,12]
        assert_raises(ValueError, np.array, ['1980-00'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-13'], np.dtype('M8[us]'))
        # Month must have two digits
        assert_raises(ValueError, np.array, ['1980-1'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-1-02'], np.dtype('M8[us]'))
        # 'Mor' is not a valid month
        assert_raises(ValueError, np.array, ['1980-Mor'], np.dtype('M8[us]'))
        # Cannot have trailing '-'
        assert_raises(ValueError, np.array, ['1980-01-'], np.dtype('M8[us]'))
        # Day must be in range [1,len(month)]
        assert_raises(ValueError, np.array, ['1980-01-0'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-01-00'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-01-32'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1979-02-29'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-02-30'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-03-32'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-04-31'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-05-32'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-06-31'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-07-32'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-08-32'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-09-31'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-10-32'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-11-31'], np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-12-32'], np.dtype('M8[us]'))
        # Cannot have trailing characters
        assert_raises(ValueError, np.array, ['1980-02-03%'],
                                                        np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-02-03 q'],
                                                        np.dtype('M8[us]'))

        # Hours must be in range [0, 23]
        assert_raises(ValueError, np.array, ['1980-02-03 25'],
                                                        np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-02-03T25'],
                                                        np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-02-03 24:01'],
                                                        np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-02-03T24:01'],
                                                        np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-02-03 -1'],
                                                        np.dtype('M8[us]'))
        # No trailing ':'
        assert_raises(ValueError, np.array, ['1980-02-03 01:'],
                                                        np.dtype('M8[us]'))
        # Minutes must be in range [0, 59]
        assert_raises(ValueError, np.array, ['1980-02-03 01:-1'],
                                                        np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-02-03 01:60'],
                                                        np.dtype('M8[us]'))
        # No trailing ':'
        assert_raises(ValueError, np.array, ['1980-02-03 01:60:'],
                                                        np.dtype('M8[us]'))
        # Seconds must be in range [0, 59]
        assert_raises(ValueError, np.array, ['1980-02-03 01:10:-1'],
                                                        np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-02-03 01:01:60'],
                                                        np.dtype('M8[us]'))
        # Timezone offset must within a reasonable range
        with assert_warns(DeprecationWarning):
            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00+0661'],
                                                            np.dtype('M8[us]'))
        with assert_warns(DeprecationWarning):
            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00+2500'],
                                                            np.dtype('M8[us]'))
        with assert_warns(DeprecationWarning):
            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00-0070'],
                                                            np.dtype('M8[us]'))
        with assert_warns(DeprecationWarning):
            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00-3000'],
                                                            np.dtype('M8[us]'))
        with assert_warns(DeprecationWarning):
            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00-25:00'],
                                                            np.dtype('M8[us]'))

    def test_creation_overflow(self):
        date = '1980-03-23 20:00:00'
        timesteps = np.array([date], dtype='datetime64[s]')[0].astype(np.int64)
        for unit in ['ms', 'us', 'ns']:
            timesteps *= 1000
            x = np.array([date], dtype='datetime64[%s]' % unit)

            assert_equal(timesteps, x[0].astype(np.int64),
                         err_msg='Datetime conversion error for unit %s' % unit)

        assert_equal(x[0].astype(np.int64), 322689600000000000)

        # gh-13062
        with pytest.raises(OverflowError):
            np.datetime64(2**64, 'D')
        with pytest.raises(OverflowError):
            np.timedelta64(2**64, 'D')

    def test_datetime_as_string(self):
        # Check all the units with default string conversion
        date = '1959-10-13'
        datetime = '1959-10-13T12:34:56.789012345678901234'

        assert_equal(np.datetime_as_string(np.datetime64(date, 'Y')),
                     '1959')
        assert_equal(np.datetime_as_string(np.datetime64(date, 'M')),
                     '1959-10')
        assert_equal(np.datetime_as_string(np.datetime64(date, 'D')),
                     '1959-10-13')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'h')),
                     '1959-10-13T12')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'm')),
                     '1959-10-13T12:34')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 's')),
                     '1959-10-13T12:34:56')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ms')),
                     '1959-10-13T12:34:56.789')
        for us in ['us', 'μs', b'us']:  # check non-ascii and bytes too
            assert_equal(np.datetime_as_string(np.datetime64(datetime, us)),
                         '1959-10-13T12:34:56.789012')

        datetime = '1969-12-31T23:34:56.789012345678901234'

        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ns')),
                     '1969-12-31T23:34:56.789012345')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ps')),
                     '1969-12-31T23:34:56.789012345678')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'fs')),
                     '1969-12-31T23:34:56.789012345678901')

        datetime = '1969-12-31T23:59:57.789012345678901234'

        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'as')),
                     datetime)
        datetime = '1970-01-01T00:34:56.789012345678901234'

        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ns')),
                     '1970-01-01T00:34:56.789012345')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ps')),
                     '1970-01-01T00:34:56.789012345678')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'fs')),
                     '1970-01-01T00:34:56.789012345678901')

        datetime = '1970-01-01T00:00:05.789012345678901234'

        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'as')),
                     datetime)

        # String conversion with the unit= parameter
        a = np.datetime64('2032-07-18T12:23:34.123456', 'us')
        assert_equal(np.datetime_as_string(a, unit='Y', casting='unsafe'),
                            '2032')
        assert_equal(np.datetime_as_string(a, unit='M', casting='unsafe'),
                            '2032-07')
        assert_equal(np.datetime_as_string(a, unit='W', casting='unsafe'),
                            '2032-07-18')
        assert_equal(np.datetime_as_string(a, unit='D', casting='unsafe'),
                            '2032-07-18')
        assert_equal(np.datetime_as_string(a, unit='h'), '2032-07-18T12')
        assert_equal(np.datetime_as_string(a, unit='m'),
                            '2032-07-18T12:23')
        assert_equal(np.datetime_as_string(a, unit='s'),
                            '2032-07-18T12:23:34')
        assert_equal(np.datetime_as_string(a, unit='ms'),
                            '2032-07-18T12:23:34.123')
        assert_equal(np.datetime_as_string(a, unit='us'),
                            '2032-07-18T12:23:34.123456')
        assert_equal(np.datetime_as_string(a, unit='ns'),
                            '2032-07-18T12:23:34.123456000')
        assert_equal(np.datetime_as_string(a, unit='ps'),
                            '2032-07-18T12:23:34.123456000000')
        assert_equal(np.datetime_as_string(a, unit='fs'),
                            '2032-07-18T12:23:34.123456000000000')
        assert_equal(np.datetime_as_string(a, unit='as'),
                            '2032-07-18T12:23:34.123456000000000000')

        # unit='auto' parameter
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-07-18T12:23:34.123456', 'us'), unit='auto'),
                '2032-07-18T12:23:34.123456')
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-07-18T12:23:34.12', 'us'), unit='auto'),
                '2032-07-18T12:23:34.120')
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-07-18T12:23:34', 'us'), unit='auto'),
                '2032-07-18T12:23:34')
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-07-18T12:23:00', 'us'), unit='auto'),
                '2032-07-18T12:23')
        # 'auto' doesn't split up hour and minute
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-07-18T12:00:00', 'us'), unit='auto'),
                '2032-07-18T12:00')
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-07-18T00:00:00', 'us'), unit='auto'),
                '2032-07-18')
        # 'auto' doesn't split up the date
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-07-01T00:00:00', 'us'), unit='auto'),
                '2032-07-01')
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-01-01T00:00:00', 'us'), unit='auto'),
                '2032-01-01')

    @pytest.mark.skipif(not _has_pytz, reason="The pytz module is not available.")
    def test_datetime_as_string_timezone(self):
        # timezone='local' vs 'UTC'
        a = np.datetime64('2010-03-15T06:30', 'm')
        assert_equal(np.datetime_as_string(a),
                '2010-03-15T06:30')
        assert_equal(np.datetime_as_string(a, timezone='naive'),
                '2010-03-15T06:30')
        assert_equal(np.datetime_as_string(a, timezone='UTC'),
                '2010-03-15T06:30Z')
        assert_(np.datetime_as_string(a, timezone='local') !=
                '2010-03-15T06:30')

        b = np.datetime64('2010-02-15T06:30', 'm')

        assert_equal(np.datetime_as_string(a, timezone=tz('US/Central')),
                     '2010-03-15T01:30-0500')
        assert_equal(np.datetime_as_string(a, timezone=tz('US/Eastern')),
                     '2010-03-15T02:30-0400')
        assert_equal(np.datetime_as_string(a, timezone=tz('US/Pacific')),
                     '2010-03-14T23:30-0700')

        assert_equal(np.datetime_as_string(b, timezone=tz('US/Central')),
                     '2010-02-15T00:30-0600')
        assert_equal(np.datetime_as_string(b, timezone=tz('US/Eastern')),
                     '2010-02-15T01:30-0500')
        assert_equal(np.datetime_as_string(b, timezone=tz('US/Pacific')),
                     '2010-02-14T22:30-0800')

        # Dates to strings with a timezone attached is disabled by default
        assert_raises(TypeError, np.datetime_as_string, a, unit='D',
                           timezone=tz('US/Pacific'))
        # Check that we can print out the date in the specified time zone
        assert_equal(np.datetime_as_string(a, unit='D',
                           timezone=tz('US/Pacific'), casting='unsafe'),
                     '2010-03-14')
        assert_equal(np.datetime_as_string(b, unit='D',
                           timezone=tz('US/Central'), casting='unsafe'),
                     '2010-02-15')

    def test_datetime_arange(self):
        # With two datetimes provided as strings
        a = np.arange('2010-01-05', '2010-01-10', dtype='M8[D]')
        assert_equal(a.dtype, np.dtype('M8[D]'))
        assert_equal(a,
            np.array(['2010-01-05', '2010-01-06', '2010-01-07',
                      '2010-01-08', '2010-01-09'], dtype='M8[D]'))

        a = np.arange('1950-02-10', '1950-02-06', -1, dtype='M8[D]')
        assert_equal(a.dtype, np.dtype('M8[D]'))
        assert_equal(a,
            np.array(['1950-02-10', '1950-02-09', '1950-02-08',
                      '1950-02-07'], dtype='M8[D]'))

        # Unit should be detected as months here
        a = np.arange('1969-05', '1970-05', 2, dtype='M8')
        assert_equal(a.dtype, np.dtype('M8[M]'))
        assert_equal(a,
            np.datetime64('1969-05') + np.arange(12, step=2))

        # datetime, integer|timedelta works as well
        # produces arange (start, start + stop) in this case
        a = np.arange('1969', 18, 3, dtype='M8')
        assert_equal(a.dtype, np.dtype('M8[Y]'))
        assert_equal(a,
            np.datetime64('1969') + np.arange(18, step=3))
        a = np.arange('1969-12-19', 22, np.timedelta64(2), dtype='M8')
        assert_equal(a.dtype, np.dtype('M8[D]'))
        assert_equal(a,
            np.datetime64('1969-12-19') + np.arange(22, step=2))

        # Step of 0 is disallowed
        assert_raises(ValueError, np.arange, np.datetime64('today'),
                                np.datetime64('today') + 3, 0)
        # Promotion across nonlinear unit boundaries is disallowed
        assert_raises(TypeError, np.arange, np.datetime64('2011-03-01', 'D'),
                                np.timedelta64(5, 'M'))
        assert_raises(TypeError, np.arange,
                                np.datetime64('2012-02-03T14', 's'),
                                np.timedelta64(5, 'Y'))

    def test_datetime_arange_no_dtype(self):
        d = np.array('2010-01-04', dtype="M8[D]")
        assert_equal(np.arange(d, d + 1), d)
        assert_raises(ValueError, np.arange, d)

    def test_timedelta_arange(self):
        a = np.arange(3, 10, dtype='m8')
        assert_equal(a.dtype, np.dtype('m8'))
        assert_equal(a, np.timedelta64(0) + np.arange(3, 10))

        a = np.arange(np.timedelta64(3, 's'), 10, 2, dtype='m8')
        assert_equal(a.dtype, np.dtype('m8[s]'))
        assert_equal(a, np.timedelta64(0, 's') + np.arange(3, 10, 2))

        # Step of 0 is disallowed
        assert_raises(ValueError, np.arange, np.timedelta64(0),
                                np.timedelta64(5), 0)
        # Promotion across nonlinear unit boundaries is disallowed
        assert_raises(TypeError, np.arange, np.timedelta64(0, 'D'),
                                np.timedelta64(5, 'M'))
        assert_raises(TypeError, np.arange, np.timedelta64(0, 'Y'),
                                np.timedelta64(5, 'D'))

    @pytest.mark.parametrize("val1, val2, expected", [
        # case from gh-12092
        (np.timedelta64(7, 's'),
         np.timedelta64(3, 's'),
         np.timedelta64(1, 's')),
        # negative value cases
        (np.timedelta64(3, 's'),
         np.timedelta64(-2, 's'),
         np.timedelta64(-1, 's')),
        (np.timedelta64(-3, 's'),
         np.timedelta64(2, 's'),
         np.timedelta64(1, 's')),
        # larger value cases
        (np.timedelta64(17, 's'),
         np.timedelta64(22, 's'),
         np.timedelta64(17, 's')),
        (np.timedelta64(22, 's'),
         np.timedelta64(17, 's'),
         np.timedelta64(5, 's')),
        # different units
        (np.timedelta64(1, 'm'),
         np.timedelta64(57, 's'),
         np.timedelta64(3, 's')),
        (np.timedelta64(1, 'us'),
         np.timedelta64(727, 'ns'),
         np.timedelta64(273, 'ns')),
        # NaT is propagated
        (np.timedelta64('NaT'),
         np.timedelta64(50, 'ns'),
         np.timedelta64('NaT')),
        # Y % M works
        (np.timedelta64(2, 'Y'),
         np.timedelta64(22, 'M'),
         np.timedelta64(2, 'M')),
        ])
    def test_timedelta_modulus(self, val1, val2, expected):
        assert_equal(val1 % val2, expected)

    @pytest.mark.parametrize("val1, val2", [
        # years and months sometimes can't be unambiguously
        # divided for modulus operation
        (np.timedelta64(7, 'Y'),
         np.timedelta64(3, 's')),
        (np.timedelta64(7, 'M'),
         np.timedelta64(1, 'D')),
        ])
    def test_timedelta_modulus_error(self, val1, val2):
        with assert_raises_regex(TypeError, "common metadata divisor"):
            val1 % val2

    @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm")
    def test_timedelta_modulus_div_by_zero(self):
        with assert_warns(RuntimeWarning):
            actual = np.timedelta64(10, 's') % np.timedelta64(0, 's')
            assert_equal(actual, np.timedelta64('NaT'))

    @pytest.mark.parametrize("val1, val2", [
        # cases where one operand is not
        # timedelta64
        (np.timedelta64(7, 'Y'),
         15,),
        (7.5,
         np.timedelta64(1, 'D')),
        ])
    def test_timedelta_modulus_type_resolution(self, val1, val2):
        # NOTE: some of the operations may be supported
        # in the future
        with assert_raises_regex(TypeError,
                                 "'remainder' cannot use operands with types"):
            val1 % val2

    def test_timedelta_arange_no_dtype(self):
        d = np.array(5, dtype="m8[D]")
        assert_equal(np.arange(d, d + 1), d)
        assert_equal(np.arange(d), np.arange(0, d))

    def test_datetime_maximum_reduce(self):
        a = np.array(['2010-01-02', '1999-03-14', '1833-03'], dtype='M8[D]')
        assert_equal(np.maximum.reduce(a).dtype, np.dtype('M8[D]'))
        assert_equal(np.maximum.reduce(a),
                     np.datetime64('2010-01-02'))

        a = np.array([1, 4, 0, 7, 2], dtype='m8[s]')
        assert_equal(np.maximum.reduce(a).dtype, np.dtype('m8[s]'))
        assert_equal(np.maximum.reduce(a),
                     np.timedelta64(7, 's'))

    def test_timedelta_correct_mean(self):
        # test mainly because it worked only via a bug in that allowed:
        # `timedelta.sum(dtype="f8")` to ignore the dtype request.
        a = np.arange(1000, dtype="m8[s]")
        assert_array_equal(a.mean(), a.sum() / len(a))

    def test_datetime_no_subtract_reducelike(self):
        # subtracting two datetime64 works, but we cannot reduce it, since
        # the result of that subtraction will have a different dtype.
        arr = np.array(["2021-12-02", "2019-05-12"], dtype="M8[ms]")
        msg = r"the resolved dtypes are not compatible"

        with pytest.raises(TypeError, match=msg):
            np.subtract.reduce(arr)

        with pytest.raises(TypeError, match=msg):
            np.subtract.accumulate(arr)

        with pytest.raises(TypeError, match=msg):
            np.subtract.reduceat(arr, [0])

    def test_datetime_busday_offset(self):
        # First Monday in June
        assert_equal(
            np.busday_offset('2011-06', 0, roll='forward', weekmask='Mon'),
            np.datetime64('2011-06-06'))
        # Last Monday in June
        assert_equal(
            np.busday_offset('2011-07', -1, roll='forward', weekmask='Mon'),
            np.datetime64('2011-06-27'))
        assert_equal(
            np.busday_offset('2011-07', -1, roll='forward', weekmask='Mon'),
            np.datetime64('2011-06-27'))

        # Default M-F business days, different roll modes
        assert_equal(np.busday_offset('2010-08', 0, roll='backward'),
                     np.datetime64('2010-07-30'))
        assert_equal(np.busday_offset('2010-08', 0, roll='preceding'),
                     np.datetime64('2010-07-30'))
        assert_equal(np.busday_offset('2010-08', 0, roll='modifiedpreceding'),
                     np.datetime64('2010-08-02'))
        assert_equal(np.busday_offset('2010-08', 0, roll='modifiedfollowing'),
                     np.datetime64('2010-08-02'))
        assert_equal(np.busday_offset('2010-08', 0, roll='forward'),
                     np.datetime64('2010-08-02'))
        assert_equal(np.busday_offset('2010-08', 0, roll='following'),
                     np.datetime64('2010-08-02'))
        assert_equal(np.busday_offset('2010-10-30', 0, roll='following'),
                     np.datetime64('2010-11-01'))
        assert_equal(
                np.busday_offset('2010-10-30', 0, roll='modifiedfollowing'),
                np.datetime64('2010-10-29'))
        assert_equal(
                np.busday_offset('2010-10-30', 0, roll='modifiedpreceding'),
                np.datetime64('2010-10-29'))
        assert_equal(
                np.busday_offset('2010-10-16', 0, roll='modifiedfollowing'),
                np.datetime64('2010-10-18'))
        assert_equal(
                np.busday_offset('2010-10-16', 0, roll='modifiedpreceding'),
                np.datetime64('2010-10-15'))
        # roll='raise' by default
        assert_raises(ValueError, np.busday_offset, '2011-06-04', 0)

        # Bigger offset values
        assert_equal(np.busday_offset('2006-02-01', 25),
                     np.datetime64('2006-03-08'))
        assert_equal(np.busday_offset('2006-03-08', -25),
                     np.datetime64('2006-02-01'))
        assert_equal(np.busday_offset('2007-02-25', 11, weekmask='SatSun'),
                     np.datetime64('2007-04-07'))
        assert_equal(np.busday_offset('2007-04-07', -11, weekmask='SatSun'),
                     np.datetime64('2007-02-25'))

        # NaT values when roll is not raise
        assert_equal(np.busday_offset(np.datetime64('NaT'), 1, roll='nat'),
                     np.datetime64('NaT'))
        assert_equal(np.busday_offset(np.datetime64('NaT'), 1, roll='following'),
                     np.datetime64('NaT'))
        assert_equal(np.busday_offset(np.datetime64('NaT'), 1, roll='preceding'),
                     np.datetime64('NaT'))

    def test_datetime_busdaycalendar(self):
        # Check that it removes NaT, duplicates, and weekends
        # and sorts the result.
        bdd = np.busdaycalendar(
            holidays=['NaT', '2011-01-17', '2011-03-06', 'NaT',
                       '2011-12-26', '2011-05-30', '2011-01-17'])
        assert_equal(bdd.holidays,
            np.array(['2011-01-17', '2011-05-30', '2011-12-26'], dtype='M8'))
        # Default M-F weekmask
        assert_equal(bdd.weekmask, np.array([1, 1, 1, 1, 1, 0, 0], dtype='?'))

        # Check string weekmask with varying whitespace.
        bdd = np.busdaycalendar(weekmask="Sun TueWed  Thu\tFri")
        assert_equal(bdd.weekmask, np.array([0, 1, 1, 1, 1, 0, 1], dtype='?'))

        # Check length 7 0/1 string
        bdd = np.busdaycalendar(weekmask="0011001")
        assert_equal(bdd.weekmask, np.array([0, 0, 1, 1, 0, 0, 1], dtype='?'))

        # Check length 7 string weekmask.
        bdd = np.busdaycalendar(weekmask="Mon Tue")
        assert_equal(bdd.weekmask, np.array([1, 1, 0, 0, 0, 0, 0], dtype='?'))

        # All-zeros weekmask should raise
        assert_raises(ValueError, np.busdaycalendar, weekmask=[0, 0, 0, 0, 0, 0, 0])
        # weekday names must be correct case
        assert_raises(ValueError, np.busdaycalendar, weekmask="satsun")
        # All-zeros weekmask should raise
        assert_raises(ValueError, np.busdaycalendar, weekmask="")
        # Invalid weekday name codes should raise
        assert_raises(ValueError, np.busdaycalendar, weekmask="Mon Tue We")
        assert_raises(ValueError, np.busdaycalendar, weekmask="Max")
        assert_raises(ValueError, np.busdaycalendar, weekmask="Monday Tue")

    def test_datetime_busday_holidays_offset(self):
        # With exactly one holiday
        assert_equal(
            np.busday_offset('2011-11-10', 1, holidays=['2011-11-11']),
            np.datetime64('2011-11-14'))
        assert_equal(
            np.busday_offset('2011-11-04', 5, holidays=['2011-11-11']),
            np.datetime64('2011-11-14'))
        assert_equal(
            np.busday_offset('2011-11-10', 5, holidays=['2011-11-11']),
            np.datetime64('2011-11-18'))
        assert_equal(
            np.busday_offset('2011-11-14', -1, holidays=['2011-11-11']),
            np.datetime64('2011-11-10'))
        assert_equal(
            np.busday_offset('2011-11-18', -5, holidays=['2011-11-11']),
            np.datetime64('2011-11-10'))
        assert_equal(
            np.busday_offset('2011-11-14', -5, holidays=['2011-11-11']),
            np.datetime64('2011-11-04'))
        # With the holiday appearing twice
        assert_equal(
            np.busday_offset('2011-11-10', 1,
                holidays=['2011-11-11', '2011-11-11']),
            np.datetime64('2011-11-14'))
        assert_equal(
            np.busday_offset('2011-11-14', -1,
                holidays=['2011-11-11', '2011-11-11']),
            np.datetime64('2011-11-10'))
        # With a NaT holiday
        assert_equal(
            np.busday_offset('2011-11-10', 1,
                holidays=['2011-11-11', 'NaT']),
            np.datetime64('2011-11-14'))
        assert_equal(
            np.busday_offset('2011-11-14', -1,
                holidays=['NaT', '2011-11-11']),
            np.datetime64('2011-11-10'))
        # With another holiday after
        assert_equal(
            np.busday_offset('2011-11-10', 1,
                holidays=['2011-11-11', '2011-11-24']),
            np.datetime64('2011-11-14'))
        assert_equal(
            np.busday_offset('2011-11-14', -1,
                holidays=['2011-11-11', '2011-11-24']),
            np.datetime64('2011-11-10'))
        # With another holiday before
        assert_equal(
            np.busday_offset('2011-11-10', 1,
                holidays=['2011-10-10', '2011-11-11']),
            np.datetime64('2011-11-14'))
        assert_equal(
            np.busday_offset('2011-11-14', -1,
                holidays=['2011-10-10', '2011-11-11']),
            np.datetime64('2011-11-10'))
        # With another holiday before and after
        assert_equal(
            np.busday_offset('2011-11-10', 1,
                holidays=['2011-10-10', '2011-11-11', '2011-11-24']),
            np.datetime64('2011-11-14'))
        assert_equal(
            np.busday_offset('2011-11-14', -1,
                holidays=['2011-10-10', '2011-11-11', '2011-11-24']),
            np.datetime64('2011-11-10'))

        # A bigger forward jump across more than one week/holiday
        holidays = ['2011-10-10', '2011-11-11', '2011-11-24',
                  '2011-12-25', '2011-05-30', '2011-02-21',
                  '2011-12-26', '2012-01-02']
        bdd = np.busdaycalendar(weekmask='1111100', holidays=holidays)
        assert_equal(
            np.busday_offset('2011-10-03', 4, holidays=holidays),
            np.busday_offset('2011-10-03', 4))
        assert_equal(
            np.busday_offset('2011-10-03', 5, holidays=holidays),
            np.busday_offset('2011-10-03', 5 + 1))
        assert_equal(
            np.busday_offset('2011-10-03', 27, holidays=holidays),
            np.busday_offset('2011-10-03', 27 + 1))
        assert_equal(
            np.busday_offset('2011-10-03', 28, holidays=holidays),
            np.busday_offset('2011-10-03', 28 + 2))
        assert_equal(
            np.busday_offset('2011-10-03', 35, holidays=holidays),
            np.busday_offset('2011-10-03', 35 + 2))
        assert_equal(
            np.busday_offset('2011-10-03', 36, holidays=holidays),
            np.busday_offset('2011-10-03', 36 + 3))
        assert_equal(
            np.busday_offset('2011-10-03', 56, holidays=holidays),
            np.busday_offset('2011-10-03', 56 + 3))
        assert_equal(
            np.busday_offset('2011-10-03', 57, holidays=holidays),
            np.busday_offset('2011-10-03', 57 + 4))
        assert_equal(
            np.busday_offset('2011-10-03', 60, holidays=holidays),
            np.busday_offset('2011-10-03', 60 + 4))
        assert_equal(
            np.busday_offset('2011-10-03', 61, holidays=holidays),
            np.busday_offset('2011-10-03', 61 + 5))
        assert_equal(
            np.busday_offset('2011-10-03', 61, busdaycal=bdd),
            np.busday_offset('2011-10-03', 61 + 5))
        # A bigger backward jump across more than one week/holiday
        assert_equal(
            np.busday_offset('2012-01-03', -1, holidays=holidays),
            np.busday_offset('2012-01-03', -1 - 1))
        assert_equal(
            np.busday_offset('2012-01-03', -4, holidays=holidays),
            np.busday_offset('2012-01-03', -4 - 1))
        assert_equal(
            np.busday_offset('2012-01-03', -5, holidays=holidays),
            np.busday_offset('2012-01-03', -5 - 2))
        assert_equal(
            np.busday_offset('2012-01-03', -25, holidays=holidays),
            np.busday_offset('2012-01-03', -25 - 2))
        assert_equal(
            np.busday_offset('2012-01-03', -26, holidays=holidays),
            np.busday_offset('2012-01-03', -26 - 3))
        assert_equal(
            np.busday_offset('2012-01-03', -33, holidays=holidays),
            np.busday_offset('2012-01-03', -33 - 3))
        assert_equal(
            np.busday_offset('2012-01-03', -34, holidays=holidays),
            np.busday_offset('2012-01-03', -34 - 4))
        assert_equal(
            np.busday_offset('2012-01-03', -56, holidays=holidays),
            np.busday_offset('2012-01-03', -56 - 4))
        assert_equal(
            np.busday_offset('2012-01-03', -57, holidays=holidays),
            np.busday_offset('2012-01-03', -57 - 5))
        assert_equal(
            np.busday_offset('2012-01-03', -57, busdaycal=bdd),
            np.busday_offset('2012-01-03', -57 - 5))

        # Can't supply both a weekmask/holidays and busdaycal
        assert_raises(ValueError, np.busday_offset, '2012-01-03', -15,
                        weekmask='1111100', busdaycal=bdd)
        assert_raises(ValueError, np.busday_offset, '2012-01-03', -15,
                        holidays=holidays, busdaycal=bdd)

        # Roll with the holidays
        assert_equal(
            np.busday_offset('2011-12-25', 0,
                roll='forward', holidays=holidays),
            np.datetime64('2011-12-27'))
        assert_equal(
            np.busday_offset('2011-12-26', 0,
                roll='forward', holidays=holidays),
            np.datetime64('2011-12-27'))
        assert_equal(
            np.busday_offset('2011-12-26', 0,
                roll='backward', holidays=holidays),
            np.datetime64('2011-12-23'))
        assert_equal(
            np.busday_offset('2012-02-27', 0,
                roll='modifiedfollowing',
                holidays=['2012-02-27', '2012-02-26', '2012-02-28',
                          '2012-03-01', '2012-02-29']),
            np.datetime64('2012-02-24'))
        assert_equal(
            np.busday_offset('2012-03-06', 0,
                roll='modifiedpreceding',
                holidays=['2012-03-02', '2012-03-03', '2012-03-01',
                          '2012-03-05', '2012-03-07', '2012-03-06']),
            np.datetime64('2012-03-08'))

    def test_datetime_busday_holidays_count(self):
        holidays = ['2011-01-01', '2011-10-10', '2011-11-11', '2011-11-24',
                    '2011-12-25', '2011-05-30', '2011-02-21', '2011-01-17',
                    '2011-12-26', '2012-01-02', '2011-02-21', '2011-05-30',
                    '2011-07-01', '2011-07-04', '2011-09-05', '2011-10-10']
        bdd = np.busdaycalendar(weekmask='1111100', holidays=holidays)

        # Validate against busday_offset broadcast against
        # a range of offsets
        dates = np.busday_offset('2011-01-01', np.arange(366),
                        roll='forward', busdaycal=bdd)
        assert_equal(np.busday_count('2011-01-01', dates, busdaycal=bdd),
                     np.arange(366))
        # Returns negative value when reversed
        # -1 since the '2011-01-01' is not a busday
        assert_equal(np.busday_count(dates, '2011-01-01', busdaycal=bdd),
                     -np.arange(366) - 1)

        # 2011-12-31 is a saturday
        dates = np.busday_offset('2011-12-31', -np.arange(366),
                        roll='forward', busdaycal=bdd)
        # only the first generated date is in the future of 2011-12-31
        expected = np.arange(366)
        expected[0] = -1
        assert_equal(np.busday_count(dates, '2011-12-31', busdaycal=bdd),
                     expected)
        # Returns negative value when reversed
        expected = -np.arange(366)+1
        expected[0] = 0
        assert_equal(np.busday_count('2011-12-31', dates, busdaycal=bdd),
                     expected)

        # Can't supply both a weekmask/holidays and busdaycal
        assert_raises(ValueError, np.busday_offset, '2012-01-03', '2012-02-03',
                        weekmask='1111100', busdaycal=bdd)
        assert_raises(ValueError, np.busday_offset, '2012-01-03', '2012-02-03',
                        holidays=holidays, busdaycal=bdd)

        # Number of Mondays in March 2011
        assert_equal(np.busday_count('2011-03', '2011-04', weekmask='Mon'), 4)
        # Returns negative value when reversed
        assert_equal(np.busday_count('2011-04', '2011-03', weekmask='Mon'), -4)

        sunday = np.datetime64('2023-03-05')
        monday = sunday + 1
        friday = sunday + 5
        saturday = sunday + 6
        assert_equal(np.busday_count(sunday, monday), 0)
        assert_equal(np.busday_count(monday, sunday), -1)

        assert_equal(np.busday_count(friday, saturday), 1)
        assert_equal(np.busday_count(saturday, friday), 0)


    def test_datetime_is_busday(self):
        holidays = ['2011-01-01', '2011-10-10', '2011-11-11', '2011-11-24',
                    '2011-12-25', '2011-05-30', '2011-02-21', '2011-01-17',
                    '2011-12-26', '2012-01-02', '2011-02-21', '2011-05-30',
                    '2011-07-01', '2011-07-04', '2011-09-05', '2011-10-10',
                    'NaT']
        bdd = np.busdaycalendar(weekmask='1111100', holidays=holidays)

        # Weekend/weekday tests
        assert_equal(np.is_busday('2011-01-01'), False)
        assert_equal(np.is_busday('2011-01-02'), False)
        assert_equal(np.is_busday('2011-01-03'), True)

        # All the holidays are not business days
        assert_equal(np.is_busday(holidays, busdaycal=bdd),
                     np.zeros(len(holidays), dtype='?'))

    def test_datetime_y2038(self):
        # Test parsing on either side of the Y2038 boundary
        a = np.datetime64('2038-01-19T03:14:07')
        assert_equal(a.view(np.int64), 2**31 - 1)
        a = np.datetime64('2038-01-19T03:14:08')
        assert_equal(a.view(np.int64), 2**31)

        # Test parsing on either side of the Y2038 boundary with
        # a manually specified timezone offset
        with assert_warns(DeprecationWarning):
            a = np.datetime64('2038-01-19T04:14:07+0100')
            assert_equal(a.view(np.int64), 2**31 - 1)
        with assert_warns(DeprecationWarning):
            a = np.datetime64('2038-01-19T04:14:08+0100')
            assert_equal(a.view(np.int64), 2**31)

        # Test parsing a date after Y2038
        a = np.datetime64('2038-01-20T13:21:14')
        assert_equal(str(a), '2038-01-20T13:21:14')

    def test_isnat(self):
        assert_(np.isnat(np.datetime64('NaT', 'ms')))
        assert_(np.isnat(np.datetime64('NaT', 'ns')))
        assert_(not np.isnat(np.datetime64('2038-01-19T03:14:07')))

        assert_(np.isnat(np.timedelta64('NaT', "ms")))
        assert_(not np.isnat(np.timedelta64(34, "ms")))

        res = np.array([False, False, True])
        for unit in ['Y', 'M', 'W', 'D',
                     'h', 'm', 's', 'ms', 'us',
                     'ns', 'ps', 'fs', 'as']:
            arr = np.array([123, -321, "NaT"], dtype='<datetime64[%s]' % unit)
            assert_equal(np.isnat(arr), res)
            arr = np.array([123, -321, "NaT"], dtype='>datetime64[%s]' % unit)
            assert_equal(np.isnat(arr), res)
            arr = np.array([123, -321, "NaT"], dtype='<timedelta64[%s]' % unit)
            assert_equal(np.isnat(arr), res)
            arr = np.array([123, -321, "NaT"], dtype='>timedelta64[%s]' % unit)
            assert_equal(np.isnat(arr), res)

    def test_isnat_error(self):
        # Test that only datetime dtype arrays are accepted
        for t in np.typecodes["All"]:
            if t in np.typecodes["Datetime"]:
                continue
            assert_raises(TypeError, np.isnat, np.zeros(10, t))

    def test_isfinite_scalar(self):
        assert_(not np.isfinite(np.datetime64('NaT', 'ms')))
        assert_(not np.isfinite(np.datetime64('NaT', 'ns')))
        assert_(np.isfinite(np.datetime64('2038-01-19T03:14:07')))

        assert_(not np.isfinite(np.timedelta64('NaT', "ms")))
        assert_(np.isfinite(np.timedelta64(34, "ms")))

    @pytest.mark.parametrize('unit', ['Y', 'M', 'W', 'D', 'h', 'm', 's', 'ms',
                                      'us', 'ns', 'ps', 'fs', 'as'])
    @pytest.mark.parametrize('dstr', ['<datetime64[%s]', '>datetime64[%s]',
                                      '<timedelta64[%s]', '>timedelta64[%s]'])
    def test_isfinite_isinf_isnan_units(self, unit, dstr):
        '''check isfinite, isinf, isnan for all units of <M, >M, <m, >m dtypes
        '''
        arr_val = [123, -321, "NaT"]
        arr = np.array(arr_val,  dtype= dstr % unit)
        pos = np.array([True, True,  False])
        neg = np.array([False, False,  True])
        false = np.array([False, False,  False])
        assert_equal(np.isfinite(arr), pos)
        assert_equal(np.isinf(arr), false)
        assert_equal(np.isnan(arr), neg)

    def test_assert_equal(self):
        assert_raises(AssertionError, assert_equal,
                np.datetime64('nat'), np.timedelta64('nat'))

    def test_corecursive_input(self):
        # construct a co-recursive list
        a, b = [], []
        a.append(b)
        b.append(a)
        obj_arr = np.array([None])
        obj_arr[0] = a

        # At some point this caused a stack overflow (gh-11154). Now raises
        # ValueError since the nested list cannot be converted to a datetime.
        assert_raises(ValueError, obj_arr.astype, 'M8')
        assert_raises(ValueError, obj_arr.astype, 'm8')

    @pytest.mark.parametrize("shape", [(), (1,)])
    def test_discovery_from_object_array(self, shape):
        arr = np.array("2020-10-10", dtype=object).reshape(shape)
        res = np.array("2020-10-10", dtype="M8").reshape(shape)
        assert res.dtype == np.dtype("M8[D]")
        assert_equal(arr.astype("M8"), res)
        arr[...] = np.bytes_("2020-10-10")  # try a numpy string type
        assert_equal(arr.astype("M8"), res)
        arr = arr.astype("S")
        assert_equal(arr.astype("S").astype("M8"), res)

    @pytest.mark.parametrize("time_unit", [
        "Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "ps", "fs", "as",
        # compound units
        "10D", "2M",
    ])
    def test_limit_symmetry(self, time_unit):
        """
        Dates should have symmetric limits around the unix epoch at +/-np.int64
        """
        epoch = np.datetime64(0, time_unit)
        latest = np.datetime64(np.iinfo(np.int64).max, time_unit)
        earliest = np.datetime64(-np.iinfo(np.int64).max, time_unit)

        # above should not have overflowed
        assert earliest < epoch < latest

    @pytest.mark.parametrize("time_unit", [
        "Y", "M",
        pytest.param("W", marks=pytest.mark.xfail(reason="gh-13197")),
        "D", "h", "m",
        "s", "ms", "us", "ns", "ps", "fs", "as",
        pytest.param("10D", marks=pytest.mark.xfail(reason="similar to gh-13197")),
    ])
    @pytest.mark.parametrize("sign", [-1, 1])
    def test_limit_str_roundtrip(self, time_unit, sign):
        """
        Limits should roundtrip when converted to strings.

        This tests the conversion to and from npy_datetimestruct.
        """
        # TODO: add absolute (gold standard) time span limit strings
        limit = np.datetime64(np.iinfo(np.int64).max * sign, time_unit)

        # Convert to string and back. Explicit unit needed since the day and
        # week reprs are not distinguishable.
        limit_via_str = np.datetime64(str(limit), time_unit)
        assert limit_via_str == limit


class TestDateTimeData:

    def test_basic(self):
        a = np.array(['1980-03-23'], dtype=np.datetime64)
        assert_equal(np.datetime_data(a.dtype), ('D', 1))

    def test_bytes(self):
        # byte units are converted to unicode
        dt = np.datetime64('2000', (b'ms', 5))
        assert np.datetime_data(dt.dtype) == ('ms', 5)

        dt = np.datetime64('2000', b'5ms')
        assert np.datetime_data(dt.dtype) == ('ms', 5)

    def test_non_ascii(self):
        # μs is normalized to μ
        dt = np.datetime64('2000', ('μs', 5))
        assert np.datetime_data(dt.dtype) == ('us', 5)

        dt = np.datetime64('2000', '5μs')
        assert np.datetime_data(dt.dtype) == ('us', 5)


def test_comparisons_return_not_implemented():
    # GH#17017

    class custom:
        __array_priority__ = 10000

    obj = custom()

    dt = np.datetime64('2000', 'ns')
    td = dt - dt

    for item in [dt, td]:
        assert item.__eq__(obj) is NotImplemented
        assert item.__ne__(obj) is NotImplemented
        assert item.__le__(obj) is NotImplemented
        assert item.__lt__(obj) is NotImplemented
        assert item.__ge__(obj) is NotImplemented
        assert item.__gt__(obj) is NotImplemented

Youez - 2016 - github.com/yon3zu
LinuXploit