1
2import numpy
3import numpy as np
4import datetime
5import pytest
6from numpy.testing import (
7    assert_, assert_equal, assert_raises, assert_warns, suppress_warnings,
8    assert_raises_regex,
9    )
10from numpy.compat import pickle
11
12# Use pytz to test out various time zones if available
13try:
14    from pytz import timezone as tz
15    _has_pytz = True
16except ImportError:
17    _has_pytz = False
18
19try:
20    RecursionError
21except NameError:
22    RecursionError = RuntimeError  # python < 3.5
23
24
25class TestDateTime:
26    def test_datetime_dtype_creation(self):
27        for unit in ['Y', 'M', 'W', 'D',
28                     'h', 'm', 's', 'ms', 'us',
29                     'μs',  # alias for us
30                     'ns', 'ps', 'fs', 'as']:
31            dt1 = np.dtype('M8[750%s]' % unit)
32            assert_(dt1 == np.dtype('datetime64[750%s]' % unit))
33            dt2 = np.dtype('m8[%s]' % unit)
34            assert_(dt2 == np.dtype('timedelta64[%s]' % unit))
35
36        # Generic units shouldn't add [] to the end
37        assert_equal(str(np.dtype("M8")), "datetime64")
38
39        # Should be possible to specify the endianness
40        assert_equal(np.dtype("=M8"), np.dtype("M8"))
41        assert_equal(np.dtype("=M8[s]"), np.dtype("M8[s]"))
42        assert_(np.dtype(">M8") == np.dtype("M8") or
43                np.dtype("<M8") == np.dtype("M8"))
44        assert_(np.dtype(">M8[D]") == np.dtype("M8[D]") or
45                np.dtype("<M8[D]") == np.dtype("M8[D]"))
46        assert_(np.dtype(">M8") != np.dtype("<M8"))
47
48        assert_equal(np.dtype("=m8"), np.dtype("m8"))
49        assert_equal(np.dtype("=m8[s]"), np.dtype("m8[s]"))
50        assert_(np.dtype(">m8") == np.dtype("m8") or
51                np.dtype("<m8") == np.dtype("m8"))
52        assert_(np.dtype(">m8[D]") == np.dtype("m8[D]") or
53                np.dtype("<m8[D]") == np.dtype("m8[D]"))
54        assert_(np.dtype(">m8") != np.dtype("<m8"))
55
56        # Check that the parser rejects bad datetime types
57        assert_raises(TypeError, np.dtype, 'M8[badunit]')
58        assert_raises(TypeError, np.dtype, 'm8[badunit]')
59        assert_raises(TypeError, np.dtype, 'M8[YY]')
60        assert_raises(TypeError, np.dtype, 'm8[YY]')
61        assert_raises(TypeError, np.dtype, 'm4')
62        assert_raises(TypeError, np.dtype, 'M7')
63        assert_raises(TypeError, np.dtype, 'm7')
64        assert_raises(TypeError, np.dtype, 'M16')
65        assert_raises(TypeError, np.dtype, 'm16')
66
67    def test_datetime_casting_rules(self):
68        # Cannot cast safely/same_kind between timedelta and datetime
69        assert_(not np.can_cast('m8', 'M8', casting='same_kind'))
70        assert_(not np.can_cast('M8', 'm8', casting='same_kind'))
71        assert_(not np.can_cast('m8', 'M8', casting='safe'))
72        assert_(not np.can_cast('M8', 'm8', casting='safe'))
73
74        # Can cast safely/same_kind from integer to timedelta
75        assert_(np.can_cast('i8', 'm8', casting='same_kind'))
76        assert_(np.can_cast('i8', 'm8', casting='safe'))
77        assert_(np.can_cast('i4', 'm8', casting='same_kind'))
78        assert_(np.can_cast('i4', 'm8', casting='safe'))
79        assert_(np.can_cast('u4', 'm8', casting='same_kind'))
80        assert_(np.can_cast('u4', 'm8', casting='safe'))
81
82        # Cannot cast safely from unsigned integer of the same size, which
83        # could overflow
84        assert_(np.can_cast('u8', 'm8', casting='same_kind'))
85        assert_(not np.can_cast('u8', 'm8', casting='safe'))
86
87        # Cannot cast safely/same_kind from float to timedelta
88        assert_(not np.can_cast('f4', 'm8', casting='same_kind'))
89        assert_(not np.can_cast('f4', 'm8', casting='safe'))
90
91        # Cannot cast safely/same_kind from integer to datetime
92        assert_(not np.can_cast('i8', 'M8', casting='same_kind'))
93        assert_(not np.can_cast('i8', 'M8', casting='safe'))
94
95        # Cannot cast safely/same_kind from bool to datetime
96        assert_(not np.can_cast('b1', 'M8', casting='same_kind'))
97        assert_(not np.can_cast('b1', 'M8', casting='safe'))
98        # Can cast safely/same_kind from bool to timedelta
99        assert_(np.can_cast('b1', 'm8', casting='same_kind'))
100        assert_(np.can_cast('b1', 'm8', casting='safe'))
101
102        # Can cast datetime safely from months/years to days
103        assert_(np.can_cast('M8[M]', 'M8[D]', casting='safe'))
104        assert_(np.can_cast('M8[Y]', 'M8[D]', casting='safe'))
105        # Cannot cast timedelta safely from months/years to days
106        assert_(not np.can_cast('m8[M]', 'm8[D]', casting='safe'))
107        assert_(not np.can_cast('m8[Y]', 'm8[D]', casting='safe'))
108        # Can cast datetime same_kind from months/years to days
109        assert_(np.can_cast('M8[M]', 'M8[D]', casting='same_kind'))
110        assert_(np.can_cast('M8[Y]', 'M8[D]', casting='same_kind'))
111        # Can't cast timedelta same_kind from months/years to days
112        assert_(not np.can_cast('m8[M]', 'm8[D]', casting='same_kind'))
113        assert_(not np.can_cast('m8[Y]', 'm8[D]', casting='same_kind'))
114        # Can cast datetime same_kind across the date/time boundary
115        assert_(np.can_cast('M8[D]', 'M8[h]', casting='same_kind'))
116        # Can cast timedelta same_kind across the date/time boundary
117        assert_(np.can_cast('m8[D]', 'm8[h]', casting='same_kind'))
118        assert_(np.can_cast('m8[h]', 'm8[D]', casting='same_kind'))
119
120        # Cannot cast safely if the integer multiplier doesn't divide
121        assert_(not np.can_cast('M8[7h]', 'M8[3h]', casting='safe'))
122        assert_(not np.can_cast('M8[3h]', 'M8[6h]', casting='safe'))
123        # But can cast same_kind
124        assert_(np.can_cast('M8[7h]', 'M8[3h]', casting='same_kind'))
125        # Can cast safely if the integer multiplier does divide
126        assert_(np.can_cast('M8[6h]', 'M8[3h]', casting='safe'))
127
128        # We can always cast types with generic units (corresponding to NaT) to
129        # more specific types
130        assert_(np.can_cast('m8', 'm8[h]', casting='same_kind'))
131        assert_(np.can_cast('m8', 'm8[h]', casting='safe'))
132        assert_(np.can_cast('M8', 'M8[h]', casting='same_kind'))
133        assert_(np.can_cast('M8', 'M8[h]', casting='safe'))
134        # but not the other way around
135        assert_(not np.can_cast('m8[h]', 'm8', casting='same_kind'))
136        assert_(not np.can_cast('m8[h]', 'm8', casting='safe'))
137        assert_(not np.can_cast('M8[h]', 'M8', casting='same_kind'))
138        assert_(not np.can_cast('M8[h]', 'M8', casting='safe'))
139
140    def test_compare_generic_nat(self):
141        # regression tests for gh-6452
142        assert_(np.datetime64('NaT') !=
143                np.datetime64('2000') + np.timedelta64('NaT'))
144        assert_(np.datetime64('NaT') != np.datetime64('NaT', 'us'))
145        assert_(np.datetime64('NaT', 'us') != np.datetime64('NaT'))
146
147    @pytest.mark.parametrize("size", [
148        3, 21, 217, 1000])
149    def test_datetime_nat_argsort_stability(self, size):
150        # NaT < NaT should be False internally for
151        # sort stability
152        expected = np.arange(size)
153        arr = np.tile(np.datetime64('NaT'), size)
154        assert_equal(np.argsort(arr, kind='mergesort'), expected)
155
156    @pytest.mark.parametrize("size", [
157        3, 21, 217, 1000])
158    def test_timedelta_nat_argsort_stability(self, size):
159        # NaT < NaT should be False internally for
160        # sort stability
161        expected = np.arange(size)
162        arr = np.tile(np.timedelta64('NaT'), size)
163        assert_equal(np.argsort(arr, kind='mergesort'), expected)
164
165    @pytest.mark.parametrize("arr, expected", [
166        # the example provided in gh-12629
167        (['NaT', 1, 2, 3],
168         [1, 2, 3, 'NaT']),
169        # multiple NaTs
170        (['NaT', 9, 'NaT', -707],
171         [-707, 9, 'NaT', 'NaT']),
172        # this sort explores another code path for NaT
173        ([1, -2, 3, 'NaT'],
174         [-2, 1, 3, 'NaT']),
175        # 2-D array
176        ([[51, -220, 'NaT'],
177          [-17, 'NaT', -90]],
178         [[-220, 51, 'NaT'],
179          [-90, -17, 'NaT']]),
180        ])
181    @pytest.mark.parametrize("dtype", [
182        'M8[ns]', 'M8[us]',
183        'm8[ns]', 'm8[us]'])
184    def test_datetime_timedelta_sort_nat(self, arr, expected, dtype):
185        # fix for gh-12629 and gh-15063; NaT sorting to end of array
186        arr = np.array(arr, dtype=dtype)
187        expected = np.array(expected, dtype=dtype)
188        arr.sort()
189        assert_equal(arr, expected)
190
191    def test_datetime_scalar_construction(self):
192        # Construct with different units
193        assert_equal(np.datetime64('1950-03-12', 'D'),
194                     np.datetime64('1950-03-12'))
195        assert_equal(np.datetime64('1950-03-12T13', 's'),
196                     np.datetime64('1950-03-12T13', 'm'))
197
198        # Default construction means NaT
199        assert_equal(np.datetime64(), np.datetime64('NaT'))
200
201        # Some basic strings and repr
202        assert_equal(str(np.datetime64('NaT')), 'NaT')
203        assert_equal(repr(np.datetime64('NaT')),
204                     "numpy.datetime64('NaT')")
205        assert_equal(str(np.datetime64('2011-02')), '2011-02')
206        assert_equal(repr(np.datetime64('2011-02')),
207                     "numpy.datetime64('2011-02')")
208
209        # None gets constructed as NaT
210        assert_equal(np.datetime64(None), np.datetime64('NaT'))
211
212        # Default construction of NaT is in generic units
213        assert_equal(np.datetime64().dtype, np.dtype('M8'))
214        assert_equal(np.datetime64('NaT').dtype, np.dtype('M8'))
215
216        # Construction from integers requires a specified unit
217        assert_raises(ValueError, np.datetime64, 17)
218
219        # When constructing from a scalar or zero-dimensional array,
220        # it either keeps the units or you can override them.
221        a = np.datetime64('2000-03-18T16', 'h')
222        b = np.array('2000-03-18T16', dtype='M8[h]')
223
224        assert_equal(a.dtype, np.dtype('M8[h]'))
225        assert_equal(b.dtype, np.dtype('M8[h]'))
226
227        assert_equal(np.datetime64(a), a)
228        assert_equal(np.datetime64(a).dtype, np.dtype('M8[h]'))
229
230        assert_equal(np.datetime64(b), a)
231        assert_equal(np.datetime64(b).dtype, np.dtype('M8[h]'))
232
233        assert_equal(np.datetime64(a, 's'), a)
234        assert_equal(np.datetime64(a, 's').dtype, np.dtype('M8[s]'))
235
236        assert_equal(np.datetime64(b, 's'), a)
237        assert_equal(np.datetime64(b, 's').dtype, np.dtype('M8[s]'))
238
239        # Construction from datetime.date
240        assert_equal(np.datetime64('1945-03-25'),
241                     np.datetime64(datetime.date(1945, 3, 25)))
242        assert_equal(np.datetime64('2045-03-25', 'D'),
243                     np.datetime64(datetime.date(2045, 3, 25), 'D'))
244        # Construction from datetime.datetime
245        assert_equal(np.datetime64('1980-01-25T14:36:22.5'),
246                     np.datetime64(datetime.datetime(1980, 1, 25,
247                                                14, 36, 22, 500000)))
248
249        # Construction with time units from a date is okay
250        assert_equal(np.datetime64('1920-03-13', 'h'),
251                     np.datetime64('1920-03-13T00'))
252        assert_equal(np.datetime64('1920-03', 'm'),
253                     np.datetime64('1920-03-01T00:00'))
254        assert_equal(np.datetime64('1920', 's'),
255                     np.datetime64('1920-01-01T00:00:00'))
256        assert_equal(np.datetime64(datetime.date(2045, 3, 25), 'ms'),
257                     np.datetime64('2045-03-25T00:00:00.000'))
258
259        # Construction with date units from a datetime is also okay
260        assert_equal(np.datetime64('1920-03-13T18', 'D'),
261                     np.datetime64('1920-03-13'))
262        assert_equal(np.datetime64('1920-03-13T18:33:12', 'M'),
263                     np.datetime64('1920-03'))
264        assert_equal(np.datetime64('1920-03-13T18:33:12.5', 'Y'),
265                     np.datetime64('1920'))
266
267    def test_datetime_scalar_construction_timezone(self):
268        # verify that supplying an explicit timezone works, but is deprecated
269        with assert_warns(DeprecationWarning):
270            assert_equal(np.datetime64('2000-01-01T00Z'),
271                         np.datetime64('2000-01-01T00'))
272        with assert_warns(DeprecationWarning):
273            assert_equal(np.datetime64('2000-01-01T00-08'),
274                         np.datetime64('2000-01-01T08'))
275
276    def test_datetime_array_find_type(self):
277        dt = np.datetime64('1970-01-01', 'M')
278        arr = np.array([dt])
279        assert_equal(arr.dtype, np.dtype('M8[M]'))
280
281        # at the moment, we don't automatically convert these to datetime64
282
283        dt = datetime.date(1970, 1, 1)
284        arr = np.array([dt])
285        assert_equal(arr.dtype, np.dtype('O'))
286
287        dt = datetime.datetime(1970, 1, 1, 12, 30, 40)
288        arr = np.array([dt])
289        assert_equal(arr.dtype, np.dtype('O'))
290
291        # find "supertype" for non-dates and dates
292
293        b = np.bool_(True)
294        dm = np.datetime64('1970-01-01', 'M')
295        d = datetime.date(1970, 1, 1)
296        dt = datetime.datetime(1970, 1, 1, 12, 30, 40)
297
298        arr = np.array([b, dm])
299        assert_equal(arr.dtype, np.dtype('O'))
300
301        arr = np.array([b, d])
302        assert_equal(arr.dtype, np.dtype('O'))
303
304        arr = np.array([b, dt])
305        assert_equal(arr.dtype, np.dtype('O'))
306
307        arr = np.array([d, d]).astype('datetime64')
308        assert_equal(arr.dtype, np.dtype('M8[D]'))
309
310        arr = np.array([dt, dt]).astype('datetime64')
311        assert_equal(arr.dtype, np.dtype('M8[us]'))
312
313    @pytest.mark.parametrize("unit", [
314    # test all date / time units and use
315    # "generic" to select generic unit
316    ("Y"), ("M"), ("W"), ("D"), ("h"), ("m"),
317    ("s"), ("ms"), ("us"), ("ns"), ("ps"),
318    ("fs"), ("as"), ("generic") ])
319    def test_timedelta_np_int_construction(self, unit):
320        # regression test for gh-7617
321        if unit != "generic":
322            assert_equal(np.timedelta64(np.int64(123), unit),
323                         np.timedelta64(123, unit))
324        else:
325            assert_equal(np.timedelta64(np.int64(123)),
326                         np.timedelta64(123))
327
328    def test_timedelta_scalar_construction(self):
329        # Construct with different units
330        assert_equal(np.timedelta64(7, 'D'),
331                     np.timedelta64(1, 'W'))
332        assert_equal(np.timedelta64(120, 's'),
333                     np.timedelta64(2, 'm'))
334
335        # Default construction means 0
336        assert_equal(np.timedelta64(), np.timedelta64(0))
337
338        # None gets constructed as NaT
339        assert_equal(np.timedelta64(None), np.timedelta64('NaT'))
340
341        # Some basic strings and repr
342        assert_equal(str(np.timedelta64('NaT')), 'NaT')
343        assert_equal(repr(np.timedelta64('NaT')),
344                     "numpy.timedelta64('NaT')")
345        assert_equal(str(np.timedelta64(3, 's')), '3 seconds')
346        assert_equal(repr(np.timedelta64(-3, 's')),
347                     "numpy.timedelta64(-3,'s')")
348        assert_equal(repr(np.timedelta64(12)),
349                     "numpy.timedelta64(12)")
350
351        # Construction from an integer produces generic units
352        assert_equal(np.timedelta64(12).dtype, np.dtype('m8'))
353
354        # When constructing from a scalar or zero-dimensional array,
355        # it either keeps the units or you can override them.
356        a = np.timedelta64(2, 'h')
357        b = np.array(2, dtype='m8[h]')
358
359        assert_equal(a.dtype, np.dtype('m8[h]'))
360        assert_equal(b.dtype, np.dtype('m8[h]'))
361
362        assert_equal(np.timedelta64(a), a)
363        assert_equal(np.timedelta64(a).dtype, np.dtype('m8[h]'))
364
365        assert_equal(np.timedelta64(b), a)
366        assert_equal(np.timedelta64(b).dtype, np.dtype('m8[h]'))
367
368        assert_equal(np.timedelta64(a, 's'), a)
369        assert_equal(np.timedelta64(a, 's').dtype, np.dtype('m8[s]'))
370
371        assert_equal(np.timedelta64(b, 's'), a)
372        assert_equal(np.timedelta64(b, 's').dtype, np.dtype('m8[s]'))
373
374        # Construction from datetime.timedelta
375        assert_equal(np.timedelta64(5, 'D'),
376                     np.timedelta64(datetime.timedelta(days=5)))
377        assert_equal(np.timedelta64(102347621, 's'),
378                     np.timedelta64(datetime.timedelta(seconds=102347621)))
379        assert_equal(np.timedelta64(-10234760000, 'us'),
380                     np.timedelta64(datetime.timedelta(
381                                            microseconds=-10234760000)))
382        assert_equal(np.timedelta64(10234760000, 'us'),
383                     np.timedelta64(datetime.timedelta(
384                                            microseconds=10234760000)))
385        assert_equal(np.timedelta64(1023476, 'ms'),
386                     np.timedelta64(datetime.timedelta(milliseconds=1023476)))
387        assert_equal(np.timedelta64(10, 'm'),
388                     np.timedelta64(datetime.timedelta(minutes=10)))
389        assert_equal(np.timedelta64(281, 'h'),
390                     np.timedelta64(datetime.timedelta(hours=281)))
391        assert_equal(np.timedelta64(28, 'W'),
392                     np.timedelta64(datetime.timedelta(weeks=28)))
393
394        # Cannot construct across nonlinear time unit boundaries
395        a = np.timedelta64(3, 's')
396        assert_raises(TypeError, np.timedelta64, a, 'M')
397        assert_raises(TypeError, np.timedelta64, a, 'Y')
398        a = np.timedelta64(6, 'M')
399        assert_raises(TypeError, np.timedelta64, a, 'D')
400        assert_raises(TypeError, np.timedelta64, a, 'h')
401        a = np.timedelta64(1, 'Y')
402        assert_raises(TypeError, np.timedelta64, a, 'D')
403        assert_raises(TypeError, np.timedelta64, a, 'm')
404        a = datetime.timedelta(seconds=3)
405        assert_raises(TypeError, np.timedelta64, a, 'M')
406        assert_raises(TypeError, np.timedelta64, a, 'Y')
407        a = datetime.timedelta(weeks=3)
408        assert_raises(TypeError, np.timedelta64, a, 'M')
409        assert_raises(TypeError, np.timedelta64, a, 'Y')
410        a = datetime.timedelta()
411        assert_raises(TypeError, np.timedelta64, a, 'M')
412        assert_raises(TypeError, np.timedelta64, a, 'Y')
413
414    def test_timedelta_object_array_conversion(self):
415        # Regression test for gh-11096
416        inputs = [datetime.timedelta(28),
417                  datetime.timedelta(30),
418                  datetime.timedelta(31)]
419        expected = np.array([28, 30, 31], dtype='timedelta64[D]')
420        actual = np.array(inputs, dtype='timedelta64[D]')
421        assert_equal(expected, actual)
422
423    def test_timedelta_0_dim_object_array_conversion(self):
424        # Regression test for gh-11151
425        test = np.array(datetime.timedelta(seconds=20))
426        actual = test.astype(np.timedelta64)
427        # expected value from the array constructor workaround
428        # described in above issue
429        expected = np.array(datetime.timedelta(seconds=20),
430                            np.timedelta64)
431        assert_equal(actual, expected)
432
433    def test_timedelta_nat_format(self):
434        # gh-17552
435        assert_equal('NaT', '{0}'.format(np.timedelta64('nat')))
436
437    def test_timedelta_scalar_construction_units(self):
438        # String construction detecting units
439        assert_equal(np.datetime64('2010').dtype,
440                     np.dtype('M8[Y]'))
441        assert_equal(np.datetime64('2010-03').dtype,
442                     np.dtype('M8[M]'))
443        assert_equal(np.datetime64('2010-03-12').dtype,
444                     np.dtype('M8[D]'))
445        assert_equal(np.datetime64('2010-03-12T17').dtype,
446                     np.dtype('M8[h]'))
447        assert_equal(np.datetime64('2010-03-12T17:15').dtype,
448                     np.dtype('M8[m]'))
449        assert_equal(np.datetime64('2010-03-12T17:15:08').dtype,
450                     np.dtype('M8[s]'))
451
452        assert_equal(np.datetime64('2010-03-12T17:15:08.1').dtype,
453                     np.dtype('M8[ms]'))
454        assert_equal(np.datetime64('2010-03-12T17:15:08.12').dtype,
455                     np.dtype('M8[ms]'))
456        assert_equal(np.datetime64('2010-03-12T17:15:08.123').dtype,
457                     np.dtype('M8[ms]'))
458
459        assert_equal(np.datetime64('2010-03-12T17:15:08.1234').dtype,
460                     np.dtype('M8[us]'))
461        assert_equal(np.datetime64('2010-03-12T17:15:08.12345').dtype,
462                     np.dtype('M8[us]'))
463        assert_equal(np.datetime64('2010-03-12T17:15:08.123456').dtype,
464                     np.dtype('M8[us]'))
465
466        assert_equal(np.datetime64('1970-01-01T00:00:02.1234567').dtype,
467                     np.dtype('M8[ns]'))
468        assert_equal(np.datetime64('1970-01-01T00:00:02.12345678').dtype,
469                     np.dtype('M8[ns]'))
470        assert_equal(np.datetime64('1970-01-01T00:00:02.123456789').dtype,
471                     np.dtype('M8[ns]'))
472
473        assert_equal(np.datetime64('1970-01-01T00:00:02.1234567890').dtype,
474                     np.dtype('M8[ps]'))
475        assert_equal(np.datetime64('1970-01-01T00:00:02.12345678901').dtype,
476                     np.dtype('M8[ps]'))
477        assert_equal(np.datetime64('1970-01-01T00:00:02.123456789012').dtype,
478                     np.dtype('M8[ps]'))
479
480        assert_equal(np.datetime64(
481                     '1970-01-01T00:00:02.1234567890123').dtype,
482                     np.dtype('M8[fs]'))
483        assert_equal(np.datetime64(
484                     '1970-01-01T00:00:02.12345678901234').dtype,
485                     np.dtype('M8[fs]'))
486        assert_equal(np.datetime64(
487                     '1970-01-01T00:00:02.123456789012345').dtype,
488                     np.dtype('M8[fs]'))
489
490        assert_equal(np.datetime64(
491                    '1970-01-01T00:00:02.1234567890123456').dtype,
492                     np.dtype('M8[as]'))
493        assert_equal(np.datetime64(
494                    '1970-01-01T00:00:02.12345678901234567').dtype,
495                     np.dtype('M8[as]'))
496        assert_equal(np.datetime64(
497                    '1970-01-01T00:00:02.123456789012345678').dtype,
498                     np.dtype('M8[as]'))
499
500        # Python date object
501        assert_equal(np.datetime64(datetime.date(2010, 4, 16)).dtype,
502                     np.dtype('M8[D]'))
503
504        # Python datetime object
505        assert_equal(np.datetime64(
506                        datetime.datetime(2010, 4, 16, 13, 45, 18)).dtype,
507                     np.dtype('M8[us]'))
508
509        # 'today' special value
510        assert_equal(np.datetime64('today').dtype,
511                     np.dtype('M8[D]'))
512
513        # 'now' special value
514        assert_equal(np.datetime64('now').dtype,
515                     np.dtype('M8[s]'))
516
517    def test_datetime_nat_casting(self):
518        a = np.array('NaT', dtype='M8[D]')
519        b = np.datetime64('NaT', '[D]')
520
521        # Arrays
522        assert_equal(a.astype('M8[s]'), np.array('NaT', dtype='M8[s]'))
523        assert_equal(a.astype('M8[ms]'), np.array('NaT', dtype='M8[ms]'))
524        assert_equal(a.astype('M8[M]'), np.array('NaT', dtype='M8[M]'))
525        assert_equal(a.astype('M8[Y]'), np.array('NaT', dtype='M8[Y]'))
526        assert_equal(a.astype('M8[W]'), np.array('NaT', dtype='M8[W]'))
527
528        # Scalars -> Scalars
529        assert_equal(np.datetime64(b, '[s]'), np.datetime64('NaT', '[s]'))
530        assert_equal(np.datetime64(b, '[ms]'), np.datetime64('NaT', '[ms]'))
531        assert_equal(np.datetime64(b, '[M]'), np.datetime64('NaT', '[M]'))
532        assert_equal(np.datetime64(b, '[Y]'), np.datetime64('NaT', '[Y]'))
533        assert_equal(np.datetime64(b, '[W]'), np.datetime64('NaT', '[W]'))
534
535        # Arrays -> Scalars
536        assert_equal(np.datetime64(a, '[s]'), np.datetime64('NaT', '[s]'))
537        assert_equal(np.datetime64(a, '[ms]'), np.datetime64('NaT', '[ms]'))
538        assert_equal(np.datetime64(a, '[M]'), np.datetime64('NaT', '[M]'))
539        assert_equal(np.datetime64(a, '[Y]'), np.datetime64('NaT', '[Y]'))
540        assert_equal(np.datetime64(a, '[W]'), np.datetime64('NaT', '[W]'))
541
542        # NaN -> NaT
543        nan = np.array([np.nan] * 8)
544        fnan = nan.astype('f')
545        lnan = nan.astype('g')
546        cnan = nan.astype('D')
547        cfnan = nan.astype('F')
548        clnan = nan.astype('G')
549
550        nat = np.array([np.datetime64('NaT')] * 8)
551        assert_equal(nan.astype('M8[ns]'), nat)
552        assert_equal(fnan.astype('M8[ns]'), nat)
553        assert_equal(lnan.astype('M8[ns]'), nat)
554        assert_equal(cnan.astype('M8[ns]'), nat)
555        assert_equal(cfnan.astype('M8[ns]'), nat)
556        assert_equal(clnan.astype('M8[ns]'), nat)
557
558        nat = np.array([np.timedelta64('NaT')] * 8)
559        assert_equal(nan.astype('timedelta64[ns]'), nat)
560        assert_equal(fnan.astype('timedelta64[ns]'), nat)
561        assert_equal(lnan.astype('timedelta64[ns]'), nat)
562        assert_equal(cnan.astype('timedelta64[ns]'), nat)
563        assert_equal(cfnan.astype('timedelta64[ns]'), nat)
564        assert_equal(clnan.astype('timedelta64[ns]'), nat)
565
566    def test_days_creation(self):
567        assert_equal(np.array('1599', dtype='M8[D]').astype('i8'),
568                (1600-1970)*365 - (1972-1600)/4 + 3 - 365)
569        assert_equal(np.array('1600', dtype='M8[D]').astype('i8'),
570                (1600-1970)*365 - (1972-1600)/4 + 3)
571        assert_equal(np.array('1601', dtype='M8[D]').astype('i8'),
572                (1600-1970)*365 - (1972-1600)/4 + 3 + 366)
573        assert_equal(np.array('1900', dtype='M8[D]').astype('i8'),
574                (1900-1970)*365 - (1970-1900)//4)
575        assert_equal(np.array('1901', dtype='M8[D]').astype('i8'),
576                (1900-1970)*365 - (1970-1900)//4 + 365)
577        assert_equal(np.array('1967', dtype='M8[D]').astype('i8'), -3*365 - 1)
578        assert_equal(np.array('1968', dtype='M8[D]').astype('i8'), -2*365 - 1)
579        assert_equal(np.array('1969', dtype='M8[D]').astype('i8'), -1*365)
580        assert_equal(np.array('1970', dtype='M8[D]').astype('i8'), 0*365)
581        assert_equal(np.array('1971', dtype='M8[D]').astype('i8'), 1*365)
582        assert_equal(np.array('1972', dtype='M8[D]').astype('i8'), 2*365)
583        assert_equal(np.array('1973', dtype='M8[D]').astype('i8'), 3*365 + 1)
584        assert_equal(np.array('1974', dtype='M8[D]').astype('i8'), 4*365 + 1)
585        assert_equal(np.array('2000', dtype='M8[D]').astype('i8'),
586                 (2000 - 1970)*365 + (2000 - 1972)//4)
587        assert_equal(np.array('2001', dtype='M8[D]').astype('i8'),
588                 (2000 - 1970)*365 + (2000 - 1972)//4 + 366)
589        assert_equal(np.array('2400', dtype='M8[D]').astype('i8'),
590                 (2400 - 1970)*365 + (2400 - 1972)//4 - 3)
591        assert_equal(np.array('2401', dtype='M8[D]').astype('i8'),
592                 (2400 - 1970)*365 + (2400 - 1972)//4 - 3 + 366)
593
594        assert_equal(np.array('1600-02-29', dtype='M8[D]').astype('i8'),
595                (1600-1970)*365 - (1972-1600)//4 + 3 + 31 + 28)
596        assert_equal(np.array('1600-03-01', dtype='M8[D]').astype('i8'),
597                (1600-1970)*365 - (1972-1600)//4 + 3 + 31 + 29)
598        assert_equal(np.array('2000-02-29', dtype='M8[D]').astype('i8'),
599                 (2000 - 1970)*365 + (2000 - 1972)//4 + 31 + 28)
600        assert_equal(np.array('2000-03-01', dtype='M8[D]').astype('i8'),
601                 (2000 - 1970)*365 + (2000 - 1972)//4 + 31 + 29)
602        assert_equal(np.array('2001-03-22', dtype='M8[D]').astype('i8'),
603                 (2000 - 1970)*365 + (2000 - 1972)//4 + 366 + 31 + 28 + 21)
604
605    def test_days_to_pydate(self):
606        assert_equal(np.array('1599', dtype='M8[D]').astype('O'),
607                    datetime.date(1599, 1, 1))
608        assert_equal(np.array('1600', dtype='M8[D]').astype('O'),
609                    datetime.date(1600, 1, 1))
610        assert_equal(np.array('1601', dtype='M8[D]').astype('O'),
611                    datetime.date(1601, 1, 1))
612        assert_equal(np.array('1900', dtype='M8[D]').astype('O'),
613                    datetime.date(1900, 1, 1))
614        assert_equal(np.array('1901', dtype='M8[D]').astype('O'),
615                    datetime.date(1901, 1, 1))
616        assert_equal(np.array('2000', dtype='M8[D]').astype('O'),
617                    datetime.date(2000, 1, 1))
618        assert_equal(np.array('2001', dtype='M8[D]').astype('O'),
619                    datetime.date(2001, 1, 1))
620        assert_equal(np.array('1600-02-29', dtype='M8[D]').astype('O'),
621                    datetime.date(1600, 2, 29))
622        assert_equal(np.array('1600-03-01', dtype='M8[D]').astype('O'),
623                    datetime.date(1600, 3, 1))
624        assert_equal(np.array('2001-03-22', dtype='M8[D]').astype('O'),
625                    datetime.date(2001, 3, 22))
626
627    def test_dtype_comparison(self):
628        assert_(not (np.dtype('M8[us]') == np.dtype('M8[ms]')))
629        assert_(np.dtype('M8[us]') != np.dtype('M8[ms]'))
630        assert_(np.dtype('M8[2D]') != np.dtype('M8[D]'))
631        assert_(np.dtype('M8[D]') != np.dtype('M8[2D]'))
632
633    def test_pydatetime_creation(self):
634        a = np.array(['1960-03-12', datetime.date(1960, 3, 12)], dtype='M8[D]')
635        assert_equal(a[0], a[1])
636        a = np.array(['1999-12-31', datetime.date(1999, 12, 31)], dtype='M8[D]')
637        assert_equal(a[0], a[1])
638        a = np.array(['2000-01-01', datetime.date(2000, 1, 1)], dtype='M8[D]')
639        assert_equal(a[0], a[1])
640        # Will fail if the date changes during the exact right moment
641        a = np.array(['today', datetime.date.today()], dtype='M8[D]')
642        assert_equal(a[0], a[1])
643        # datetime.datetime.now() returns local time, not UTC
644        #a = np.array(['now', datetime.datetime.now()], dtype='M8[s]')
645        #assert_equal(a[0], a[1])
646
647        # we can give a datetime.date time units
648        assert_equal(np.array(datetime.date(1960, 3, 12), dtype='M8[s]'),
649                     np.array(np.datetime64('1960-03-12T00:00:00')))
650
651    def test_datetime_string_conversion(self):
652        a = ['2011-03-16', '1920-01-01', '2013-05-19']
653        str_a = np.array(a, dtype='S')
654        uni_a = np.array(a, dtype='U')
655        dt_a = np.array(a, dtype='M')
656
657        # String to datetime
658        assert_equal(dt_a, str_a.astype('M'))
659        assert_equal(dt_a.dtype, str_a.astype('M').dtype)
660        dt_b = np.empty_like(dt_a)
661        dt_b[...] = str_a
662        assert_equal(dt_a, dt_b)
663
664        # Datetime to string
665        assert_equal(str_a, dt_a.astype('S0'))
666        str_b = np.empty_like(str_a)
667        str_b[...] = dt_a
668        assert_equal(str_a, str_b)
669
670        # Unicode to datetime
671        assert_equal(dt_a, uni_a.astype('M'))
672        assert_equal(dt_a.dtype, uni_a.astype('M').dtype)
673        dt_b = np.empty_like(dt_a)
674        dt_b[...] = uni_a
675        assert_equal(dt_a, dt_b)
676
677        # Datetime to unicode
678        assert_equal(uni_a, dt_a.astype('U'))
679        uni_b = np.empty_like(uni_a)
680        uni_b[...] = dt_a
681        assert_equal(uni_a, uni_b)
682
683        # Datetime to long string - gh-9712
684        assert_equal(str_a, dt_a.astype((np.string_, 128)))
685        str_b = np.empty(str_a.shape, dtype=(np.string_, 128))
686        str_b[...] = dt_a
687        assert_equal(str_a, str_b)
688
689    def test_datetime_array_str(self):
690        a = np.array(['2011-03-16', '1920-01-01', '2013-05-19'], dtype='M')
691        assert_equal(str(a), "['2011-03-16' '1920-01-01' '2013-05-19']")
692
693        a = np.array(['2011-03-16T13:55', '1920-01-01T03:12'], dtype='M')
694        assert_equal(np.array2string(a, separator=', ',
695                    formatter={'datetime': lambda x:
696                            "'%s'" % np.datetime_as_string(x, timezone='UTC')}),
697                     "['2011-03-16T13:55Z', '1920-01-01T03:12Z']")
698
699        # Check that one NaT doesn't corrupt subsequent entries
700        a = np.array(['2010', 'NaT', '2030']).astype('M')
701        assert_equal(str(a), "['2010'  'NaT' '2030']")
702
703    def test_timedelta_array_str(self):
704        a = np.array([-1, 0, 100], dtype='m')
705        assert_equal(str(a), "[ -1   0 100]")
706        a = np.array(['NaT', 'NaT'], dtype='m')
707        assert_equal(str(a), "['NaT' 'NaT']")
708        # Check right-alignment with NaTs
709        a = np.array([-1, 'NaT', 0], dtype='m')
710        assert_equal(str(a), "[   -1 'NaT'     0]")
711        a = np.array([-1, 'NaT', 1234567], dtype='m')
712        assert_equal(str(a), "[     -1   'NaT' 1234567]")
713
714        # Test with other byteorder:
715        a = np.array([-1, 'NaT', 1234567], dtype='>m')
716        assert_equal(str(a), "[     -1   'NaT' 1234567]")
717        a = np.array([-1, 'NaT', 1234567], dtype='<m')
718        assert_equal(str(a), "[     -1   'NaT' 1234567]")
719
720    def test_pickle(self):
721        # Check that pickle roundtripping works
722        for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
723            dt = np.dtype('M8[7D]')
724            assert_equal(pickle.loads(pickle.dumps(dt, protocol=proto)), dt)
725            dt = np.dtype('M8[W]')
726            assert_equal(pickle.loads(pickle.dumps(dt, protocol=proto)), dt)
727            scalar = np.datetime64('2016-01-01T00:00:00.000000000')
728            assert_equal(pickle.loads(pickle.dumps(scalar, protocol=proto)),
729                         scalar)
730            delta = scalar - np.datetime64('2015-01-01T00:00:00.000000000')
731            assert_equal(pickle.loads(pickle.dumps(delta, protocol=proto)),
732                         delta)
733
734        # Check that loading pickles from 1.6 works
735        pkl = b"cnumpy\ndtype\np0\n(S'M8'\np1\nI0\nI1\ntp2\nRp3\n" + \
736              b"(I4\nS'<'\np4\nNNNI-1\nI-1\nI0\n((dp5\n(S'D'\np6\n" + \
737              b"I7\nI1\nI1\ntp7\ntp8\ntp9\nb."
738        assert_equal(pickle.loads(pkl), np.dtype('<M8[7D]'))
739        pkl = b"cnumpy\ndtype\np0\n(S'M8'\np1\nI0\nI1\ntp2\nRp3\n" + \
740              b"(I4\nS'<'\np4\nNNNI-1\nI-1\nI0\n((dp5\n(S'W'\np6\n" + \
741              b"I1\nI1\nI1\ntp7\ntp8\ntp9\nb."
742        assert_equal(pickle.loads(pkl), np.dtype('<M8[W]'))
743        pkl = b"cnumpy\ndtype\np0\n(S'M8'\np1\nI0\nI1\ntp2\nRp3\n" + \
744              b"(I4\nS'>'\np4\nNNNI-1\nI-1\nI0\n((dp5\n(S'us'\np6\n" + \
745              b"I1\nI1\nI1\ntp7\ntp8\ntp9\nb."
746        assert_equal(pickle.loads(pkl), np.dtype('>M8[us]'))
747
748    def test_setstate(self):
749        "Verify that datetime dtype __setstate__ can handle bad arguments"
750        dt = np.dtype('>M8[us]')
751        assert_raises(ValueError, dt.__setstate__, (4, '>', None, None, None, -1, -1, 0, 1))
752        assert_(dt.__reduce__()[2] == np.dtype('>M8[us]').__reduce__()[2])
753        assert_raises(TypeError, dt.__setstate__, (4, '>', None, None, None, -1, -1, 0, ({}, 'xxx')))
754        assert_(dt.__reduce__()[2] == np.dtype('>M8[us]').__reduce__()[2])
755
756    def test_dtype_promotion(self):
757        # datetime <op> datetime computes the metadata gcd
758        # timedelta <op> timedelta computes the metadata gcd
759        for mM in ['m', 'M']:
760            assert_equal(
761                np.promote_types(np.dtype(mM+'8[2Y]'), np.dtype(mM+'8[2Y]')),
762                np.dtype(mM+'8[2Y]'))
763            assert_equal(
764                np.promote_types(np.dtype(mM+'8[12Y]'), np.dtype(mM+'8[15Y]')),
765                np.dtype(mM+'8[3Y]'))
766            assert_equal(
767                np.promote_types(np.dtype(mM+'8[62M]'), np.dtype(mM+'8[24M]')),
768                np.dtype(mM+'8[2M]'))
769            assert_equal(
770                np.promote_types(np.dtype(mM+'8[1W]'), np.dtype(mM+'8[2D]')),
771                np.dtype(mM+'8[1D]'))
772            assert_equal(
773                np.promote_types(np.dtype(mM+'8[W]'), np.dtype(mM+'8[13s]')),
774                np.dtype(mM+'8[s]'))
775            assert_equal(
776                np.promote_types(np.dtype(mM+'8[13W]'), np.dtype(mM+'8[49s]')),
777                np.dtype(mM+'8[7s]'))
778        # timedelta <op> timedelta raises when there is no reasonable gcd
779        assert_raises(TypeError, np.promote_types,
780                            np.dtype('m8[Y]'), np.dtype('m8[D]'))
781        assert_raises(TypeError, np.promote_types,
782                            np.dtype('m8[M]'), np.dtype('m8[W]'))
783        # timedelta and float cannot be safely cast with each other
784        assert_raises(TypeError, np.promote_types, "float32", "m8")
785        assert_raises(TypeError, np.promote_types, "m8", "float32")
786        assert_raises(TypeError, np.promote_types, "uint64", "m8")
787        assert_raises(TypeError, np.promote_types, "m8", "uint64")
788
789        # timedelta <op> timedelta may overflow with big unit ranges
790        assert_raises(OverflowError, np.promote_types,
791                            np.dtype('m8[W]'), np.dtype('m8[fs]'))
792        assert_raises(OverflowError, np.promote_types,
793                            np.dtype('m8[s]'), np.dtype('m8[as]'))
794
795    def test_cast_overflow(self):
796        # gh-4486
797        def cast():
798            numpy.datetime64("1971-01-01 00:00:00.000000000000000").astype("<M8[D]")
799        assert_raises(OverflowError, cast)
800
801        def cast2():
802            numpy.datetime64("2014").astype("<M8[fs]")
803        assert_raises(OverflowError, cast2)
804
805    def test_pyobject_roundtrip(self):
806        # All datetime types should be able to roundtrip through object
807        a = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0,
808                      -1020040340, -2942398, -1, 0, 1, 234523453, 1199164176],
809                                                        dtype=np.int64)
810        # With date units
811        for unit in ['M8[D]', 'M8[W]', 'M8[M]', 'M8[Y]']:
812            b = a.copy().view(dtype=unit)
813            b[0] = '-0001-01-01'
814            b[1] = '-0001-12-31'
815            b[2] = '0000-01-01'
816            b[3] = '0001-01-01'
817            b[4] = '1969-12-31'
818            b[5] = '1970-01-01'
819            b[6] = '9999-12-31'
820            b[7] = '10000-01-01'
821            b[8] = 'NaT'
822
823            assert_equal(b.astype(object).astype(unit), b,
824                            "Error roundtripping unit %s" % unit)
825        # With time units
826        for unit in ['M8[as]', 'M8[16fs]', 'M8[ps]', 'M8[us]',
827                     'M8[300as]', 'M8[20us]']:
828            b = a.copy().view(dtype=unit)
829            b[0] = '-0001-01-01T00'
830            b[1] = '-0001-12-31T00'
831            b[2] = '0000-01-01T00'
832            b[3] = '0001-01-01T00'
833            b[4] = '1969-12-31T23:59:59.999999'
834            b[5] = '1970-01-01T00'
835            b[6] = '9999-12-31T23:59:59.999999'
836            b[7] = '10000-01-01T00'
837            b[8] = 'NaT'
838
839            assert_equal(b.astype(object).astype(unit), b,
840                            "Error roundtripping unit %s" % unit)
841
842    def test_month_truncation(self):
843        # Make sure that months are truncating correctly
844        assert_equal(np.array('1945-03-01', dtype='M8[M]'),
845                     np.array('1945-03-31', dtype='M8[M]'))
846        assert_equal(np.array('1969-11-01', dtype='M8[M]'),
847             np.array('1969-11-30T23:59:59.99999', dtype='M').astype('M8[M]'))
848        assert_equal(np.array('1969-12-01', dtype='M8[M]'),
849             np.array('1969-12-31T23:59:59.99999', dtype='M').astype('M8[M]'))
850        assert_equal(np.array('1970-01-01', dtype='M8[M]'),
851             np.array('1970-01-31T23:59:59.99999', dtype='M').astype('M8[M]'))
852        assert_equal(np.array('1980-02-01', dtype='M8[M]'),
853             np.array('1980-02-29T23:59:59.99999', dtype='M').astype('M8[M]'))
854
855    def test_different_unit_comparison(self):
856        # Check some years with date units
857        for unit1 in ['Y', 'M', 'D']:
858            dt1 = np.dtype('M8[%s]' % unit1)
859            for unit2 in ['Y', 'M', 'D']:
860                dt2 = np.dtype('M8[%s]' % unit2)
861                assert_equal(np.array('1945', dtype=dt1),
862                             np.array('1945', dtype=dt2))
863                assert_equal(np.array('1970', dtype=dt1),
864                             np.array('1970', dtype=dt2))
865                assert_equal(np.array('9999', dtype=dt1),
866                             np.array('9999', dtype=dt2))
867                assert_equal(np.array('10000', dtype=dt1),
868                             np.array('10000-01-01', dtype=dt2))
869                assert_equal(np.datetime64('1945', unit1),
870                             np.datetime64('1945', unit2))
871                assert_equal(np.datetime64('1970', unit1),
872                             np.datetime64('1970', unit2))
873                assert_equal(np.datetime64('9999', unit1),
874                             np.datetime64('9999', unit2))
875                assert_equal(np.datetime64('10000', unit1),
876                             np.datetime64('10000-01-01', unit2))
877        # Check some datetimes with time units
878        for unit1 in ['6h', 'h', 'm', 's', '10ms', 'ms', 'us']:
879            dt1 = np.dtype('M8[%s]' % unit1)
880            for unit2 in ['h', 'm', 's', 'ms', 'us']:
881                dt2 = np.dtype('M8[%s]' % unit2)
882                assert_equal(np.array('1945-03-12T18', dtype=dt1),
883                             np.array('1945-03-12T18', dtype=dt2))
884                assert_equal(np.array('1970-03-12T18', dtype=dt1),
885                             np.array('1970-03-12T18', dtype=dt2))
886                assert_equal(np.array('9999-03-12T18', dtype=dt1),
887                             np.array('9999-03-12T18', dtype=dt2))
888                assert_equal(np.array('10000-01-01T00', dtype=dt1),
889                             np.array('10000-01-01T00', dtype=dt2))
890                assert_equal(np.datetime64('1945-03-12T18', unit1),
891                             np.datetime64('1945-03-12T18', unit2))
892                assert_equal(np.datetime64('1970-03-12T18', unit1),
893                             np.datetime64('1970-03-12T18', unit2))
894                assert_equal(np.datetime64('9999-03-12T18', unit1),
895                             np.datetime64('9999-03-12T18', unit2))
896                assert_equal(np.datetime64('10000-01-01T00', unit1),
897                             np.datetime64('10000-01-01T00', unit2))
898        # Check some days with units that won't overflow
899        for unit1 in ['D', '12h', 'h', 'm', 's', '4s', 'ms', 'us']:
900            dt1 = np.dtype('M8[%s]' % unit1)
901            for unit2 in ['D', 'h', 'm', 's', 'ms', 'us']:
902                dt2 = np.dtype('M8[%s]' % unit2)
903                assert_(np.equal(np.array('1932-02-17', dtype='M').astype(dt1),
904                     np.array('1932-02-17T00:00:00', dtype='M').astype(dt2),
905                     casting='unsafe'))
906                assert_(np.equal(np.array('10000-04-27', dtype='M').astype(dt1),
907                     np.array('10000-04-27T00:00:00', dtype='M').astype(dt2),
908                     casting='unsafe'))
909
910        # Shouldn't be able to compare datetime and timedelta
911        # TODO: Changing to 'same_kind' or 'safe' casting in the ufuncs by
912        #       default is needed to properly catch this kind of thing...
913        a = np.array('2012-12-21', dtype='M8[D]')
914        b = np.array(3, dtype='m8[D]')
915        #assert_raises(TypeError, np.less, a, b)
916        assert_raises(TypeError, np.less, a, b, casting='same_kind')
917
918    def test_datetime_like(self):
919        a = np.array([3], dtype='m8[4D]')
920        b = np.array(['2012-12-21'], dtype='M8[D]')
921
922        assert_equal(np.ones_like(a).dtype, a.dtype)
923        assert_equal(np.zeros_like(a).dtype, a.dtype)
924        assert_equal(np.empty_like(a).dtype, a.dtype)
925        assert_equal(np.ones_like(b).dtype, b.dtype)
926        assert_equal(np.zeros_like(b).dtype, b.dtype)
927        assert_equal(np.empty_like(b).dtype, b.dtype)
928
929    def test_datetime_unary(self):
930        for tda, tdb, tdzero, tdone, tdmone in \
931                [
932                 # One-dimensional arrays
933                 (np.array([3], dtype='m8[D]'),
934                  np.array([-3], dtype='m8[D]'),
935                  np.array([0], dtype='m8[D]'),
936                  np.array([1], dtype='m8[D]'),
937                  np.array([-1], dtype='m8[D]')),
938                 # NumPy scalars
939                 (np.timedelta64(3, '[D]'),
940                  np.timedelta64(-3, '[D]'),
941                  np.timedelta64(0, '[D]'),
942                  np.timedelta64(1, '[D]'),
943                  np.timedelta64(-1, '[D]'))]:
944            # negative ufunc
945            assert_equal(-tdb, tda)
946            assert_equal((-tdb).dtype, tda.dtype)
947            assert_equal(np.negative(tdb), tda)
948            assert_equal(np.negative(tdb).dtype, tda.dtype)
949
950            # positive ufunc
951            assert_equal(np.positive(tda), tda)
952            assert_equal(np.positive(tda).dtype, tda.dtype)
953            assert_equal(np.positive(tdb), tdb)
954            assert_equal(np.positive(tdb).dtype, tdb.dtype)
955
956            # absolute ufunc
957            assert_equal(np.absolute(tdb), tda)
958            assert_equal(np.absolute(tdb).dtype, tda.dtype)
959
960            # sign ufunc
961            assert_equal(np.sign(tda), tdone)
962            assert_equal(np.sign(tdb), tdmone)
963            assert_equal(np.sign(tdzero), tdzero)
964            assert_equal(np.sign(tda).dtype, tda.dtype)
965
966            # The ufuncs always produce native-endian results
967            assert_
968
969    def test_datetime_add(self):
970        for dta, dtb, dtc, dtnat, tda, tdb, tdc in \
971                    [
972                     # One-dimensional arrays
973                     (np.array(['2012-12-21'], dtype='M8[D]'),
974                      np.array(['2012-12-24'], dtype='M8[D]'),
975                      np.array(['2012-12-21T11'], dtype='M8[h]'),
976                      np.array(['NaT'], dtype='M8[D]'),
977                      np.array([3], dtype='m8[D]'),
978                      np.array([11], dtype='m8[h]'),
979                      np.array([3*24 + 11], dtype='m8[h]')),
980                     # NumPy scalars
981                     (np.datetime64('2012-12-21', '[D]'),
982                      np.datetime64('2012-12-24', '[D]'),
983                      np.datetime64('2012-12-21T11', '[h]'),
984                      np.datetime64('NaT', '[D]'),
985                      np.timedelta64(3, '[D]'),
986                      np.timedelta64(11, '[h]'),
987                      np.timedelta64(3*24 + 11, '[h]'))]:
988            # m8 + m8
989            assert_equal(tda + tdb, tdc)
990            assert_equal((tda + tdb).dtype, np.dtype('m8[h]'))
991            # m8 + bool
992            assert_equal(tdb + True, tdb + 1)
993            assert_equal((tdb + True).dtype, np.dtype('m8[h]'))
994            # m8 + int
995            assert_equal(tdb + 3*24, tdc)
996            assert_equal((tdb + 3*24).dtype, np.dtype('m8[h]'))
997            # bool + m8
998            assert_equal(False + tdb, tdb)
999            assert_equal((False + tdb).dtype, np.dtype('m8[h]'))
1000            # int + m8
1001            assert_equal(3*24 + tdb, tdc)
1002            assert_equal((3*24 + tdb).dtype, np.dtype('m8[h]'))
1003            # M8 + bool
1004            assert_equal(dta + True, dta + 1)
1005            assert_equal(dtnat + True, dtnat)
1006            assert_equal((dta + True).dtype, np.dtype('M8[D]'))
1007            # M8 + int
1008            assert_equal(dta + 3, dtb)
1009            assert_equal(dtnat + 3, dtnat)
1010            assert_equal((dta + 3).dtype, np.dtype('M8[D]'))
1011            # bool + M8
1012            assert_equal(False + dta, dta)
1013            assert_equal(False + dtnat, dtnat)
1014            assert_equal((False + dta).dtype, np.dtype('M8[D]'))
1015            # int + M8
1016            assert_equal(3 + dta, dtb)
1017            assert_equal(3 + dtnat, dtnat)
1018            assert_equal((3 + dta).dtype, np.dtype('M8[D]'))
1019            # M8 + m8
1020            assert_equal(dta + tda, dtb)
1021            assert_equal(dtnat + tda, dtnat)
1022            assert_equal((dta + tda).dtype, np.dtype('M8[D]'))
1023            # m8 + M8
1024            assert_equal(tda + dta, dtb)
1025            assert_equal(tda + dtnat, dtnat)
1026            assert_equal((tda + dta).dtype, np.dtype('M8[D]'))
1027
1028            # In M8 + m8, the result goes to higher precision
1029            assert_equal(np.add(dta, tdb, casting='unsafe'), dtc)
1030            assert_equal(np.add(dta, tdb, casting='unsafe').dtype,
1031                         np.dtype('M8[h]'))
1032            assert_equal(np.add(tdb, dta, casting='unsafe'), dtc)
1033            assert_equal(np.add(tdb, dta, casting='unsafe').dtype,
1034                         np.dtype('M8[h]'))
1035
1036            # M8 + M8
1037            assert_raises(TypeError, np.add, dta, dtb)
1038
1039    def test_datetime_subtract(self):
1040        for dta, dtb, dtc, dtd, dte, dtnat, tda, tdb, tdc in \
1041                    [
1042                     # One-dimensional arrays
1043                     (np.array(['2012-12-21'], dtype='M8[D]'),
1044                      np.array(['2012-12-24'], dtype='M8[D]'),
1045                      np.array(['1940-12-24'], dtype='M8[D]'),
1046                      np.array(['1940-12-24T00'], dtype='M8[h]'),
1047                      np.array(['1940-12-23T13'], dtype='M8[h]'),
1048                      np.array(['NaT'], dtype='M8[D]'),
1049                      np.array([3], dtype='m8[D]'),
1050                      np.array([11], dtype='m8[h]'),
1051                      np.array([3*24 - 11], dtype='m8[h]')),
1052                     # NumPy scalars
1053                     (np.datetime64('2012-12-21', '[D]'),
1054                      np.datetime64('2012-12-24', '[D]'),
1055                      np.datetime64('1940-12-24', '[D]'),
1056                      np.datetime64('1940-12-24T00', '[h]'),
1057                      np.datetime64('1940-12-23T13', '[h]'),
1058                      np.datetime64('NaT', '[D]'),
1059                      np.timedelta64(3, '[D]'),
1060                      np.timedelta64(11, '[h]'),
1061                      np.timedelta64(3*24 - 11, '[h]'))]:
1062            # m8 - m8
1063            assert_equal(tda - tdb, tdc)
1064            assert_equal((tda - tdb).dtype, np.dtype('m8[h]'))
1065            assert_equal(tdb - tda, -tdc)
1066            assert_equal((tdb - tda).dtype, np.dtype('m8[h]'))
1067            # m8 - bool
1068            assert_equal(tdc - True, tdc - 1)
1069            assert_equal((tdc - True).dtype, np.dtype('m8[h]'))
1070            # m8 - int
1071            assert_equal(tdc - 3*24, -tdb)
1072            assert_equal((tdc - 3*24).dtype, np.dtype('m8[h]'))
1073            # int - m8
1074            assert_equal(False - tdb, -tdb)
1075            assert_equal((False - tdb).dtype, np.dtype('m8[h]'))
1076            # int - m8
1077            assert_equal(3*24 - tdb, tdc)
1078            assert_equal((3*24 - tdb).dtype, np.dtype('m8[h]'))
1079            # M8 - bool
1080            assert_equal(dtb - True, dtb - 1)
1081            assert_equal(dtnat - True, dtnat)
1082            assert_equal((dtb - True).dtype, np.dtype('M8[D]'))
1083            # M8 - int
1084            assert_equal(dtb - 3, dta)
1085            assert_equal(dtnat - 3, dtnat)
1086            assert_equal((dtb - 3).dtype, np.dtype('M8[D]'))
1087            # M8 - m8
1088            assert_equal(dtb - tda, dta)
1089            assert_equal(dtnat - tda, dtnat)
1090            assert_equal((dtb - tda).dtype, np.dtype('M8[D]'))
1091
1092            # In M8 - m8, the result goes to higher precision
1093            assert_equal(np.subtract(dtc, tdb, casting='unsafe'), dte)
1094            assert_equal(np.subtract(dtc, tdb, casting='unsafe').dtype,
1095                         np.dtype('M8[h]'))
1096
1097            # M8 - M8 with different goes to higher precision
1098            assert_equal(np.subtract(dtc, dtd, casting='unsafe'),
1099                         np.timedelta64(0, 'h'))
1100            assert_equal(np.subtract(dtc, dtd, casting='unsafe').dtype,
1101                         np.dtype('m8[h]'))
1102            assert_equal(np.subtract(dtd, dtc, casting='unsafe'),
1103                         np.timedelta64(0, 'h'))
1104            assert_equal(np.subtract(dtd, dtc, casting='unsafe').dtype,
1105                         np.dtype('m8[h]'))
1106
1107            # m8 - M8
1108            assert_raises(TypeError, np.subtract, tda, dta)
1109            # bool - M8
1110            assert_raises(TypeError, np.subtract, False, dta)
1111            # int - M8
1112            assert_raises(TypeError, np.subtract, 3, dta)
1113
1114    def test_datetime_multiply(self):
1115        for dta, tda, tdb, tdc in \
1116                    [
1117                     # One-dimensional arrays
1118                     (np.array(['2012-12-21'], dtype='M8[D]'),
1119                      np.array([6], dtype='m8[h]'),
1120                      np.array([9], dtype='m8[h]'),
1121                      np.array([12], dtype='m8[h]')),
1122                     # NumPy scalars
1123                     (np.datetime64('2012-12-21', '[D]'),
1124                      np.timedelta64(6, '[h]'),
1125                      np.timedelta64(9, '[h]'),
1126                      np.timedelta64(12, '[h]'))]:
1127            # m8 * int
1128            assert_equal(tda * 2, tdc)
1129            assert_equal((tda * 2).dtype, np.dtype('m8[h]'))
1130            # int * m8
1131            assert_equal(2 * tda, tdc)
1132            assert_equal((2 * tda).dtype, np.dtype('m8[h]'))
1133            # m8 * float
1134            assert_equal(tda * 1.5, tdb)
1135            assert_equal((tda * 1.5).dtype, np.dtype('m8[h]'))
1136            # float * m8
1137            assert_equal(1.5 * tda, tdb)
1138            assert_equal((1.5 * tda).dtype, np.dtype('m8[h]'))
1139
1140            # m8 * m8
1141            assert_raises(TypeError, np.multiply, tda, tdb)
1142            # m8 * M8
1143            assert_raises(TypeError, np.multiply, dta, tda)
1144            # M8 * m8
1145            assert_raises(TypeError, np.multiply, tda, dta)
1146            # M8 * int
1147            assert_raises(TypeError, np.multiply, dta, 2)
1148            # int * M8
1149            assert_raises(TypeError, np.multiply, 2, dta)
1150            # M8 * float
1151            assert_raises(TypeError, np.multiply, dta, 1.5)
1152            # float * M8
1153            assert_raises(TypeError, np.multiply, 1.5, dta)
1154
1155        # NaTs
1156        with suppress_warnings() as sup:
1157            sup.filter(RuntimeWarning, "invalid value encountered in multiply")
1158            nat = np.timedelta64('NaT')
1159            def check(a, b, res):
1160                assert_equal(a * b, res)
1161                assert_equal(b * a, res)
1162            for tp in (int, float):
1163                check(nat, tp(2), nat)
1164                check(nat, tp(0), nat)
1165            for f in (float('inf'), float('nan')):
1166                check(np.timedelta64(1), f, nat)
1167                check(np.timedelta64(0), f, nat)
1168                check(nat, f, nat)
1169
1170    @pytest.mark.parametrize("op1, op2, exp", [
1171        # m8 same units round down
1172        (np.timedelta64(7, 's'),
1173         np.timedelta64(4, 's'),
1174         1),
1175        # m8 same units round down with negative
1176        (np.timedelta64(7, 's'),
1177         np.timedelta64(-4, 's'),
1178         -2),
1179        # m8 same units negative no round down
1180        (np.timedelta64(8, 's'),
1181         np.timedelta64(-4, 's'),
1182         -2),
1183        # m8 different units
1184        (np.timedelta64(1, 'm'),
1185         np.timedelta64(31, 's'),
1186         1),
1187        # m8 generic units
1188        (np.timedelta64(1890),
1189         np.timedelta64(31),
1190         60),
1191        # Y // M works
1192        (np.timedelta64(2, 'Y'),
1193         np.timedelta64('13', 'M'),
1194         1),
1195        # handle 1D arrays
1196        (np.array([1, 2, 3], dtype='m8'),
1197         np.array([2], dtype='m8'),
1198         np.array([0, 1, 1], dtype=np.int64)),
1199        ])
1200    def test_timedelta_floor_divide(self, op1, op2, exp):
1201        assert_equal(op1 // op2, exp)
1202
1203    @pytest.mark.parametrize("op1, op2", [
1204        # div by 0
1205        (np.timedelta64(10, 'us'),
1206         np.timedelta64(0, 'us')),
1207        # div with NaT
1208        (np.timedelta64('NaT'),
1209         np.timedelta64(50, 'us')),
1210        # special case for int64 min
1211        # in integer floor division
1212        (np.timedelta64(np.iinfo(np.int64).min),
1213         np.timedelta64(-1)),
1214        ])
1215    def test_timedelta_floor_div_warnings(self, op1, op2):
1216        with assert_warns(RuntimeWarning):
1217            actual = op1 // op2
1218            assert_equal(actual, 0)
1219            assert_equal(actual.dtype, np.int64)
1220
1221    @pytest.mark.parametrize("val1, val2", [
1222        # the smallest integer that can't be represented
1223        # exactly in a double should be preserved if we avoid
1224        # casting to double in floordiv operation
1225        (9007199254740993, 1),
1226        # stress the alternate floordiv code path where
1227        # operand signs don't match and remainder isn't 0
1228        (9007199254740999, -2),
1229        ])
1230    def test_timedelta_floor_div_precision(self, val1, val2):
1231        op1 = np.timedelta64(val1)
1232        op2 = np.timedelta64(val2)
1233        actual = op1 // op2
1234        # Python reference integer floor
1235        expected = val1 // val2
1236        assert_equal(actual, expected)
1237
1238    @pytest.mark.parametrize("val1, val2", [
1239        # years and months sometimes can't be unambiguously
1240        # divided for floor division operation
1241        (np.timedelta64(7, 'Y'),
1242         np.timedelta64(3, 's')),
1243        (np.timedelta64(7, 'M'),
1244         np.timedelta64(1, 'D')),
1245        ])
1246    def test_timedelta_floor_div_error(self, val1, val2):
1247        with assert_raises_regex(TypeError, "common metadata divisor"):
1248            val1 // val2
1249
1250    @pytest.mark.parametrize("op1, op2", [
1251        # reuse the test cases from floordiv
1252        (np.timedelta64(7, 's'),
1253         np.timedelta64(4, 's')),
1254        # m8 same units round down with negative
1255        (np.timedelta64(7, 's'),
1256         np.timedelta64(-4, 's')),
1257        # m8 same units negative no round down
1258        (np.timedelta64(8, 's'),
1259         np.timedelta64(-4, 's')),
1260        # m8 different units
1261        (np.timedelta64(1, 'm'),
1262         np.timedelta64(31, 's')),
1263        # m8 generic units
1264        (np.timedelta64(1890),
1265         np.timedelta64(31)),
1266        # Y // M works
1267        (np.timedelta64(2, 'Y'),
1268         np.timedelta64('13', 'M')),
1269        # handle 1D arrays
1270        (np.array([1, 2, 3], dtype='m8'),
1271         np.array([2], dtype='m8')),
1272        ])
1273    def test_timedelta_divmod(self, op1, op2):
1274        expected = (op1 // op2, op1 % op2)
1275        assert_equal(divmod(op1, op2), expected)
1276
1277    @pytest.mark.parametrize("op1, op2", [
1278        # reuse cases from floordiv
1279        # div by 0
1280        (np.timedelta64(10, 'us'),
1281         np.timedelta64(0, 'us')),
1282        # div with NaT
1283        (np.timedelta64('NaT'),
1284         np.timedelta64(50, 'us')),
1285        # special case for int64 min
1286        # in integer floor division
1287        (np.timedelta64(np.iinfo(np.int64).min),
1288         np.timedelta64(-1)),
1289        ])
1290    def test_timedelta_divmod_warnings(self, op1, op2):
1291        with assert_warns(RuntimeWarning):
1292            expected = (op1 // op2, op1 % op2)
1293        with assert_warns(RuntimeWarning):
1294            actual = divmod(op1, op2)
1295        assert_equal(actual, expected)
1296
1297    def test_datetime_divide(self):
1298        for dta, tda, tdb, tdc, tdd in \
1299                    [
1300                     # One-dimensional arrays
1301                     (np.array(['2012-12-21'], dtype='M8[D]'),
1302                      np.array([6], dtype='m8[h]'),
1303                      np.array([9], dtype='m8[h]'),
1304                      np.array([12], dtype='m8[h]'),
1305                      np.array([6], dtype='m8[m]')),
1306                     # NumPy scalars
1307                     (np.datetime64('2012-12-21', '[D]'),
1308                      np.timedelta64(6, '[h]'),
1309                      np.timedelta64(9, '[h]'),
1310                      np.timedelta64(12, '[h]'),
1311                      np.timedelta64(6, '[m]'))]:
1312            # m8 / int
1313            assert_equal(tdc / 2, tda)
1314            assert_equal((tdc / 2).dtype, np.dtype('m8[h]'))
1315            # m8 / float
1316            assert_equal(tda / 0.5, tdc)
1317            assert_equal((tda / 0.5).dtype, np.dtype('m8[h]'))
1318            # m8 / m8
1319            assert_equal(tda / tdb, 6.0 / 9.0)
1320            assert_equal(np.divide(tda, tdb), 6.0 / 9.0)
1321            assert_equal(np.true_divide(tda, tdb), 6.0 / 9.0)
1322            assert_equal(tdb / tda, 9.0 / 6.0)
1323            assert_equal((tda / tdb).dtype, np.dtype('f8'))
1324            assert_equal(tda / tdd, 60.0)
1325            assert_equal(tdd / tda, 1.0 / 60.0)
1326
1327            # int / m8
1328            assert_raises(TypeError, np.divide, 2, tdb)
1329            # float / m8
1330            assert_raises(TypeError, np.divide, 0.5, tdb)
1331            # m8 / M8
1332            assert_raises(TypeError, np.divide, dta, tda)
1333            # M8 / m8
1334            assert_raises(TypeError, np.divide, tda, dta)
1335            # M8 / int
1336            assert_raises(TypeError, np.divide, dta, 2)
1337            # int / M8
1338            assert_raises(TypeError, np.divide, 2, dta)
1339            # M8 / float
1340            assert_raises(TypeError, np.divide, dta, 1.5)
1341            # float / M8
1342            assert_raises(TypeError, np.divide, 1.5, dta)
1343
1344        # NaTs
1345        with suppress_warnings() as sup:
1346            sup.filter(RuntimeWarning,  r".*encountered in true\_divide")
1347            nat = np.timedelta64('NaT')
1348            for tp in (int, float):
1349                assert_equal(np.timedelta64(1) / tp(0), nat)
1350                assert_equal(np.timedelta64(0) / tp(0), nat)
1351                assert_equal(nat / tp(0), nat)
1352                assert_equal(nat / tp(2), nat)
1353            # Division by inf
1354            assert_equal(np.timedelta64(1) / float('inf'), np.timedelta64(0))
1355            assert_equal(np.timedelta64(0) / float('inf'), np.timedelta64(0))
1356            assert_equal(nat / float('inf'), nat)
1357            # Division by nan
1358            assert_equal(np.timedelta64(1) / float('nan'), nat)
1359            assert_equal(np.timedelta64(0) / float('nan'), nat)
1360            assert_equal(nat / float('nan'), nat)
1361
1362    def test_datetime_compare(self):
1363        # Test all the comparison operators
1364        a = np.datetime64('2000-03-12T18:00:00.000000')
1365        b = np.array(['2000-03-12T18:00:00.000000',
1366                      '2000-03-12T17:59:59.999999',
1367                      '2000-03-12T18:00:00.000001',
1368                      '1970-01-11T12:00:00.909090',
1369                      '2016-01-11T12:00:00.909090'],
1370                      dtype='datetime64[us]')
1371        assert_equal(np.equal(a, b), [1, 0, 0, 0, 0])
1372        assert_equal(np.not_equal(a, b), [0, 1, 1, 1, 1])
1373        assert_equal(np.less(a, b), [0, 0, 1, 0, 1])
1374        assert_equal(np.less_equal(a, b), [1, 0, 1, 0, 1])
1375        assert_equal(np.greater(a, b), [0, 1, 0, 1, 0])
1376        assert_equal(np.greater_equal(a, b), [1, 1, 0, 1, 0])
1377
1378    def test_datetime_compare_nat(self):
1379        dt_nat = np.datetime64('NaT', 'D')
1380        dt_other = np.datetime64('2000-01-01')
1381        td_nat = np.timedelta64('NaT', 'h')
1382        td_other = np.timedelta64(1, 'h')
1383
1384        for op in [np.equal, np.less, np.less_equal,
1385                   np.greater, np.greater_equal]:
1386            assert_(not op(dt_nat, dt_nat))
1387            assert_(not op(dt_nat, dt_other))
1388            assert_(not op(dt_other, dt_nat))
1389
1390            assert_(not op(td_nat, td_nat))
1391            assert_(not op(td_nat, td_other))
1392            assert_(not op(td_other, td_nat))
1393
1394        assert_(np.not_equal(dt_nat, dt_nat))
1395        assert_(np.not_equal(dt_nat, dt_other))
1396        assert_(np.not_equal(dt_other, dt_nat))
1397
1398        assert_(np.not_equal(td_nat, td_nat))
1399        assert_(np.not_equal(td_nat, td_other))
1400        assert_(np.not_equal(td_other, td_nat))
1401
1402    def test_datetime_minmax(self):
1403        # The metadata of the result should become the GCD
1404        # of the operand metadata
1405        a = np.array('1999-03-12T13', dtype='M8[2m]')
1406        b = np.array('1999-03-12T12', dtype='M8[s]')
1407        assert_equal(np.minimum(a, b), b)
1408        assert_equal(np.minimum(a, b).dtype, np.dtype('M8[s]'))
1409        assert_equal(np.fmin(a, b), b)
1410        assert_equal(np.fmin(a, b).dtype, np.dtype('M8[s]'))
1411        assert_equal(np.maximum(a, b), a)
1412        assert_equal(np.maximum(a, b).dtype, np.dtype('M8[s]'))
1413        assert_equal(np.fmax(a, b), a)
1414        assert_equal(np.fmax(a, b).dtype, np.dtype('M8[s]'))
1415        # Viewed as integers, the comparison is opposite because
1416        # of the units chosen
1417        assert_equal(np.minimum(a.view('i8'), b.view('i8')), a.view('i8'))
1418
1419        # Interaction with NaT
1420        a = np.array('1999-03-12T13', dtype='M8[2m]')
1421        dtnat = np.array('NaT', dtype='M8[h]')
1422        assert_equal(np.minimum(a, dtnat), dtnat)
1423        assert_equal(np.minimum(dtnat, a), dtnat)
1424        assert_equal(np.maximum(a, dtnat), dtnat)
1425        assert_equal(np.maximum(dtnat, a), dtnat)
1426        assert_equal(np.fmin(dtnat, a), a)
1427        assert_equal(np.fmin(a, dtnat), a)
1428        assert_equal(np.fmax(dtnat, a), a)
1429        assert_equal(np.fmax(a, dtnat), a)
1430
1431        # Also do timedelta
1432        a = np.array(3, dtype='m8[h]')
1433        b = np.array(3*3600 - 3, dtype='m8[s]')
1434        assert_equal(np.minimum(a, b), b)
1435        assert_equal(np.minimum(a, b).dtype, np.dtype('m8[s]'))
1436        assert_equal(np.fmin(a, b), b)
1437        assert_equal(np.fmin(a, b).dtype, np.dtype('m8[s]'))
1438        assert_equal(np.maximum(a, b), a)
1439        assert_equal(np.maximum(a, b).dtype, np.dtype('m8[s]'))
1440        assert_equal(np.fmax(a, b), a)
1441        assert_equal(np.fmax(a, b).dtype, np.dtype('m8[s]'))
1442        # Viewed as integers, the comparison is opposite because
1443        # of the units chosen
1444        assert_equal(np.minimum(a.view('i8'), b.view('i8')), a.view('i8'))
1445
1446        # should raise between datetime and timedelta
1447        #
1448        # TODO: Allowing unsafe casting by
1449        #       default in ufuncs strikes again... :(
1450        a = np.array(3, dtype='m8[h]')
1451        b = np.array('1999-03-12T12', dtype='M8[s]')
1452        #assert_raises(TypeError, np.minimum, a, b)
1453        #assert_raises(TypeError, np.maximum, a, b)
1454        #assert_raises(TypeError, np.fmin, a, b)
1455        #assert_raises(TypeError, np.fmax, a, b)
1456        assert_raises(TypeError, np.minimum, a, b, casting='same_kind')
1457        assert_raises(TypeError, np.maximum, a, b, casting='same_kind')
1458        assert_raises(TypeError, np.fmin, a, b, casting='same_kind')
1459        assert_raises(TypeError, np.fmax, a, b, casting='same_kind')
1460
1461    def test_hours(self):
1462        t = np.ones(3, dtype='M8[s]')
1463        t[0] = 60*60*24 + 60*60*10
1464        assert_(t[0].item().hour == 10)
1465
1466    def test_divisor_conversion_year(self):
1467        assert_(np.dtype('M8[Y/4]') == np.dtype('M8[3M]'))
1468        assert_(np.dtype('M8[Y/13]') == np.dtype('M8[4W]'))
1469        assert_(np.dtype('M8[3Y/73]') == np.dtype('M8[15D]'))
1470
1471    def test_divisor_conversion_month(self):
1472        assert_(np.dtype('M8[M/2]') == np.dtype('M8[2W]'))
1473        assert_(np.dtype('M8[M/15]') == np.dtype('M8[2D]'))
1474        assert_(np.dtype('M8[3M/40]') == np.dtype('M8[54h]'))
1475
1476    def test_divisor_conversion_week(self):
1477        assert_(np.dtype('m8[W/7]') == np.dtype('m8[D]'))
1478        assert_(np.dtype('m8[3W/14]') == np.dtype('m8[36h]'))
1479        assert_(np.dtype('m8[5W/140]') == np.dtype('m8[360m]'))
1480
1481    def test_divisor_conversion_day(self):
1482        assert_(np.dtype('M8[D/12]') == np.dtype('M8[2h]'))
1483        assert_(np.dtype('M8[D/120]') == np.dtype('M8[12m]'))
1484        assert_(np.dtype('M8[3D/960]') == np.dtype('M8[270s]'))
1485
1486    def test_divisor_conversion_hour(self):
1487        assert_(np.dtype('m8[h/30]') == np.dtype('m8[2m]'))
1488        assert_(np.dtype('m8[3h/300]') == np.dtype('m8[36s]'))
1489
1490    def test_divisor_conversion_minute(self):
1491        assert_(np.dtype('m8[m/30]') == np.dtype('m8[2s]'))
1492        assert_(np.dtype('m8[3m/300]') == np.dtype('m8[600ms]'))
1493
1494    def test_divisor_conversion_second(self):
1495        assert_(np.dtype('m8[s/100]') == np.dtype('m8[10ms]'))
1496        assert_(np.dtype('m8[3s/10000]') == np.dtype('m8[300us]'))
1497
1498    def test_divisor_conversion_fs(self):
1499        assert_(np.dtype('M8[fs/100]') == np.dtype('M8[10as]'))
1500        assert_raises(ValueError, lambda: np.dtype('M8[3fs/10000]'))
1501
1502    def test_divisor_conversion_as(self):
1503        assert_raises(ValueError, lambda: np.dtype('M8[as/10]'))
1504
1505    def test_string_parser_variants(self):
1506        # Allow space instead of 'T' between date and time
1507        assert_equal(np.array(['1980-02-29T01:02:03'], np.dtype('M8[s]')),
1508                     np.array(['1980-02-29 01:02:03'], np.dtype('M8[s]')))
1509        # Allow positive years
1510        assert_equal(np.array(['+1980-02-29T01:02:03'], np.dtype('M8[s]')),
1511                     np.array(['+1980-02-29 01:02:03'], np.dtype('M8[s]')))
1512        # Allow negative years
1513        assert_equal(np.array(['-1980-02-29T01:02:03'], np.dtype('M8[s]')),
1514                     np.array(['-1980-02-29 01:02:03'], np.dtype('M8[s]')))
1515        # UTC specifier
1516        with assert_warns(DeprecationWarning):
1517            assert_equal(
1518                np.array(['+1980-02-29T01:02:03'], np.dtype('M8[s]')),
1519                np.array(['+1980-02-29 01:02:03Z'], np.dtype('M8[s]')))
1520        with assert_warns(DeprecationWarning):
1521            assert_equal(
1522                np.array(['-1980-02-29T01:02:03'], np.dtype('M8[s]')),
1523                np.array(['-1980-02-29 01:02:03Z'], np.dtype('M8[s]')))
1524        # Time zone offset
1525        with assert_warns(DeprecationWarning):
1526            assert_equal(
1527                np.array(['1980-02-29T02:02:03'], np.dtype('M8[s]')),
1528                np.array(['1980-02-29 00:32:03-0130'], np.dtype('M8[s]')))
1529        with assert_warns(DeprecationWarning):
1530            assert_equal(
1531                np.array(['1980-02-28T22:32:03'], np.dtype('M8[s]')),
1532                np.array(['1980-02-29 00:02:03+01:30'], np.dtype('M8[s]')))
1533        with assert_warns(DeprecationWarning):
1534            assert_equal(
1535                np.array(['1980-02-29T02:32:03.506'], np.dtype('M8[s]')),
1536                np.array(['1980-02-29 00:32:03.506-02'], np.dtype('M8[s]')))
1537        with assert_warns(DeprecationWarning):
1538            assert_equal(np.datetime64('1977-03-02T12:30-0230'),
1539                         np.datetime64('1977-03-02T15:00'))
1540
1541    def test_string_parser_error_check(self):
1542        # Arbitrary bad string
1543        assert_raises(ValueError, np.array, ['badvalue'], np.dtype('M8[us]'))
1544        # Character after year must be '-'
1545        assert_raises(ValueError, np.array, ['1980X'], np.dtype('M8[us]'))
1546        # Cannot have trailing '-'
1547        assert_raises(ValueError, np.array, ['1980-'], np.dtype('M8[us]'))
1548        # Month must be in range [1,12]
1549        assert_raises(ValueError, np.array, ['1980-00'], np.dtype('M8[us]'))
1550        assert_raises(ValueError, np.array, ['1980-13'], np.dtype('M8[us]'))
1551        # Month must have two digits
1552        assert_raises(ValueError, np.array, ['1980-1'], np.dtype('M8[us]'))
1553        assert_raises(ValueError, np.array, ['1980-1-02'], np.dtype('M8[us]'))
1554        # 'Mor' is not a valid month
1555        assert_raises(ValueError, np.array, ['1980-Mor'], np.dtype('M8[us]'))
1556        # Cannot have trailing '-'
1557        assert_raises(ValueError, np.array, ['1980-01-'], np.dtype('M8[us]'))
1558        # Day must be in range [1,len(month)]
1559        assert_raises(ValueError, np.array, ['1980-01-0'], np.dtype('M8[us]'))
1560        assert_raises(ValueError, np.array, ['1980-01-00'], np.dtype('M8[us]'))
1561        assert_raises(ValueError, np.array, ['1980-01-32'], np.dtype('M8[us]'))
1562        assert_raises(ValueError, np.array, ['1979-02-29'], np.dtype('M8[us]'))
1563        assert_raises(ValueError, np.array, ['1980-02-30'], np.dtype('M8[us]'))
1564        assert_raises(ValueError, np.array, ['1980-03-32'], np.dtype('M8[us]'))
1565        assert_raises(ValueError, np.array, ['1980-04-31'], np.dtype('M8[us]'))
1566        assert_raises(ValueError, np.array, ['1980-05-32'], np.dtype('M8[us]'))
1567        assert_raises(ValueError, np.array, ['1980-06-31'], np.dtype('M8[us]'))
1568        assert_raises(ValueError, np.array, ['1980-07-32'], np.dtype('M8[us]'))
1569        assert_raises(ValueError, np.array, ['1980-08-32'], np.dtype('M8[us]'))
1570        assert_raises(ValueError, np.array, ['1980-09-31'], np.dtype('M8[us]'))
1571        assert_raises(ValueError, np.array, ['1980-10-32'], np.dtype('M8[us]'))
1572        assert_raises(ValueError, np.array, ['1980-11-31'], np.dtype('M8[us]'))
1573        assert_raises(ValueError, np.array, ['1980-12-32'], np.dtype('M8[us]'))
1574        # Cannot have trailing characters
1575        assert_raises(ValueError, np.array, ['1980-02-03%'],
1576                                                        np.dtype('M8[us]'))
1577        assert_raises(ValueError, np.array, ['1980-02-03 q'],
1578                                                        np.dtype('M8[us]'))
1579
1580        # Hours must be in range [0, 23]
1581        assert_raises(ValueError, np.array, ['1980-02-03 25'],
1582                                                        np.dtype('M8[us]'))
1583        assert_raises(ValueError, np.array, ['1980-02-03T25'],
1584                                                        np.dtype('M8[us]'))
1585        assert_raises(ValueError, np.array, ['1980-02-03 24:01'],
1586                                                        np.dtype('M8[us]'))
1587        assert_raises(ValueError, np.array, ['1980-02-03T24:01'],
1588                                                        np.dtype('M8[us]'))
1589        assert_raises(ValueError, np.array, ['1980-02-03 -1'],
1590                                                        np.dtype('M8[us]'))
1591        # No trailing ':'
1592        assert_raises(ValueError, np.array, ['1980-02-03 01:'],
1593                                                        np.dtype('M8[us]'))
1594        # Minutes must be in range [0, 59]
1595        assert_raises(ValueError, np.array, ['1980-02-03 01:-1'],
1596                                                        np.dtype('M8[us]'))
1597        assert_raises(ValueError, np.array, ['1980-02-03 01:60'],
1598                                                        np.dtype('M8[us]'))
1599        # No trailing ':'
1600        assert_raises(ValueError, np.array, ['1980-02-03 01:60:'],
1601                                                        np.dtype('M8[us]'))
1602        # Seconds must be in range [0, 59]
1603        assert_raises(ValueError, np.array, ['1980-02-03 01:10:-1'],
1604                                                        np.dtype('M8[us]'))
1605        assert_raises(ValueError, np.array, ['1980-02-03 01:01:60'],
1606                                                        np.dtype('M8[us]'))
1607        # Timezone offset must within a reasonable range
1608        with assert_warns(DeprecationWarning):
1609            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00+0661'],
1610                                                            np.dtype('M8[us]'))
1611        with assert_warns(DeprecationWarning):
1612            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00+2500'],
1613                                                            np.dtype('M8[us]'))
1614        with assert_warns(DeprecationWarning):
1615            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00-0070'],
1616                                                            np.dtype('M8[us]'))
1617        with assert_warns(DeprecationWarning):
1618            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00-3000'],
1619                                                            np.dtype('M8[us]'))
1620        with assert_warns(DeprecationWarning):
1621            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00-25:00'],
1622                                                            np.dtype('M8[us]'))
1623
1624    def test_creation_overflow(self):
1625        date = '1980-03-23 20:00:00'
1626        timesteps = np.array([date], dtype='datetime64[s]')[0].astype(np.int64)
1627        for unit in ['ms', 'us', 'ns']:
1628            timesteps *= 1000
1629            x = np.array([date], dtype='datetime64[%s]' % unit)
1630
1631            assert_equal(timesteps, x[0].astype(np.int64),
1632                         err_msg='Datetime conversion error for unit %s' % unit)
1633
1634        assert_equal(x[0].astype(np.int64), 322689600000000000)
1635
1636        # gh-13062
1637        with pytest.raises(OverflowError):
1638            np.datetime64(2**64, 'D')
1639        with pytest.raises(OverflowError):
1640            np.timedelta64(2**64, 'D')
1641
1642    def test_datetime_as_string(self):
1643        # Check all the units with default string conversion
1644        date = '1959-10-13'
1645        datetime = '1959-10-13T12:34:56.789012345678901234'
1646
1647        assert_equal(np.datetime_as_string(np.datetime64(date, 'Y')),
1648                     '1959')
1649        assert_equal(np.datetime_as_string(np.datetime64(date, 'M')),
1650                     '1959-10')
1651        assert_equal(np.datetime_as_string(np.datetime64(date, 'D')),
1652                     '1959-10-13')
1653        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'h')),
1654                     '1959-10-13T12')
1655        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'm')),
1656                     '1959-10-13T12:34')
1657        assert_equal(np.datetime_as_string(np.datetime64(datetime, 's')),
1658                     '1959-10-13T12:34:56')
1659        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ms')),
1660                     '1959-10-13T12:34:56.789')
1661        for us in ['us', 'μs', b'us']:  # check non-ascii and bytes too
1662            assert_equal(np.datetime_as_string(np.datetime64(datetime, us)),
1663                         '1959-10-13T12:34:56.789012')
1664
1665        datetime = '1969-12-31T23:34:56.789012345678901234'
1666
1667        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ns')),
1668                     '1969-12-31T23:34:56.789012345')
1669        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ps')),
1670                     '1969-12-31T23:34:56.789012345678')
1671        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'fs')),
1672                     '1969-12-31T23:34:56.789012345678901')
1673
1674        datetime = '1969-12-31T23:59:57.789012345678901234'
1675
1676        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'as')),
1677                     datetime)
1678        datetime = '1970-01-01T00:34:56.789012345678901234'
1679
1680        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ns')),
1681                     '1970-01-01T00:34:56.789012345')
1682        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ps')),
1683                     '1970-01-01T00:34:56.789012345678')
1684        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'fs')),
1685                     '1970-01-01T00:34:56.789012345678901')
1686
1687        datetime = '1970-01-01T00:00:05.789012345678901234'
1688
1689        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'as')),
1690                     datetime)
1691
1692        # String conversion with the unit= parameter
1693        a = np.datetime64('2032-07-18T12:23:34.123456', 'us')
1694        assert_equal(np.datetime_as_string(a, unit='Y', casting='unsafe'),
1695                            '2032')
1696        assert_equal(np.datetime_as_string(a, unit='M', casting='unsafe'),
1697                            '2032-07')
1698        assert_equal(np.datetime_as_string(a, unit='W', casting='unsafe'),
1699                            '2032-07-18')
1700        assert_equal(np.datetime_as_string(a, unit='D', casting='unsafe'),
1701                            '2032-07-18')
1702        assert_equal(np.datetime_as_string(a, unit='h'), '2032-07-18T12')
1703        assert_equal(np.datetime_as_string(a, unit='m'),
1704                            '2032-07-18T12:23')
1705        assert_equal(np.datetime_as_string(a, unit='s'),
1706                            '2032-07-18T12:23:34')
1707        assert_equal(np.datetime_as_string(a, unit='ms'),
1708                            '2032-07-18T12:23:34.123')
1709        assert_equal(np.datetime_as_string(a, unit='us'),
1710                            '2032-07-18T12:23:34.123456')
1711        assert_equal(np.datetime_as_string(a, unit='ns'),
1712                            '2032-07-18T12:23:34.123456000')
1713        assert_equal(np.datetime_as_string(a, unit='ps'),
1714                            '2032-07-18T12:23:34.123456000000')
1715        assert_equal(np.datetime_as_string(a, unit='fs'),
1716                            '2032-07-18T12:23:34.123456000000000')
1717        assert_equal(np.datetime_as_string(a, unit='as'),
1718                            '2032-07-18T12:23:34.123456000000000000')
1719
1720        # unit='auto' parameter
1721        assert_equal(np.datetime_as_string(
1722                np.datetime64('2032-07-18T12:23:34.123456', 'us'), unit='auto'),
1723                '2032-07-18T12:23:34.123456')
1724        assert_equal(np.datetime_as_string(
1725                np.datetime64('2032-07-18T12:23:34.12', 'us'), unit='auto'),
1726                '2032-07-18T12:23:34.120')
1727        assert_equal(np.datetime_as_string(
1728                np.datetime64('2032-07-18T12:23:34', 'us'), unit='auto'),
1729                '2032-07-18T12:23:34')
1730        assert_equal(np.datetime_as_string(
1731                np.datetime64('2032-07-18T12:23:00', 'us'), unit='auto'),
1732                '2032-07-18T12:23')
1733        # 'auto' doesn't split up hour and minute
1734        assert_equal(np.datetime_as_string(
1735                np.datetime64('2032-07-18T12:00:00', 'us'), unit='auto'),
1736                '2032-07-18T12:00')
1737        assert_equal(np.datetime_as_string(
1738                np.datetime64('2032-07-18T00:00:00', 'us'), unit='auto'),
1739                '2032-07-18')
1740        # 'auto' doesn't split up the date
1741        assert_equal(np.datetime_as_string(
1742                np.datetime64('2032-07-01T00:00:00', 'us'), unit='auto'),
1743                '2032-07-01')
1744        assert_equal(np.datetime_as_string(
1745                np.datetime64('2032-01-01T00:00:00', 'us'), unit='auto'),
1746                '2032-01-01')
1747
1748    @pytest.mark.skipif(not _has_pytz, reason="The pytz module is not available.")
1749    def test_datetime_as_string_timezone(self):
1750        # timezone='local' vs 'UTC'
1751        a = np.datetime64('2010-03-15T06:30', 'm')
1752        assert_equal(np.datetime_as_string(a),
1753                '2010-03-15T06:30')
1754        assert_equal(np.datetime_as_string(a, timezone='naive'),
1755                '2010-03-15T06:30')
1756        assert_equal(np.datetime_as_string(a, timezone='UTC'),
1757                '2010-03-15T06:30Z')
1758        assert_(np.datetime_as_string(a, timezone='local') !=
1759                '2010-03-15T06:30')
1760
1761        b = np.datetime64('2010-02-15T06:30', 'm')
1762
1763        assert_equal(np.datetime_as_string(a, timezone=tz('US/Central')),
1764                     '2010-03-15T01:30-0500')
1765        assert_equal(np.datetime_as_string(a, timezone=tz('US/Eastern')),
1766                     '2010-03-15T02:30-0400')
1767        assert_equal(np.datetime_as_string(a, timezone=tz('US/Pacific')),
1768                     '2010-03-14T23:30-0700')
1769
1770        assert_equal(np.datetime_as_string(b, timezone=tz('US/Central')),
1771                     '2010-02-15T00:30-0600')
1772        assert_equal(np.datetime_as_string(b, timezone=tz('US/Eastern')),
1773                     '2010-02-15T01:30-0500')
1774        assert_equal(np.datetime_as_string(b, timezone=tz('US/Pacific')),
1775                     '2010-02-14T22:30-0800')
1776
1777        # Dates to strings with a timezone attached is disabled by default
1778        assert_raises(TypeError, np.datetime_as_string, a, unit='D',
1779                           timezone=tz('US/Pacific'))
1780        # Check that we can print out the date in the specified time zone
1781        assert_equal(np.datetime_as_string(a, unit='D',
1782                           timezone=tz('US/Pacific'), casting='unsafe'),
1783                     '2010-03-14')
1784        assert_equal(np.datetime_as_string(b, unit='D',
1785                           timezone=tz('US/Central'), casting='unsafe'),
1786                     '2010-02-15')
1787
1788    def test_datetime_arange(self):
1789        # With two datetimes provided as strings
1790        a = np.arange('2010-01-05', '2010-01-10', dtype='M8[D]')
1791        assert_equal(a.dtype, np.dtype('M8[D]'))
1792        assert_equal(a,
1793            np.array(['2010-01-05', '2010-01-06', '2010-01-07',
1794                      '2010-01-08', '2010-01-09'], dtype='M8[D]'))
1795
1796        a = np.arange('1950-02-10', '1950-02-06', -1, dtype='M8[D]')
1797        assert_equal(a.dtype, np.dtype('M8[D]'))
1798        assert_equal(a,
1799            np.array(['1950-02-10', '1950-02-09', '1950-02-08',
1800                      '1950-02-07'], dtype='M8[D]'))
1801
1802        # Unit should be detected as months here
1803        a = np.arange('1969-05', '1970-05', 2, dtype='M8')
1804        assert_equal(a.dtype, np.dtype('M8[M]'))
1805        assert_equal(a,
1806            np.datetime64('1969-05') + np.arange(12, step=2))
1807
1808        # datetime, integer|timedelta works as well
1809        # produces arange (start, start + stop) in this case
1810        a = np.arange('1969', 18, 3, dtype='M8')
1811        assert_equal(a.dtype, np.dtype('M8[Y]'))
1812        assert_equal(a,
1813            np.datetime64('1969') + np.arange(18, step=3))
1814        a = np.arange('1969-12-19', 22, np.timedelta64(2), dtype='M8')
1815        assert_equal(a.dtype, np.dtype('M8[D]'))
1816        assert_equal(a,
1817            np.datetime64('1969-12-19') + np.arange(22, step=2))
1818
1819        # Step of 0 is disallowed
1820        assert_raises(ValueError, np.arange, np.datetime64('today'),
1821                                np.datetime64('today') + 3, 0)
1822        # Promotion across nonlinear unit boundaries is disallowed
1823        assert_raises(TypeError, np.arange, np.datetime64('2011-03-01', 'D'),
1824                                np.timedelta64(5, 'M'))
1825        assert_raises(TypeError, np.arange,
1826                                np.datetime64('2012-02-03T14', 's'),
1827                                np.timedelta64(5, 'Y'))
1828
1829    def test_datetime_arange_no_dtype(self):
1830        d = np.array('2010-01-04', dtype="M8[D]")
1831        assert_equal(np.arange(d, d + 1), d)
1832        assert_raises(ValueError, np.arange, d)
1833
1834    def test_timedelta_arange(self):
1835        a = np.arange(3, 10, dtype='m8')
1836        assert_equal(a.dtype, np.dtype('m8'))
1837        assert_equal(a, np.timedelta64(0) + np.arange(3, 10))
1838
1839        a = np.arange(np.timedelta64(3, 's'), 10, 2, dtype='m8')
1840        assert_equal(a.dtype, np.dtype('m8[s]'))
1841        assert_equal(a, np.timedelta64(0, 's') + np.arange(3, 10, 2))
1842
1843        # Step of 0 is disallowed
1844        assert_raises(ValueError, np.arange, np.timedelta64(0),
1845                                np.timedelta64(5), 0)
1846        # Promotion across nonlinear unit boundaries is disallowed
1847        assert_raises(TypeError, np.arange, np.timedelta64(0, 'D'),
1848                                np.timedelta64(5, 'M'))
1849        assert_raises(TypeError, np.arange, np.timedelta64(0, 'Y'),
1850                                np.timedelta64(5, 'D'))
1851
1852    @pytest.mark.parametrize("val1, val2, expected", [
1853        # case from gh-12092
1854        (np.timedelta64(7, 's'),
1855         np.timedelta64(3, 's'),
1856         np.timedelta64(1, 's')),
1857        # negative value cases
1858        (np.timedelta64(3, 's'),
1859         np.timedelta64(-2, 's'),
1860         np.timedelta64(-1, 's')),
1861        (np.timedelta64(-3, 's'),
1862         np.timedelta64(2, 's'),
1863         np.timedelta64(1, 's')),
1864        # larger value cases
1865        (np.timedelta64(17, 's'),
1866         np.timedelta64(22, 's'),
1867         np.timedelta64(17, 's')),
1868        (np.timedelta64(22, 's'),
1869         np.timedelta64(17, 's'),
1870         np.timedelta64(5, 's')),
1871        # different units
1872        (np.timedelta64(1, 'm'),
1873         np.timedelta64(57, 's'),
1874         np.timedelta64(3, 's')),
1875        (np.timedelta64(1, 'us'),
1876         np.timedelta64(727, 'ns'),
1877         np.timedelta64(273, 'ns')),
1878        # NaT is propagated
1879        (np.timedelta64('NaT'),
1880         np.timedelta64(50, 'ns'),
1881         np.timedelta64('NaT')),
1882        # Y % M works
1883        (np.timedelta64(2, 'Y'),
1884         np.timedelta64(22, 'M'),
1885         np.timedelta64(2, 'M')),
1886        ])
1887    def test_timedelta_modulus(self, val1, val2, expected):
1888        assert_equal(val1 % val2, expected)
1889
1890    @pytest.mark.parametrize("val1, val2", [
1891        # years and months sometimes can't be unambiguously
1892        # divided for modulus operation
1893        (np.timedelta64(7, 'Y'),
1894         np.timedelta64(3, 's')),
1895        (np.timedelta64(7, 'M'),
1896         np.timedelta64(1, 'D')),
1897        ])
1898    def test_timedelta_modulus_error(self, val1, val2):
1899        with assert_raises_regex(TypeError, "common metadata divisor"):
1900            val1 % val2
1901
1902    def test_timedelta_modulus_div_by_zero(self):
1903        with assert_warns(RuntimeWarning):
1904            actual = np.timedelta64(10, 's') % np.timedelta64(0, 's')
1905            assert_equal(actual, np.timedelta64('NaT'))
1906
1907    @pytest.mark.parametrize("val1, val2", [
1908        # cases where one operand is not
1909        # timedelta64
1910        (np.timedelta64(7, 'Y'),
1911         15,),
1912        (7.5,
1913         np.timedelta64(1, 'D')),
1914        ])
1915    def test_timedelta_modulus_type_resolution(self, val1, val2):
1916        # NOTE: some of the operations may be supported
1917        # in the future
1918        with assert_raises_regex(TypeError,
1919                                 "'remainder' cannot use operands with types"):
1920            val1 % val2
1921
1922    def test_timedelta_arange_no_dtype(self):
1923        d = np.array(5, dtype="m8[D]")
1924        assert_equal(np.arange(d, d + 1), d)
1925        assert_equal(np.arange(d), np.arange(0, d))
1926
1927    def test_datetime_maximum_reduce(self):
1928        a = np.array(['2010-01-02', '1999-03-14', '1833-03'], dtype='M8[D]')
1929        assert_equal(np.maximum.reduce(a).dtype, np.dtype('M8[D]'))
1930        assert_equal(np.maximum.reduce(a),
1931                     np.datetime64('2010-01-02'))
1932
1933        a = np.array([1, 4, 0, 7, 2], dtype='m8[s]')
1934        assert_equal(np.maximum.reduce(a).dtype, np.dtype('m8[s]'))
1935        assert_equal(np.maximum.reduce(a),
1936                     np.timedelta64(7, 's'))
1937
1938    def test_datetime_busday_offset(self):
1939        # First Monday in June
1940        assert_equal(
1941            np.busday_offset('2011-06', 0, roll='forward', weekmask='Mon'),
1942            np.datetime64('2011-06-06'))
1943        # Last Monday in June
1944        assert_equal(
1945            np.busday_offset('2011-07', -1, roll='forward', weekmask='Mon'),
1946            np.datetime64('2011-06-27'))
1947        assert_equal(
1948            np.busday_offset('2011-07', -1, roll='forward', weekmask='Mon'),
1949            np.datetime64('2011-06-27'))
1950
1951        # Default M-F business days, different roll modes
1952        assert_equal(np.busday_offset('2010-08', 0, roll='backward'),
1953                     np.datetime64('2010-07-30'))
1954        assert_equal(np.busday_offset('2010-08', 0, roll='preceding'),
1955                     np.datetime64('2010-07-30'))
1956        assert_equal(np.busday_offset('2010-08', 0, roll='modifiedpreceding'),
1957                     np.datetime64('2010-08-02'))
1958        assert_equal(np.busday_offset('2010-08', 0, roll='modifiedfollowing'),
1959                     np.datetime64('2010-08-02'))
1960        assert_equal(np.busday_offset('2010-08', 0, roll='forward'),
1961                     np.datetime64('2010-08-02'))
1962        assert_equal(np.busday_offset('2010-08', 0, roll='following'),
1963                     np.datetime64('2010-08-02'))
1964        assert_equal(np.busday_offset('2010-10-30', 0, roll='following'),
1965                     np.datetime64('2010-11-01'))
1966        assert_equal(
1967                np.busday_offset('2010-10-30', 0, roll='modifiedfollowing'),
1968                np.datetime64('2010-10-29'))
1969        assert_equal(
1970                np.busday_offset('2010-10-30', 0, roll='modifiedpreceding'),
1971                np.datetime64('2010-10-29'))
1972        assert_equal(
1973                np.busday_offset('2010-10-16', 0, roll='modifiedfollowing'),
1974                np.datetime64('2010-10-18'))
1975        assert_equal(
1976                np.busday_offset('2010-10-16', 0, roll='modifiedpreceding'),
1977                np.datetime64('2010-10-15'))
1978        # roll='raise' by default
1979        assert_raises(ValueError, np.busday_offset, '2011-06-04', 0)
1980
1981        # Bigger offset values
1982        assert_equal(np.busday_offset('2006-02-01', 25),
1983                     np.datetime64('2006-03-08'))
1984        assert_equal(np.busday_offset('2006-03-08', -25),
1985                     np.datetime64('2006-02-01'))
1986        assert_equal(np.busday_offset('2007-02-25', 11, weekmask='SatSun'),
1987                     np.datetime64('2007-04-07'))
1988        assert_equal(np.busday_offset('2007-04-07', -11, weekmask='SatSun'),
1989                     np.datetime64('2007-02-25'))
1990
1991        # NaT values when roll is not raise
1992        assert_equal(np.busday_offset(np.datetime64('NaT'), 1, roll='nat'),
1993                     np.datetime64('NaT'))
1994        assert_equal(np.busday_offset(np.datetime64('NaT'), 1, roll='following'),
1995                     np.datetime64('NaT'))
1996        assert_equal(np.busday_offset(np.datetime64('NaT'), 1, roll='preceding'),
1997                     np.datetime64('NaT'))
1998
1999    def test_datetime_busdaycalendar(self):
2000        # Check that it removes NaT, duplicates, and weekends
2001        # and sorts the result.
2002        bdd = np.busdaycalendar(
2003            holidays=['NaT', '2011-01-17', '2011-03-06', 'NaT',
2004                       '2011-12-26', '2011-05-30', '2011-01-17'])
2005        assert_equal(bdd.holidays,
2006            np.array(['2011-01-17', '2011-05-30', '2011-12-26'], dtype='M8'))
2007        # Default M-F weekmask
2008        assert_equal(bdd.weekmask, np.array([1, 1, 1, 1, 1, 0, 0], dtype='?'))
2009
2010        # Check string weekmask with varying whitespace.
2011        bdd = np.busdaycalendar(weekmask="Sun TueWed  Thu\tFri")
2012        assert_equal(bdd.weekmask, np.array([0, 1, 1, 1, 1, 0, 1], dtype='?'))
2013
2014        # Check length 7 0/1 string
2015        bdd = np.busdaycalendar(weekmask="0011001")
2016        assert_equal(bdd.weekmask, np.array([0, 0, 1, 1, 0, 0, 1], dtype='?'))
2017
2018        # Check length 7 string weekmask.
2019        bdd = np.busdaycalendar(weekmask="Mon Tue")
2020        assert_equal(bdd.weekmask, np.array([1, 1, 0, 0, 0, 0, 0], dtype='?'))
2021
2022        # All-zeros weekmask should raise
2023        assert_raises(ValueError, np.busdaycalendar, weekmask=[0, 0, 0, 0, 0, 0, 0])
2024        # weekday names must be correct case
2025        assert_raises(ValueError, np.busdaycalendar, weekmask="satsun")
2026        # All-zeros weekmask should raise
2027        assert_raises(ValueError, np.busdaycalendar, weekmask="")
2028        # Invalid weekday name codes should raise
2029        assert_raises(ValueError, np.busdaycalendar, weekmask="Mon Tue We")
2030        assert_raises(ValueError, np.busdaycalendar, weekmask="Max")
2031        assert_raises(ValueError, np.busdaycalendar, weekmask="Monday Tue")
2032
2033    def test_datetime_busday_holidays_offset(self):
2034        # With exactly one holiday
2035        assert_equal(
2036            np.busday_offset('2011-11-10', 1, holidays=['2011-11-11']),
2037            np.datetime64('2011-11-14'))
2038        assert_equal(
2039            np.busday_offset('2011-11-04', 5, holidays=['2011-11-11']),
2040            np.datetime64('2011-11-14'))
2041        assert_equal(
2042            np.busday_offset('2011-11-10', 5, holidays=['2011-11-11']),
2043            np.datetime64('2011-11-18'))
2044        assert_equal(
2045            np.busday_offset('2011-11-14', -1, holidays=['2011-11-11']),
2046            np.datetime64('2011-11-10'))
2047        assert_equal(
2048            np.busday_offset('2011-11-18', -5, holidays=['2011-11-11']),
2049            np.datetime64('2011-11-10'))
2050        assert_equal(
2051            np.busday_offset('2011-11-14', -5, holidays=['2011-11-11']),
2052            np.datetime64('2011-11-04'))
2053        # With the holiday appearing twice
2054        assert_equal(
2055            np.busday_offset('2011-11-10', 1,
2056                holidays=['2011-11-11', '2011-11-11']),
2057            np.datetime64('2011-11-14'))
2058        assert_equal(
2059            np.busday_offset('2011-11-14', -1,
2060                holidays=['2011-11-11', '2011-11-11']),
2061            np.datetime64('2011-11-10'))
2062        # With a NaT holiday
2063        assert_equal(
2064            np.busday_offset('2011-11-10', 1,
2065                holidays=['2011-11-11', 'NaT']),
2066            np.datetime64('2011-11-14'))
2067        assert_equal(
2068            np.busday_offset('2011-11-14', -1,
2069                holidays=['NaT', '2011-11-11']),
2070            np.datetime64('2011-11-10'))
2071        # With another holiday after
2072        assert_equal(
2073            np.busday_offset('2011-11-10', 1,
2074                holidays=['2011-11-11', '2011-11-24']),
2075            np.datetime64('2011-11-14'))
2076        assert_equal(
2077            np.busday_offset('2011-11-14', -1,
2078                holidays=['2011-11-11', '2011-11-24']),
2079            np.datetime64('2011-11-10'))
2080        # With another holiday before
2081        assert_equal(
2082            np.busday_offset('2011-11-10', 1,
2083                holidays=['2011-10-10', '2011-11-11']),
2084            np.datetime64('2011-11-14'))
2085        assert_equal(
2086            np.busday_offset('2011-11-14', -1,
2087                holidays=['2011-10-10', '2011-11-11']),
2088            np.datetime64('2011-11-10'))
2089        # With another holiday before and after
2090        assert_equal(
2091            np.busday_offset('2011-11-10', 1,
2092                holidays=['2011-10-10', '2011-11-11', '2011-11-24']),
2093            np.datetime64('2011-11-14'))
2094        assert_equal(
2095            np.busday_offset('2011-11-14', -1,
2096                holidays=['2011-10-10', '2011-11-11', '2011-11-24']),
2097            np.datetime64('2011-11-10'))
2098
2099        # A bigger forward jump across more than one week/holiday
2100        holidays = ['2011-10-10', '2011-11-11', '2011-11-24',
2101                  '2011-12-25', '2011-05-30', '2011-02-21',
2102                  '2011-12-26', '2012-01-02']
2103        bdd = np.busdaycalendar(weekmask='1111100', holidays=holidays)
2104        assert_equal(
2105            np.busday_offset('2011-10-03', 4, holidays=holidays),
2106            np.busday_offset('2011-10-03', 4))
2107        assert_equal(
2108            np.busday_offset('2011-10-03', 5, holidays=holidays),
2109            np.busday_offset('2011-10-03', 5 + 1))
2110        assert_equal(
2111            np.busday_offset('2011-10-03', 27, holidays=holidays),
2112            np.busday_offset('2011-10-03', 27 + 1))
2113        assert_equal(
2114            np.busday_offset('2011-10-03', 28, holidays=holidays),
2115            np.busday_offset('2011-10-03', 28 + 2))
2116        assert_equal(
2117            np.busday_offset('2011-10-03', 35, holidays=holidays),
2118            np.busday_offset('2011-10-03', 35 + 2))
2119        assert_equal(
2120            np.busday_offset('2011-10-03', 36, holidays=holidays),
2121            np.busday_offset('2011-10-03', 36 + 3))
2122        assert_equal(
2123            np.busday_offset('2011-10-03', 56, holidays=holidays),
2124            np.busday_offset('2011-10-03', 56 + 3))
2125        assert_equal(
2126            np.busday_offset('2011-10-03', 57, holidays=holidays),
2127            np.busday_offset('2011-10-03', 57 + 4))
2128        assert_equal(
2129            np.busday_offset('2011-10-03', 60, holidays=holidays),
2130            np.busday_offset('2011-10-03', 60 + 4))
2131        assert_equal(
2132            np.busday_offset('2011-10-03', 61, holidays=holidays),
2133            np.busday_offset('2011-10-03', 61 + 5))
2134        assert_equal(
2135            np.busday_offset('2011-10-03', 61, busdaycal=bdd),
2136            np.busday_offset('2011-10-03', 61 + 5))
2137        # A bigger backward jump across more than one week/holiday
2138        assert_equal(
2139            np.busday_offset('2012-01-03', -1, holidays=holidays),
2140            np.busday_offset('2012-01-03', -1 - 1))
2141        assert_equal(
2142            np.busday_offset('2012-01-03', -4, holidays=holidays),
2143            np.busday_offset('2012-01-03', -4 - 1))
2144        assert_equal(
2145            np.busday_offset('2012-01-03', -5, holidays=holidays),
2146            np.busday_offset('2012-01-03', -5 - 2))
2147        assert_equal(
2148            np.busday_offset('2012-01-03', -25, holidays=holidays),
2149            np.busday_offset('2012-01-03', -25 - 2))
2150        assert_equal(
2151            np.busday_offset('2012-01-03', -26, holidays=holidays),
2152            np.busday_offset('2012-01-03', -26 - 3))
2153        assert_equal(
2154            np.busday_offset('2012-01-03', -33, holidays=holidays),
2155            np.busday_offset('2012-01-03', -33 - 3))
2156        assert_equal(
2157            np.busday_offset('2012-01-03', -34, holidays=holidays),
2158            np.busday_offset('2012-01-03', -34 - 4))
2159        assert_equal(
2160            np.busday_offset('2012-01-03', -56, holidays=holidays),
2161            np.busday_offset('2012-01-03', -56 - 4))
2162        assert_equal(
2163            np.busday_offset('2012-01-03', -57, holidays=holidays),
2164            np.busday_offset('2012-01-03', -57 - 5))
2165        assert_equal(
2166            np.busday_offset('2012-01-03', -57, busdaycal=bdd),
2167            np.busday_offset('2012-01-03', -57 - 5))
2168
2169        # Can't supply both a weekmask/holidays and busdaycal
2170        assert_raises(ValueError, np.busday_offset, '2012-01-03', -15,
2171                        weekmask='1111100', busdaycal=bdd)
2172        assert_raises(ValueError, np.busday_offset, '2012-01-03', -15,
2173                        holidays=holidays, busdaycal=bdd)
2174
2175        # Roll with the holidays
2176        assert_equal(
2177            np.busday_offset('2011-12-25', 0,
2178                roll='forward', holidays=holidays),
2179            np.datetime64('2011-12-27'))
2180        assert_equal(
2181            np.busday_offset('2011-12-26', 0,
2182                roll='forward', holidays=holidays),
2183            np.datetime64('2011-12-27'))
2184        assert_equal(
2185            np.busday_offset('2011-12-26', 0,
2186                roll='backward', holidays=holidays),
2187            np.datetime64('2011-12-23'))
2188        assert_equal(
2189            np.busday_offset('2012-02-27', 0,
2190                roll='modifiedfollowing',
2191                holidays=['2012-02-27', '2012-02-26', '2012-02-28',
2192                          '2012-03-01', '2012-02-29']),
2193            np.datetime64('2012-02-24'))
2194        assert_equal(
2195            np.busday_offset('2012-03-06', 0,
2196                roll='modifiedpreceding',
2197                holidays=['2012-03-02', '2012-03-03', '2012-03-01',
2198                          '2012-03-05', '2012-03-07', '2012-03-06']),
2199            np.datetime64('2012-03-08'))
2200
2201    def test_datetime_busday_holidays_count(self):
2202        holidays = ['2011-01-01', '2011-10-10', '2011-11-11', '2011-11-24',
2203                    '2011-12-25', '2011-05-30', '2011-02-21', '2011-01-17',
2204                    '2011-12-26', '2012-01-02', '2011-02-21', '2011-05-30',
2205                    '2011-07-01', '2011-07-04', '2011-09-05', '2011-10-10']
2206        bdd = np.busdaycalendar(weekmask='1111100', holidays=holidays)
2207
2208        # Validate against busday_offset broadcast against
2209        # a range of offsets
2210        dates = np.busday_offset('2011-01-01', np.arange(366),
2211                        roll='forward', busdaycal=bdd)
2212        assert_equal(np.busday_count('2011-01-01', dates, busdaycal=bdd),
2213                     np.arange(366))
2214        # Returns negative value when reversed
2215        assert_equal(np.busday_count(dates, '2011-01-01', busdaycal=bdd),
2216                     -np.arange(366))
2217
2218        dates = np.busday_offset('2011-12-31', -np.arange(366),
2219                        roll='forward', busdaycal=bdd)
2220        assert_equal(np.busday_count(dates, '2011-12-31', busdaycal=bdd),
2221                     np.arange(366))
2222        # Returns negative value when reversed
2223        assert_equal(np.busday_count('2011-12-31', dates, busdaycal=bdd),
2224                     -np.arange(366))
2225
2226        # Can't supply both a weekmask/holidays and busdaycal
2227        assert_raises(ValueError, np.busday_offset, '2012-01-03', '2012-02-03',
2228                        weekmask='1111100', busdaycal=bdd)
2229        assert_raises(ValueError, np.busday_offset, '2012-01-03', '2012-02-03',
2230                        holidays=holidays, busdaycal=bdd)
2231
2232        # Number of Mondays in March 2011
2233        assert_equal(np.busday_count('2011-03', '2011-04', weekmask='Mon'), 4)
2234        # Returns negative value when reversed
2235        assert_equal(np.busday_count('2011-04', '2011-03', weekmask='Mon'), -4)
2236
2237    def test_datetime_is_busday(self):
2238        holidays = ['2011-01-01', '2011-10-10', '2011-11-11', '2011-11-24',
2239                    '2011-12-25', '2011-05-30', '2011-02-21', '2011-01-17',
2240                    '2011-12-26', '2012-01-02', '2011-02-21', '2011-05-30',
2241                    '2011-07-01', '2011-07-04', '2011-09-05', '2011-10-10',
2242                    'NaT']
2243        bdd = np.busdaycalendar(weekmask='1111100', holidays=holidays)
2244
2245        # Weekend/weekday tests
2246        assert_equal(np.is_busday('2011-01-01'), False)
2247        assert_equal(np.is_busday('2011-01-02'), False)
2248        assert_equal(np.is_busday('2011-01-03'), True)
2249
2250        # All the holidays are not business days
2251        assert_equal(np.is_busday(holidays, busdaycal=bdd),
2252                     np.zeros(len(holidays), dtype='?'))
2253
2254    def test_datetime_y2038(self):
2255        # Test parsing on either side of the Y2038 boundary
2256        a = np.datetime64('2038-01-19T03:14:07')
2257        assert_equal(a.view(np.int64), 2**31 - 1)
2258        a = np.datetime64('2038-01-19T03:14:08')
2259        assert_equal(a.view(np.int64), 2**31)
2260
2261        # Test parsing on either side of the Y2038 boundary with
2262        # a manually specified timezone offset
2263        with assert_warns(DeprecationWarning):
2264            a = np.datetime64('2038-01-19T04:14:07+0100')
2265            assert_equal(a.view(np.int64), 2**31 - 1)
2266        with assert_warns(DeprecationWarning):
2267            a = np.datetime64('2038-01-19T04:14:08+0100')
2268            assert_equal(a.view(np.int64), 2**31)
2269
2270        # Test parsing a date after Y2038
2271        a = np.datetime64('2038-01-20T13:21:14')
2272        assert_equal(str(a), '2038-01-20T13:21:14')
2273
2274    def test_isnat(self):
2275        assert_(np.isnat(np.datetime64('NaT', 'ms')))
2276        assert_(np.isnat(np.datetime64('NaT', 'ns')))
2277        assert_(not np.isnat(np.datetime64('2038-01-19T03:14:07')))
2278
2279        assert_(np.isnat(np.timedelta64('NaT', "ms")))
2280        assert_(not np.isnat(np.timedelta64(34, "ms")))
2281
2282        res = np.array([False, False, True])
2283        for unit in ['Y', 'M', 'W', 'D',
2284                     'h', 'm', 's', 'ms', 'us',
2285                     'ns', 'ps', 'fs', 'as']:
2286            arr = np.array([123, -321, "NaT"], dtype='<datetime64[%s]' % unit)
2287            assert_equal(np.isnat(arr), res)
2288            arr = np.array([123, -321, "NaT"], dtype='>datetime64[%s]' % unit)
2289            assert_equal(np.isnat(arr), res)
2290            arr = np.array([123, -321, "NaT"], dtype='<timedelta64[%s]' % unit)
2291            assert_equal(np.isnat(arr), res)
2292            arr = np.array([123, -321, "NaT"], dtype='>timedelta64[%s]' % unit)
2293            assert_equal(np.isnat(arr), res)
2294
2295    def test_isnat_error(self):
2296        # Test that only datetime dtype arrays are accepted
2297        for t in np.typecodes["All"]:
2298            if t in np.typecodes["Datetime"]:
2299                continue
2300            assert_raises(TypeError, np.isnat, np.zeros(10, t))
2301
2302    def test_isfinite_scalar(self):
2303        assert_(not np.isfinite(np.datetime64('NaT', 'ms')))
2304        assert_(not np.isfinite(np.datetime64('NaT', 'ns')))
2305        assert_(np.isfinite(np.datetime64('2038-01-19T03:14:07')))
2306
2307        assert_(not np.isfinite(np.timedelta64('NaT', "ms")))
2308        assert_(np.isfinite(np.timedelta64(34, "ms")))
2309
2310    @pytest.mark.parametrize('unit', ['Y', 'M', 'W', 'D', 'h', 'm', 's', 'ms',
2311                                      'us', 'ns', 'ps', 'fs', 'as'])
2312    @pytest.mark.parametrize('dstr', ['<datetime64[%s]', '>datetime64[%s]',
2313                                      '<timedelta64[%s]', '>timedelta64[%s]'])
2314    def test_isfinite_isinf_isnan_units(self, unit, dstr):
2315        '''check isfinite, isinf, isnan for all units of <M, >M, <m, >m dtypes
2316        '''
2317        arr_val = [123, -321, "NaT"]
2318        arr = np.array(arr_val,  dtype= dstr % unit)
2319        pos = np.array([True, True,  False])
2320        neg = np.array([False, False,  True])
2321        false = np.array([False, False,  False])
2322        assert_equal(np.isfinite(arr), pos)
2323        assert_equal(np.isinf(arr), false)
2324        assert_equal(np.isnan(arr), neg)
2325
2326    def test_assert_equal(self):
2327        assert_raises(AssertionError, assert_equal,
2328                np.datetime64('nat'), np.timedelta64('nat'))
2329
2330    def test_corecursive_input(self):
2331        # construct a co-recursive list
2332        a, b = [], []
2333        a.append(b)
2334        b.append(a)
2335        obj_arr = np.array([None])
2336        obj_arr[0] = a
2337
2338        # At some point this caused a stack overflow (gh-11154). Now raises
2339        # ValueError since the nested list cannot be converted to a datetime.
2340        assert_raises(ValueError, obj_arr.astype, 'M8')
2341        assert_raises(ValueError, obj_arr.astype, 'm8')
2342
2343    @pytest.mark.parametrize("shape", [(), (1,)])
2344    def test_discovery_from_object_array(self, shape):
2345        arr = np.array("2020-10-10", dtype=object).reshape(shape)
2346        res = np.array("2020-10-10", dtype="M8").reshape(shape)
2347        assert res.dtype == np.dtype("M8[D]")
2348        assert_equal(arr.astype("M8"), res)
2349        arr[...] = np.bytes_("2020-10-10")  # try a numpy string type
2350        assert_equal(arr.astype("M8"), res)
2351        arr = arr.astype("S")
2352        assert_equal(arr.astype("S").astype("M8"), res)
2353
2354    @pytest.mark.parametrize("time_unit", [
2355        "Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "ps", "fs", "as",
2356        # compound units
2357        "10D", "2M",
2358    ])
2359    def test_limit_symmetry(self, time_unit):
2360        """
2361        Dates should have symmetric limits around the unix epoch at +/-np.int64
2362        """
2363        epoch = np.datetime64(0, time_unit)
2364        latest = np.datetime64(np.iinfo(np.int64).max, time_unit)
2365        earliest = np.datetime64(-np.iinfo(np.int64).max, time_unit)
2366
2367        # above should not have overflowed
2368        assert earliest < epoch < latest
2369
2370    @pytest.mark.parametrize("time_unit", [
2371        "Y", "M",
2372        pytest.param("W", marks=pytest.mark.xfail(reason="gh-13197")),
2373        "D", "h", "m",
2374        "s", "ms", "us", "ns", "ps", "fs", "as",
2375        pytest.param("10D", marks=pytest.mark.xfail(reason="similar to gh-13197")),
2376    ])
2377    @pytest.mark.parametrize("sign", [-1, 1])
2378    def test_limit_str_roundtrip(self, time_unit, sign):
2379        """
2380        Limits should roundtrip when converted to strings.
2381
2382        This tests the conversion to and from npy_datetimestruct.
2383        """
2384        # TODO: add absolute (gold standard) time span limit strings
2385        limit = np.datetime64(np.iinfo(np.int64).max * sign, time_unit)
2386
2387        # Convert to string and back. Explicit unit needed since the day and
2388        # week reprs are not distinguishable.
2389        limit_via_str = np.datetime64(str(limit), time_unit)
2390        assert limit_via_str == limit
2391
2392
2393class TestDateTimeData:
2394
2395    def test_basic(self):
2396        a = np.array(['1980-03-23'], dtype=np.datetime64)
2397        assert_equal(np.datetime_data(a.dtype), ('D', 1))
2398
2399    def test_bytes(self):
2400        # byte units are converted to unicode
2401        dt = np.datetime64('2000', (b'ms', 5))
2402        assert np.datetime_data(dt.dtype) == ('ms', 5)
2403
2404        dt = np.datetime64('2000', b'5ms')
2405        assert np.datetime_data(dt.dtype) == ('ms', 5)
2406
2407    def test_non_ascii(self):
2408        # μs is normalized to μ
2409        dt = np.datetime64('2000', ('μs', 5))
2410        assert np.datetime_data(dt.dtype) == ('us', 5)
2411
2412        dt = np.datetime64('2000', '5μs')
2413        assert np.datetime_data(dt.dtype) == ('us', 5)
2414