codekingpro/portable-devtools
115k
1import datetime
2import pickle
3import warnings
4from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
5
6import pytest
7
8import numpy
9import numpy as np
10from numpy.testing import (
11 IS_WASM,
12 assert_,
13 assert_array_equal,
14 assert_equal,
15 assert_raises,
16 assert_raises_regex,
17)
18
19try:
20 RecursionError
21except NameError:
22 RecursionError = RuntimeError # python < 3.5
23
24try:
25 ZoneInfo("US/Central")
26 _has_tz = True
27except ZoneInfoNotFoundError:
28 _has_tz = False
29
30def _assert_equal_hash(v1, v2):
31 assert v1 == v2
32 assert hash(v1) == hash(v2)
33 assert v2 in {v1}
34
35
36class TestDateTime:
37
38 def test_string(self):
39 msg = "no explicit representation of timezones available for " \
40 "np.datetime64"
41 with pytest.warns(UserWarning, match=msg):
42 np.datetime64('2000-01-01T00+01')
43
44 def test_datetime(self):
45 msg = "no explicit representation of timezones available for " \
46 "np.datetime64"
47 with pytest.warns(UserWarning, match=msg):
48 t0 = np.datetime64('2023-06-09T12:18:40Z', 'ns')
49
50 t0 = np.datetime64('2023-06-09T12:18:40', 'ns')
51
52 def test_datetime_dtype_creation(self):
53 for unit in ['Y', 'M', 'W', 'D',
54 'h', 'm', 's', 'ms', 'us',
55 'μs', # alias for us
56 'ns', 'ps', 'fs', 'as']:
57 dt1 = np.dtype(f'M8[750{unit}]')
58 assert_(dt1 == np.dtype(f'datetime64[750{unit}]'))
59 dt2 = np.dtype(f'm8[{unit}]')
60 assert_(dt2 == np.dtype(f'timedelta64[{unit}]'))
61
62 # Generic units shouldn't add [] to the end
63 assert_equal(str(np.dtype("M8")), "datetime64")
64
65 # Should be possible to specify the endianness
66 assert_equal(np.dtype("=M8"), np.dtype("M8"))
67 assert_equal(np.dtype("=M8[s]"), np.dtype("M8[s]"))
68 assert_(np.dtype(">M8") == np.dtype("M8") or
69 np.dtype("<M8") == np.dtype("M8"))
70 assert_(np.dtype(">M8[D]") == np.dtype("M8[D]") or
71 np.dtype("<M8[D]") == np.dtype("M8[D]"))
72 assert_(np.dtype(">M8") != np.dtype("<M8"))
73
74 assert_equal(np.dtype("=m8"), np.dtype("m8"))
75 assert_equal(np.dtype("=m8[s]"), np.dtype("m8[s]"))
76 assert_(np.dtype(">m8") == np.dtype("m8") or
77 np.dtype("<m8") == np.dtype("m8"))
78 assert_(np.dtype(">m8[D]") == np.dtype("m8[D]") or
79 np.dtype("<m8[D]") == np.dtype("m8[D]"))
80 assert_(np.dtype(">m8") != np.dtype("<m8"))
81
82 # Check that the parser rejects bad datetime types
83 assert_raises(TypeError, np.dtype, 'M8[badunit]')
84 assert_raises(TypeError, np.dtype, 'm8[badunit]')
85 assert_raises(TypeError, np.dtype, 'M8[YY]')
86 assert_raises(TypeError, np.dtype, 'm8[YY]')
87 assert_raises(TypeError, np.dtype, 'm4')
88 assert_raises(TypeError, np.dtype, 'M7')
89 assert_raises(TypeError, np.dtype, 'm7')
90 assert_raises(TypeError, np.dtype, 'M16')
91 assert_raises(TypeError, np.dtype, 'm16')
92 assert_raises(TypeError, np.dtype, 'M8[3000000000ps]')
93
94 def test_datetime_casting_rules(self):
95 # Cannot cast safely/same_kind between timedelta and datetime
96 assert_(not np.can_cast('m8', 'M8', casting='same_kind'))
97 assert_(not np.can_cast('M8', 'm8', casting='same_kind'))
98 assert_(not np.can_cast('m8', 'M8', casting='safe'))
99 assert_(not np.can_cast('M8', 'm8', casting='safe'))
100
101 # Can cast safely/same_kind from integer to timedelta
102 assert_(np.can_cast('i8', 'm8', casting='same_kind'))
103 assert_(np.can_cast('i8', 'm8', casting='safe'))
104 assert_(np.can_cast('i4', 'm8', casting='same_kind'))
105 assert_(np.can_cast('i4', 'm8', casting='safe'))
106 assert_(np.can_cast('u4', 'm8', casting='same_kind'))
107 assert_(np.can_cast('u4', 'm8', casting='safe'))
108
109 # Cannot cast safely from unsigned integer of the same size, which
110 # could overflow
111 assert_(np.can_cast('u8', 'm8', casting='same_kind'))
112 assert_(not np.can_cast('u8', 'm8', casting='safe'))
113
114 # Cannot cast safely/same_kind from float to timedelta
115 assert_(not np.can_cast('f4', 'm8', casting='same_kind'))
116 assert_(not np.can_cast('f4', 'm8', casting='safe'))
117
118 # Cannot cast safely/same_kind from integer to datetime
119 assert_(not np.can_cast('i8', 'M8', casting='same_kind'))
120 assert_(not np.can_cast('i8', 'M8', casting='safe'))
121
122 # Cannot cast safely/same_kind from bool to datetime
123 assert_(not np.can_cast('b1', 'M8', casting='same_kind'))
124 assert_(not np.can_cast('b1', 'M8', casting='safe'))
125 # Can cast safely/same_kind from bool to timedelta
126 assert_(np.can_cast('b1', 'm8', casting='same_kind'))
127 assert_(np.can_cast('b1', 'm8', casting='safe'))
128
129 # Can cast datetime safely from months/years to days
130 assert_(np.can_cast('M8[M]', 'M8[D]', casting='safe'))
131 assert_(np.can_cast('M8[Y]', 'M8[D]', casting='safe'))
132 # Cannot cast timedelta safely from months/years to days
133 assert_(not np.can_cast('m8[M]', 'm8[D]', casting='safe'))
134 assert_(not np.can_cast('m8[Y]', 'm8[D]', casting='safe'))
135 # Can cast datetime same_kind from months/years to days
136 assert_(np.can_cast('M8[M]', 'M8[D]', casting='same_kind'))
137 assert_(np.can_cast('M8[Y]', 'M8[D]', casting='same_kind'))
138 # Can't cast timedelta same_kind from months/years to days
139 assert_(not np.can_cast('m8[M]', 'm8[D]', casting='same_kind'))
140 assert_(not np.can_cast('m8[Y]', 'm8[D]', casting='same_kind'))
141 # Can cast datetime same_kind across the date/time boundary
142 assert_(np.can_cast('M8[D]', 'M8[h]', casting='same_kind'))
143 # Can cast timedelta same_kind across the date/time boundary
144 assert_(np.can_cast('m8[D]', 'm8[h]', casting='same_kind'))
145 assert_(np.can_cast('m8[h]', 'm8[D]', casting='same_kind'))
146
147 # Cannot cast safely if the integer multiplier doesn't divide
148 assert_(not np.can_cast('M8[7h]', 'M8[3h]', casting='safe'))
149 assert_(not np.can_cast('M8[3h]', 'M8[6h]', casting='safe'))
150 # But can cast same_kind
151 assert_(np.can_cast('M8[7h]', 'M8[3h]', casting='same_kind'))
152 # Can cast safely if the integer multiplier does divide
153 assert_(np.can_cast('M8[6h]', 'M8[3h]', casting='safe'))
154
155 # We can always cast types with generic units (corresponding to NaT) to
156 # more specific types
157 assert_(np.can_cast('m8', 'm8[h]', casting='same_kind'))
158 assert_(np.can_cast('m8', 'm8[h]', casting='safe'))
159 assert_(np.can_cast('M8', 'M8[h]', casting='same_kind'))
160 assert_(np.can_cast('M8', 'M8[h]', casting='safe'))
161 # but not the other way around
162 assert_(not np.can_cast('m8[h]', 'm8', casting='same_kind'))
163 assert_(not np.can_cast('m8[h]', 'm8', casting='safe'))
164 assert_(not np.can_cast('M8[h]', 'M8', casting='same_kind'))
165 assert_(not np.can_cast('M8[h]', 'M8', casting='safe'))
166
167 def test_datetime_prefix_conversions(self):
168 # regression tests related to gh-19631;
169 # test metric prefixes from seconds down to
170 # attoseconds for bidirectional conversions
171 smaller_units = ['M8[7000ms]',
172 'M8[2000us]',
173 'M8[1000ns]',
174 'M8[5000ns]',
175 'M8[2000ps]',
176 'M8[9000fs]',
177 'M8[1000as]',
178 'M8[2000000ps]',
179 'M8[1000000as]',
180 'M8[2000000000ps]',
181 'M8[1000000000as]']
182 larger_units = ['M8[7s]',
183 'M8[2ms]',
184 'M8[us]',
185 'M8[5us]',
186 'M8[2ns]',
187 'M8[9ps]',
188 'M8[1fs]',
189 'M8[2us]',
190 'M8[1ps]',
191 'M8[2ms]',
192 'M8[1ns]']
193 for larger_unit, smaller_unit in zip(larger_units, smaller_units):
194 assert np.can_cast(larger_unit, smaller_unit, casting='safe')
195 assert np.can_cast(smaller_unit, larger_unit, casting='safe')
196
197 @pytest.mark.parametrize("unit", [
198 "s", "ms", "us", "ns", "ps", "fs", "as"])
199 def test_prohibit_negative_datetime(self, unit):
200 with assert_raises(TypeError):
201 np.array([1], dtype=f"M8[-1{unit}]")
202
203 def test_compare_generic_nat(self):
204 # regression tests for gh-6452
205 assert_(np.datetime64('NaT') !=
206 np.datetime64('2000') + np.timedelta64('NaT'))
207 assert_(np.datetime64('NaT') != np.datetime64('NaT', 'us'))
208 assert_(np.datetime64('NaT', 'us') != np.datetime64('NaT'))
209
210 @pytest.mark.parametrize("size", [
211 3, 21, 217, 1000])
212 def test_datetime_nat_argsort_stability(self, size):
213 # NaT < NaT should be False internally for
214 # sort stability
215 expected = np.arange(size)
216 arr = np.tile(np.datetime64('NaT'), size)
217 assert_equal(np.argsort(arr, kind='mergesort'), expected)
218
219 @pytest.mark.parametrize("size", [
220 3, 21, 217, 1000])
221 def test_timedelta_nat_argsort_stability(self, size):
222 # NaT < NaT should be False internally for
223 # sort stability
224 expected = np.arange(size)
225 arr = np.tile(np.timedelta64('NaT'), size)
226 assert_equal(np.argsort(arr, kind='mergesort'), expected)
227
228 @pytest.mark.parametrize("arr, expected", [
229 # the example provided in gh-12629
230 (['NaT', 1, 2, 3],
231 [1, 2, 3, 'NaT']),
232 # multiple NaTs
233 (['NaT', 9, 'NaT', -707],
234 [-707, 9, 'NaT', 'NaT']),
235 # this sort explores another code path for NaT
236 ([1, -2, 3, 'NaT'],
237 [-2, 1, 3, 'NaT']),
238 # 2-D array
239 ([[51, -220, 'NaT'],
240 [-17, 'NaT', -90]],
241 [[-220, 51, 'NaT'],
242 [-90, -17, 'NaT']]),
243 ])
244 @pytest.mark.parametrize("dtype", [
245 'M8[ns]', 'M8[us]',
246 'm8[ns]', 'm8[us]'])
247 def test_datetime_timedelta_sort_nat(self, arr, expected, dtype):
248 # fix for gh-12629 and gh-15063; NaT sorting to end of array
249 arr = np.array(arr, dtype=dtype)
250 expected = np.array(expected, dtype=dtype)
251 arr.sort()
252 assert_equal(arr, expected)
253
254 def test_datetime_scalar_construction(self):
255 # Construct with different units
256 assert_equal(np.datetime64('1950-03-12', 'D'),
257 np.datetime64('1950-03-12'))
258 assert_equal(np.datetime64('1950-03-12T13', 's'),
259 np.datetime64('1950-03-12T13', 'm'))
260
261 # Default construction means NaT
262 assert_equal(np.datetime64(), np.datetime64('NaT'))
263
264 # Some basic strings and repr
265 assert_equal(str(np.datetime64('NaT')), 'NaT')
266 assert_equal(repr(np.datetime64('NaT')),
267 "np.datetime64('NaT','generic')")
268 assert_equal(str(np.datetime64('2011-02')), '2011-02')
269 assert_equal(repr(np.datetime64('2011-02')),
270 "np.datetime64('2011-02')")
271 assert_equal(repr(np.datetime64('NaT').astype(np.dtype("datetime64[ns]"))),
272 "np.datetime64('NaT','ns')")
273
274 # None gets constructed as NaT
275 assert_equal(np.datetime64(None), np.datetime64('NaT'))
276
277 # Default construction of NaT is in generic units
278 assert_equal(np.datetime64().dtype, np.dtype('M8'))
279 assert_equal(np.datetime64('NaT').dtype, np.dtype('M8'))
280
281 # Construction from integers requires a specified unit
282 assert_raises(ValueError, np.datetime64, 17)
283
284 # When constructing from a scalar or zero-dimensional array,
285 # it either keeps the units or you can override them.
286 a = np.datetime64('2000-03-18T16', 'h')
287 b = np.array('2000-03-18T16', dtype='M8[h]')
288
289 assert_equal(a.dtype, np.dtype('M8[h]'))
290 assert_equal(b.dtype, np.dtype('M8[h]'))
291
292 assert_equal(np.datetime64(a), a)
293 assert_equal(np.datetime64(a).dtype, np.dtype('M8[h]'))
294
295 assert_equal(np.datetime64(b), a)
296 assert_equal(np.datetime64(b).dtype, np.dtype('M8[h]'))
297
298 assert_equal(np.datetime64(a, 's'), a)
299 assert_equal(np.datetime64(a, 's').dtype, np.dtype('M8[s]'))
300
301 assert_equal(np.datetime64(b, 's'), a)
302 assert_equal(np.datetime64(b, 's').dtype, np.dtype('M8[s]'))
303
304 # Construction from datetime.date
305 assert_equal(np.datetime64('1945-03-25'),
306 np.datetime64(datetime.date(1945, 3, 25)))
307 assert_equal(np.datetime64('2045-03-25', 'D'),
308 np.datetime64(datetime.date(2045, 3, 25), 'D'))
309 # Construction from datetime.datetime
310 assert_equal(np.datetime64('1980-01-25T14:36:22.5'),
311 np.datetime64(datetime.datetime(1980, 1, 25,
312 14, 36, 22, 500000)))
313
314 # Construction with time units from a date is okay
315 assert_equal(np.datetime64('1920-03-13', 'h'),
316 np.datetime64('1920-03-13T00'))
317 assert_equal(np.datetime64('1920-03', 'm'),
318 np.datetime64('1920-03-01T00:00'))
319 assert_equal(np.datetime64('1920', 's'),
320 np.datetime64('1920-01-01T00:00:00'))
321 assert_equal(np.datetime64(datetime.date(2045, 3, 25), 'ms'),
322 np.datetime64('2045-03-25T00:00:00.000'))
323
324 # Construction with date units from a datetime is also okay
325 assert_equal(np.datetime64('1920-03-13T18', 'D'),
326 np.datetime64('1920-03-13'))
327 assert_equal(np.datetime64('1920-03-13T18:33:12', 'M'),
328 np.datetime64('1920-03'))
329 assert_equal(np.datetime64('1920-03-13T18:33:12.5', 'Y'),
330 np.datetime64('1920'))
331
332 def test_datetime_scalar_construction_timezone(self):
333 msg = "no explicit representation of timezones available for " \
334 "np.datetime64"
335 # verify that supplying an explicit timezone works, but is deprecated
336 with pytest.warns(UserWarning, match=msg):
337 assert_equal(np.datetime64('2000-01-01T00Z'),
338 np.datetime64('2000-01-01T00'))
339 with pytest.warns(UserWarning, match=msg):
340 assert_equal(np.datetime64('2000-01-01T00-08'),
341 np.datetime64('2000-01-01T08'))
342
343 def test_datetime_array_find_type(self):
344 dt = np.datetime64('1970-01-01', 'M')
345 arr = np.array([dt])
346 assert_equal(arr.dtype, np.dtype('M8[M]'))
347
348 # at the moment, we don't automatically convert these to datetime64
349
350 dt = datetime.date(1970, 1, 1)
351 arr = np.array([dt])
352 assert_equal(arr.dtype, np.dtype('O'))
353
354 dt = datetime.datetime(1970, 1, 1, 12, 30, 40)
355 arr = np.array([dt])
356 assert_equal(arr.dtype, np.dtype('O'))
357
358 # find "supertype" for non-dates and dates
359
360 b = np.bool(True)
361 dm = np.datetime64('1970-01-01', 'M')
362 d = datetime.date(1970, 1, 1)
363 dt = datetime.datetime(1970, 1, 1, 12, 30, 40)
364
365 arr = np.array([b, dm])
366 assert_equal(arr.dtype, np.dtype('O'))
367
368 arr = np.array([b, d])
369 assert_equal(arr.dtype, np.dtype('O'))
370
371 arr = np.array([b, dt])
372 assert_equal(arr.dtype, np.dtype('O'))
373
374 arr = np.array([d, d]).astype('datetime64')
375 assert_equal(arr.dtype, np.dtype('M8[D]'))
376
377 arr = np.array([dt, dt]).astype('datetime64')
378 assert_equal(arr.dtype, np.dtype('M8[us]'))
379
380 @pytest.mark.parametrize("unit", [
381 # test all date / time units and use
382 # "generic" to select generic unit
383 ("Y"), ("M"), ("W"), ("D"), ("h"), ("m"),
384 ("s"), ("ms"), ("us"), ("ns"), ("ps"),
385 ("fs"), ("as"), ("generic")])
386 def test_timedelta_np_int_construction(self, unit):
387 # regression test for gh-7617
388 if unit != "generic":
389 assert_equal(np.timedelta64(np.int64(123), unit),
390 np.timedelta64(123, unit))
391 else:
392 assert_equal(np.timedelta64(np.int64(123)),
393 np.timedelta64(123))
394
395 def test_timedelta_scalar_construction(self):
396 # Construct with different units
397 assert_equal(np.timedelta64(7, 'D'),
398 np.timedelta64(1, 'W'))
399 assert_equal(np.timedelta64(120, 's'),
400 np.timedelta64(2, 'm'))
401
402 # Default construction means 0
403 assert_equal(np.timedelta64(), np.timedelta64(0))
404
405 # None gets constructed as NaT
406 assert_equal(np.timedelta64(None), np.timedelta64('NaT'))
407
408 # Some basic strings and repr
409 assert_equal(str(np.timedelta64('NaT')), 'NaT')
410 assert_equal(repr(np.timedelta64('NaT')),
411 "np.timedelta64('NaT')")
412 assert_equal(str(np.timedelta64(3, 's')), '3 seconds')
413 assert_equal(repr(np.timedelta64(-3, 's')),
414 "np.timedelta64(-3,'s')")
415 assert_equal(repr(np.timedelta64(12)),
416 "np.timedelta64(12)")
417
418 # Construction from an integer produces generic units
419 assert_equal(np.timedelta64(12).dtype, np.dtype('m8'))
420
421 # When constructing from a scalar or zero-dimensional array,
422 # it either keeps the units or you can override them.
423 a = np.timedelta64(2, 'h')
424 b = np.array(2, dtype='m8[h]')
425
426 assert_equal(a.dtype, np.dtype('m8[h]'))
427 assert_equal(b.dtype, np.dtype('m8[h]'))
428
429 assert_equal(np.timedelta64(a), a)
430 assert_equal(np.timedelta64(a).dtype, np.dtype('m8[h]'))
431
432 assert_equal(np.timedelta64(b), a)
433 assert_equal(np.timedelta64(b).dtype, np.dtype('m8[h]'))
434
435 assert_equal(np.timedelta64(a, 's'), a)
436 assert_equal(np.timedelta64(a, 's').dtype, np.dtype('m8[s]'))
437
438 assert_equal(np.timedelta64(b, 's'), a)
439 assert_equal(np.timedelta64(b, 's').dtype, np.dtype('m8[s]'))
440
441 # Construction from datetime.timedelta
442 assert_equal(np.timedelta64(5, 'D'),
443 np.timedelta64(datetime.timedelta(days=5)))
444 assert_equal(np.timedelta64(102347621, 's'),
445 np.timedelta64(datetime.timedelta(seconds=102347621)))
446 assert_equal(np.timedelta64(-10234760000, 'us'),
447 np.timedelta64(datetime.timedelta(
448 microseconds=-10234760000)))
449 assert_equal(np.timedelta64(10234760000, 'us'),
450 np.timedelta64(datetime.timedelta(
451 microseconds=10234760000)))
452 assert_equal(np.timedelta64(1023476, 'ms'),
453 np.timedelta64(datetime.timedelta(milliseconds=1023476)))
454 assert_equal(np.timedelta64(10, 'm'),
455 np.timedelta64(datetime.timedelta(minutes=10)))
456 assert_equal(np.timedelta64(281, 'h'),
457 np.timedelta64(datetime.timedelta(hours=281)))
458 assert_equal(np.timedelta64(28, 'W'),
459 np.timedelta64(datetime.timedelta(weeks=28)))
460
461 # Cannot construct across nonlinear time unit boundaries
462 a = np.timedelta64(3, 's')
463 assert_raises(TypeError, np.timedelta64, a, 'M')
464 assert_raises(TypeError, np.timedelta64, a, 'Y')
465 a = np.timedelta64(6, 'M')
466 assert_raises(TypeError, np.timedelta64, a, 'D')
467 assert_raises(TypeError, np.timedelta64, a, 'h')
468 a = np.timedelta64(1, 'Y')
469 assert_raises(TypeError, np.timedelta64, a, 'D')
470 assert_raises(TypeError, np.timedelta64, a, 'm')
471 a = datetime.timedelta(seconds=3)
472 assert_raises(TypeError, np.timedelta64, a, 'M')
473 assert_raises(TypeError, np.timedelta64, a, 'Y')
474 a = datetime.timedelta(weeks=3)
475 assert_raises(TypeError, np.timedelta64, a, 'M')
476 assert_raises(TypeError, np.timedelta64, a, 'Y')
477 a = datetime.timedelta()
478 assert_raises(TypeError, np.timedelta64, a, 'M')
479 assert_raises(TypeError, np.timedelta64, a, 'Y')
480
481 def test_timedelta_object_array_conversion(self):
482 # Regression test for gh-11096
483 inputs = [datetime.timedelta(28),
484 datetime.timedelta(30),
485 datetime.timedelta(31)]
486 expected = np.array([28, 30, 31], dtype='timedelta64[D]')
487 actual = np.array(inputs, dtype='timedelta64[D]')
488 assert_equal(expected, actual)
489
490 def test_timedelta_0_dim_object_array_conversion(self):
491 # Regression test for gh-11151
492 test = np.array(datetime.timedelta(seconds=20))
493 actual = test.astype(np.timedelta64)
494 # expected value from the array constructor workaround
495 # described in above issue
496 expected = np.array(datetime.timedelta(seconds=20),
497 np.timedelta64)
498 assert_equal(actual, expected)
499
500 def test_timedelta_nat_format(self):
501 # gh-17552
502 assert_equal('NaT', f'{np.timedelta64("nat")}')
503
504 def test_timedelta_scalar_construction_units(self):
505 # String construction detecting units
506 assert_equal(np.datetime64('2010').dtype,
507 np.dtype('M8[Y]'))
508 assert_equal(np.datetime64('2010-03').dtype,
509 np.dtype('M8[M]'))
510 assert_equal(np.datetime64('2010-03-12').dtype,
511 np.dtype('M8[D]'))
512 assert_equal(np.datetime64('2010-03-12T17').dtype,
513 np.dtype('M8[h]'))
514 assert_equal(np.datetime64('2010-03-12T17:15').dtype,
515 np.dtype('M8[m]'))
516 assert_equal(np.datetime64('2010-03-12T17:15:08').dtype,
517 np.dtype('M8[s]'))
518
519 assert_equal(np.datetime64('2010-03-12T17:15:08.1').dtype,
520 np.dtype('M8[ms]'))
521 assert_equal(np.datetime64('2010-03-12T17:15:08.12').dtype,
522 np.dtype('M8[ms]'))
523 assert_equal(np.datetime64('2010-03-12T17:15:08.123').dtype,
524 np.dtype('M8[ms]'))
525
526 assert_equal(np.datetime64('2010-03-12T17:15:08.1234').dtype,
527 np.dtype('M8[us]'))
528 assert_equal(np.datetime64('2010-03-12T17:15:08.12345').dtype,
529 np.dtype('M8[us]'))
530 assert_equal(np.datetime64('2010-03-12T17:15:08.123456').dtype,
531 np.dtype('M8[us]'))
532
533 assert_equal(np.datetime64('1970-01-01T00:00:02.1234567').dtype,
534 np.dtype('M8[ns]'))
535 assert_equal(np.datetime64('1970-01-01T00:00:02.12345678').dtype,
536 np.dtype('M8[ns]'))
537 assert_equal(np.datetime64('1970-01-01T00:00:02.123456789').dtype,
538 np.dtype('M8[ns]'))
539
540 assert_equal(np.datetime64('1970-01-01T00:00:02.1234567890').dtype,
541 np.dtype('M8[ps]'))
542 assert_equal(np.datetime64('1970-01-01T00:00:02.12345678901').dtype,
543 np.dtype('M8[ps]'))
544 assert_equal(np.datetime64('1970-01-01T00:00:02.123456789012').dtype,
545 np.dtype('M8[ps]'))
546
547 assert_equal(np.datetime64(
548 '1970-01-01T00:00:02.1234567890123').dtype,
549 np.dtype('M8[fs]'))
550 assert_equal(np.datetime64(
551 '1970-01-01T00:00:02.12345678901234').dtype,
552 np.dtype('M8[fs]'))
553 assert_equal(np.datetime64(
554 '1970-01-01T00:00:02.123456789012345').dtype,
555 np.dtype('M8[fs]'))
556
557 assert_equal(np.datetime64(
558 '1970-01-01T00:00:02.1234567890123456').dtype,
559 np.dtype('M8[as]'))
560 assert_equal(np.datetime64(
561 '1970-01-01T00:00:02.12345678901234567').dtype,
562 np.dtype('M8[as]'))
563 assert_equal(np.datetime64(
564 '1970-01-01T00:00:02.123456789012345678').dtype,
565 np.dtype('M8[as]'))
566
567 # Python date object
568 assert_equal(np.datetime64(datetime.date(2010, 4, 16)).dtype,
569 np.dtype('M8[D]'))
570
571 # Python datetime object
572 assert_equal(np.datetime64(
573 datetime.datetime(2010, 4, 16, 13, 45, 18)).dtype,
574 np.dtype('M8[us]'))
575
576 # 'today' special value
577 assert_equal(np.datetime64('today').dtype,
578 np.dtype('M8[D]'))
579
580 # 'now' special value
581 assert_equal(np.datetime64('now').dtype,
582 np.dtype('M8[s]'))
583
584 def test_datetime_nat_casting(self):
585 a = np.array('NaT', dtype='M8[D]')
586 b = np.datetime64('NaT', '[D]')
587
588 # Arrays
589 assert_equal(a.astype('M8[s]'), np.array('NaT', dtype='M8[s]'))
590 assert_equal(a.astype('M8[ms]'), np.array('NaT', dtype='M8[ms]'))
591 assert_equal(a.astype('M8[M]'), np.array('NaT', dtype='M8[M]'))
592 assert_equal(a.astype('M8[Y]'), np.array('NaT', dtype='M8[Y]'))
593 assert_equal(a.astype('M8[W]'), np.array('NaT', dtype='M8[W]'))
594
595 # Scalars -> Scalars
596 assert_equal(np.datetime64(b, '[s]'), np.datetime64('NaT', '[s]'))
597 assert_equal(np.datetime64(b, '[ms]'), np.datetime64('NaT', '[ms]'))
598 assert_equal(np.datetime64(b, '[M]'), np.datetime64('NaT', '[M]'))
599 assert_equal(np.datetime64(b, '[Y]'), np.datetime64('NaT', '[Y]'))
600 assert_equal(np.datetime64(b, '[W]'), np.datetime64('NaT', '[W]'))
601
602 # Arrays -> Scalars
603 assert_equal(np.datetime64(a, '[s]'), np.datetime64('NaT', '[s]'))
604 assert_equal(np.datetime64(a, '[ms]'), np.datetime64('NaT', '[ms]'))
605 assert_equal(np.datetime64(a, '[M]'), np.datetime64('NaT', '[M]'))
606 assert_equal(np.datetime64(a, '[Y]'), np.datetime64('NaT', '[Y]'))
607 assert_equal(np.datetime64(a, '[W]'), np.datetime64('NaT', '[W]'))
608
609 # NaN -> NaT
610 nan = np.array([np.nan] * 8 + [0])
611 fnan = nan.astype('f')
612 lnan = nan.astype('g')
613 cnan = nan.astype('D')
614 cfnan = nan.astype('F')
615 clnan = nan.astype('G')
616 hnan = nan.astype(np.half)
617
618 nat = np.array([np.datetime64('NaT')] * 8 + [np.datetime64(0, 'D')])
619 assert_equal(nan.astype('M8[ns]'), nat)
620 assert_equal(fnan.astype('M8[ns]'), nat)
621 assert_equal(lnan.astype('M8[ns]'), nat)
622 assert_equal(cnan.astype('M8[ns]'), nat)
623 assert_equal(cfnan.astype('M8[ns]'), nat)
624 assert_equal(clnan.astype('M8[ns]'), nat)
625 assert_equal(hnan.astype('M8[ns]'), nat)
626
627 nat = np.array([np.timedelta64('NaT')] * 8 + [np.timedelta64(0)])
628 assert_equal(nan.astype('timedelta64[ns]'), nat)
629 assert_equal(fnan.astype('timedelta64[ns]'), nat)
630 assert_equal(lnan.astype('timedelta64[ns]'), nat)
631 assert_equal(cnan.astype('timedelta64[ns]'), nat)
632 assert_equal(cfnan.astype('timedelta64[ns]'), nat)
633 assert_equal(clnan.astype('timedelta64[ns]'), nat)
634 assert_equal(hnan.astype('timedelta64[ns]'), nat)
635
636 def test_days_creation(self):
637 assert_equal(np.array('1599', dtype='M8[D]').astype('i8'),
638 (1600 - 1970) * 365 - (1972 - 1600) / 4 + 3 - 365)
639 assert_equal(np.array('1600', dtype='M8[D]').astype('i8'),
640 (1600 - 1970) * 365 - (1972 - 1600) / 4 + 3)
641 assert_equal(np.array('1601', dtype='M8[D]').astype('i8'),
642 (1600 - 1970) * 365 - (1972 - 1600) / 4 + 3 + 366)
643 assert_equal(np.array('1900', dtype='M8[D]').astype('i8'),
644 (1900 - 1970) * 365 - (1970 - 1900) // 4)
645 assert_equal(np.array('1901', dtype='M8[D]').astype('i8'),
646 (1900 - 1970) * 365 - (1970 - 1900) // 4 + 365)
647 assert_equal(np.array('1967', dtype='M8[D]').astype('i8'), -3 * 365 - 1)
648 assert_equal(np.array('1968', dtype='M8[D]').astype('i8'), -2 * 365 - 1)
649 assert_equal(np.array('1969', dtype='M8[D]').astype('i8'), -1 * 365)
650 assert_equal(np.array('1970', dtype='M8[D]').astype('i8'), 0 * 365)
651 assert_equal(np.array('1971', dtype='M8[D]').astype('i8'), 1 * 365)
652 assert_equal(np.array('1972', dtype='M8[D]').astype('i8'), 2 * 365)
653 assert_equal(np.array('1973', dtype='M8[D]').astype('i8'), 3 * 365 + 1)
654 assert_equal(np.array('1974', dtype='M8[D]').astype('i8'), 4 * 365 + 1)
655 assert_equal(np.array('2000', dtype='M8[D]').astype('i8'),
656 (2000 - 1970) * 365 + (2000 - 1972) // 4)
657 assert_equal(np.array('2001', dtype='M8[D]').astype('i8'),
658 (2000 - 1970) * 365 + (2000 - 1972) // 4 + 366)
659 assert_equal(np.array('2400', dtype='M8[D]').astype('i8'),
660 (2400 - 1970) * 365 + (2400 - 1972) // 4 - 3)
661 assert_equal(np.array('2401', dtype='M8[D]').astype('i8'),
662 (2400 - 1970) * 365 + (2400 - 1972) // 4 - 3 + 366)
663
664 assert_equal(np.array('1600-02-29', dtype='M8[D]').astype('i8'),
665 (1600 - 1970) * 365 - (1972 - 1600) // 4 + 3 + 31 + 28)
666 assert_equal(np.array('1600-03-01', dtype='M8[D]').astype('i8'),
667 (1600 - 1970) * 365 - (1972 - 1600) // 4 + 3 + 31 + 29)
668 assert_equal(np.array('2000-02-29', dtype='M8[D]').astype('i8'),
669 (2000 - 1970) * 365 + (2000 - 1972) // 4 + 31 + 28)
670 assert_equal(np.array('2000-03-01', dtype='M8[D]').astype('i8'),
671 (2000 - 1970) * 365 + (2000 - 1972) // 4 + 31 + 29)
672 assert_equal(np.array('2001-03-22', dtype='M8[D]').astype('i8'),
673 (2000 - 1970) * 365 + (2000 - 1972) // 4 + 366 + 31 + 28 + 21)
674
675 def test_days_to_pydate(self):
676 assert_equal(np.array('1599', dtype='M8[D]').astype('O'),
677 datetime.date(1599, 1, 1))
678 assert_equal(np.array('1600', dtype='M8[D]').astype('O'),
679 datetime.date(1600, 1, 1))
680 assert_equal(np.array('1601', dtype='M8[D]').astype('O'),
681 datetime.date(1601, 1, 1))
682 assert_equal(np.array('1900', dtype='M8[D]').astype('O'),
683 datetime.date(1900, 1, 1))
684 assert_equal(np.array('1901', dtype='M8[D]').astype('O'),
685 datetime.date(1901, 1, 1))
686 assert_equal(np.array('2000', dtype='M8[D]').astype('O'),
687 datetime.date(2000, 1, 1))
688 assert_equal(np.array('2001', dtype='M8[D]').astype('O'),
689 datetime.date(2001, 1, 1))
690 assert_equal(np.array('1600-02-29', dtype='M8[D]').astype('O'),
691 datetime.date(1600, 2, 29))
692 assert_equal(np.array('1600-03-01', dtype='M8[D]').astype('O'),
693 datetime.date(1600, 3, 1))
694 assert_equal(np.array('2001-03-22', dtype='M8[D]').astype('O'),
695 datetime.date(2001, 3, 22))
696
697 def test_dtype_comparison(self):
698 assert_(not (np.dtype('M8[us]') == np.dtype('M8[ms]')))
699 assert_(np.dtype('M8[us]') != np.dtype('M8[ms]'))
700 assert_(np.dtype('M8[2D]') != np.dtype('M8[D]'))
701 assert_(np.dtype('M8[D]') != np.dtype('M8[2D]'))
702
703 def test_pydatetime_creation(self):
704 a = np.array(['1960-03-12', datetime.date(1960, 3, 12)], dtype='M8[D]')
705 assert_equal(a[0], a[1])
706 a = np.array(['1999-12-31', datetime.date(1999, 12, 31)], dtype='M8[D]')
707 assert_equal(a[0], a[1])
708 a = np.array(['2000-01-01', datetime.date(2000, 1, 1)], dtype='M8[D]')
709 assert_equal(a[0], a[1])
710 # Will fail if the date changes during the exact right moment
711 a = np.array(['today', datetime.date.today()], dtype='M8[D]')
712 assert_equal(a[0], a[1])
713 # datetime.datetime.now() returns local time, not UTC
714 #a = np.array(['now', datetime.datetime.now()], dtype='M8[s]')
715 #assert_equal(a[0], a[1])
716
717 # we can give a datetime.date time units
718 assert_equal(np.array(datetime.date(1960, 3, 12), dtype='M8[s]'),
719 np.array(np.datetime64('1960-03-12T00:00:00')))
720
721 def test_datetime_string_conversion(self):
722 a = ['2011-03-16', '1920-01-01', '2013-05-19']
723 str_a = np.array(a, dtype='S')
724 uni_a = np.array(a, dtype='U')
725 dt_a = np.array(a, dtype='M')
726
727 # String to datetime
728 assert_equal(dt_a, str_a.astype('M'))
729 assert_equal(dt_a.dtype, str_a.astype('M').dtype)
730 dt_b = np.empty_like(dt_a)
731 dt_b[...] = str_a
732 assert_equal(dt_a, dt_b)
733
734 # Datetime to string
735 assert_equal(str_a, dt_a.astype('S0'))
736 str_b = np.empty_like(str_a)
737 str_b[...] = dt_a
738 assert_equal(str_a, str_b)
739
740 # Unicode to datetime
741 assert_equal(dt_a, uni_a.astype('M'))
742 assert_equal(dt_a.dtype, uni_a.astype('M').dtype)
743 dt_b = np.empty_like(dt_a)
744 dt_b[...] = uni_a
745 assert_equal(dt_a, dt_b)
746
747 # Datetime to unicode
748 assert_equal(uni_a, dt_a.astype('U'))
749 uni_b = np.empty_like(uni_a)
750 uni_b[...] = dt_a
751 assert_equal(uni_a, uni_b)
752
753 # Datetime to long string - gh-9712
754 assert_equal(str_a, dt_a.astype((np.bytes_, 128)))
755 str_b = np.empty(str_a.shape, dtype=(np.bytes_, 128))
756 str_b[...] = dt_a
757 assert_equal(str_a, str_b)
758
759 @pytest.mark.parametrize("time_dtype", ["m8[D]", "M8[Y]"])
760 def test_time_byteswapping(self, time_dtype):
761 times = np.array(["2017", "NaT"], dtype=time_dtype)
762 times_swapped = times.astype(times.dtype.newbyteorder())
763 assert_array_equal(times, times_swapped)
764
765 unswapped = times_swapped.view(np.dtype("int64").newbyteorder())
766 assert_array_equal(unswapped, times.view(np.int64))
767
768 @pytest.mark.parametrize(["time1", "time2"],
769 [("M8[s]", "M8[D]"), ("m8[s]", "m8[ns]")])
770 def test_time_byteswapped_cast(self, time1, time2):
771 dtype1 = np.dtype(time1)
772 dtype2 = np.dtype(time2)
773 times = np.array(["2017", "NaT"], dtype=dtype1)
774 expected = times.astype(dtype2)
775
776 # Test that every byte-swapping combination also returns the same
777 # results (previous tests check that this comparison works fine).
778 res = times.astype(dtype1.newbyteorder()).astype(dtype2)
779 assert_array_equal(res, expected)
780 res = times.astype(dtype2.newbyteorder())
781 assert_array_equal(res, expected)
782 res = times.astype(dtype1.newbyteorder()).astype(dtype2.newbyteorder())
783 assert_array_equal(res, expected)
784
785 @pytest.mark.parametrize("time_dtype", ["m8[D]", "M8[Y]"])
786 @pytest.mark.parametrize("str_dtype", ["U", "S"])
787 def test_datetime_conversions_byteorders(self, str_dtype, time_dtype):
788 times = np.array(["2017", "NaT"], dtype=time_dtype)
789 # Unfortunately, timedelta does not roundtrip:
790 from_strings = np.array(["2017", "NaT"], dtype=str_dtype)
791 to_strings = times.astype(str_dtype) # assume this is correct
792
793 # Check that conversion from times to string works if src is swapped:
794 times_swapped = times.astype(times.dtype.newbyteorder())
795 res = times_swapped.astype(str_dtype)
796 assert_array_equal(res, to_strings)
797 # And also if both are swapped:
798 res = times_swapped.astype(to_strings.dtype.newbyteorder())
799 assert_array_equal(res, to_strings)
800 # only destination is swapped:
801 res = times.astype(to_strings.dtype.newbyteorder())
802 assert_array_equal(res, to_strings)
803
804 # Check that conversion from string to times works if src is swapped:
805 from_strings_swapped = from_strings.astype(
806 from_strings.dtype.newbyteorder())
807 res = from_strings_swapped.astype(time_dtype)
808 assert_array_equal(res, times)
809 # And if both are swapped:
810 res = from_strings_swapped.astype(times.dtype.newbyteorder())
811 assert_array_equal(res, times)
812 # Only destination is swapped:
813 res = from_strings.astype(times.dtype.newbyteorder())
814 assert_array_equal(res, times)
815
816 def test_datetime_array_str(self):
817 a = np.array(['2011-03-16', '1920-01-01', '2013-05-19'], dtype='M')
818 assert_equal(str(a), "['2011-03-16' '1920-01-01' '2013-05-19']")
819
820 a = np.array(['2011-03-16T13:55', '1920-01-01T03:12'], dtype='M')
821 assert_equal(np.array2string(a, separator=', ',
822 formatter={'datetime': lambda x:
823 f"'{np.datetime_as_string(x, timezone='UTC')}'"}),
824 "['2011-03-16T13:55Z', '1920-01-01T03:12Z']")
825
826 # Check that one NaT doesn't corrupt subsequent entries
827 a = np.array(['2010', 'NaT', '2030']).astype('M')
828 assert_equal(str(a), "['2010' 'NaT' '2030']")
829
830 def test_timedelta_array_str(self):
831 a = np.array([-1, 0, 100], dtype='m')
832 assert_equal(str(a), "[ -1 0 100]")
833 a = np.array(['NaT', 'NaT'], dtype='m')
834 assert_equal(str(a), "['NaT' 'NaT']")
835 # Check right-alignment with NaTs
836 a = np.array([-1, 'NaT', 0], dtype='m')
837 assert_equal(str(a), "[ -1 'NaT' 0]")
838 a = np.array([-1, 'NaT', 1234567], dtype='m')
839 assert_equal(str(a), "[ -1 'NaT' 1234567]")
840
841 # Test with other byteorder:
842 a = np.array([-1, 'NaT', 1234567], dtype='>m')
843 assert_equal(str(a), "[ -1 'NaT' 1234567]")
844 a = np.array([-1, 'NaT', 1234567], dtype='<m')
845 assert_equal(str(a), "[ -1 'NaT' 1234567]")
846
847 def test_timedelta_array_with_nats(self):
848 # Regression test for gh-29497.
849 x = np.array([np.timedelta64('nat'),
850 np.timedelta64('nat', 's'),
851 np.timedelta64('nat', 'ms'),
852 np.timedelta64(123, 'ms')])
853 for td in x[:3]:
854 assert np.isnat(td)
855
856 def test_timedelta_array_nat_assignment(self):
857 # Regression test for gh-29497.
858 x = np.zeros(3, dtype='m8[ms]')
859 x[1] = np.timedelta64('nat', 's')
860 assert np.isnat(x[1])
861
862 def test_pickle(self):
863 # Check that pickle roundtripping works
864 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
865 dt = np.dtype('M8[7D]')
866 assert_equal(pickle.loads(pickle.dumps(dt, protocol=proto)), dt)
867 dt = np.dtype('M8[W]')
868 assert_equal(pickle.loads(pickle.dumps(dt, protocol=proto)), dt)
869 scalar = np.datetime64('2016-01-01T00:00:00.000000000')
870 assert_equal(pickle.loads(pickle.dumps(scalar, protocol=proto)),
871 scalar)
872 delta = scalar - np.datetime64('2015-01-01T00:00:00.000000000')
873 assert_equal(pickle.loads(pickle.dumps(delta, protocol=proto)),
874 delta)
875
876 # Check that loading pickles from 1.6 works
877 with pytest.warns(np.exceptions.VisibleDeprecationWarning,
878 match=r".*align should be passed"):
879 pkl = b"cnumpy\ndtype\np0\n(S'M8'\np1\nI0\nI1\ntp2\nRp3\n"\
880 b"(I4\nS'<'\np4\nNNNI-1\nI-1\nI0\n((dp5\n(S'D'\np6\n"\
881 b"I7\nI1\nI1\ntp7\ntp8\ntp9\nb."
882 assert_equal(pickle.loads(pkl), np.dtype('<M8[7D]'))
883 pkl = b"cnumpy\ndtype\np0\n(S'M8'\np1\nI0\nI1\ntp2\nRp3\n"\
884 b"(I4\nS'<'\np4\nNNNI-1\nI-1\nI0\n((dp5\n(S'W'\np6\n"\
885 b"I1\nI1\nI1\ntp7\ntp8\ntp9\nb."
886 assert_equal(pickle.loads(pkl), np.dtype('<M8[W]'))
887 pkl = b"cnumpy\ndtype\np0\n(S'M8'\np1\nI0\nI1\ntp2\nRp3\n"\
888 b"(I4\nS'>'\np4\nNNNI-1\nI-1\nI0\n((dp5\n(S'us'\np6\n"\
889 b"I1\nI1\nI1\ntp7\ntp8\ntp9\nb."
890 assert_equal(pickle.loads(pkl), np.dtype('>M8[us]'))
891
892 def test_gh_29555(self):
893 # check that dtype metadata round-trips when none
894 dt = np.dtype('>M8[us]')
895 assert dt.metadata is None
896 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
897 res = pickle.loads(pickle.dumps(dt, protocol=proto))
898 assert_equal(res, dt)
899 assert res.metadata is None
900
901 def test_setstate(self):
902 "Verify that datetime dtype __setstate__ can handle bad arguments"
903 dt = np.dtype('>M8[us]')
904 assert_raises(ValueError, dt.__setstate__,
905 (4, '>', None, None, None, -1, -1, 0, 1))
906 assert_(dt.__reduce__()[2] == np.dtype('>M8[us]').__reduce__()[2])
907 assert_raises(TypeError, dt.__setstate__,
908 (4, '>', None, None, None, -1, -1, 0, ({}, 'xxx')))
909 assert_(dt.__reduce__()[2] == np.dtype('>M8[us]').__reduce__()[2])
910
911 def test_dtype_promotion(self):
912 # datetime <op> datetime computes the metadata gcd
913 # timedelta <op> timedelta computes the metadata gcd
914 for mM in ['m', 'M']:
915 assert_equal(
916 np.promote_types(np.dtype(mM + '8[2Y]'), np.dtype(mM + '8[2Y]')),
917 np.dtype(mM + '8[2Y]'))
918 assert_equal(
919 np.promote_types(np.dtype(mM + '8[12Y]'), np.dtype(mM + '8[15Y]')),
920 np.dtype(mM + '8[3Y]'))
921 assert_equal(
922 np.promote_types(np.dtype(mM + '8[62M]'), np.dtype(mM + '8[24M]')),
923 np.dtype(mM + '8[2M]'))
924 assert_equal(
925 np.promote_types(np.dtype(mM + '8[1W]'), np.dtype(mM + '8[2D]')),
926 np.dtype(mM + '8[1D]'))
927 assert_equal(
928 np.promote_types(np.dtype(mM + '8[W]'), np.dtype(mM + '8[13s]')),
929 np.dtype(mM + '8[s]'))
930 assert_equal(
931 np.promote_types(np.dtype(mM + '8[13W]'), np.dtype(mM + '8[49s]')),
932 np.dtype(mM + '8[7s]'))
933 # timedelta <op> timedelta raises when there is no reasonable gcd
934 assert_raises(TypeError, np.promote_types,
935 np.dtype('m8[Y]'), np.dtype('m8[D]'))
936 assert_raises(TypeError, np.promote_types,
937 np.dtype('m8[M]'), np.dtype('m8[W]'))
938 # timedelta and float cannot be safely cast with each other
939 assert_raises(TypeError, np.promote_types, "float32", "m8")
940 assert_raises(TypeError, np.promote_types, "m8", "float32")
941 assert_raises(TypeError, np.promote_types, "uint64", "m8")
942 assert_raises(TypeError, np.promote_types, "m8", "uint64")
943
944 # timedelta <op> timedelta may overflow with big unit ranges
945 assert_raises(OverflowError, np.promote_types,
946 np.dtype('m8[W]'), np.dtype('m8[fs]'))
947 assert_raises(OverflowError, np.promote_types,
948 np.dtype('m8[s]'), np.dtype('m8[as]'))
949
950 def test_cast_overflow(self):
951 # gh-4486
952 def cast():
953 numpy.datetime64("1971-01-01 00:00:00.000000000000000").astype("<M8[D]")
954 assert_raises(OverflowError, cast)
955
956 def cast2():
957 numpy.datetime64("2014").astype("<M8[fs]")
958 assert_raises(OverflowError, cast2)
959
960 def test_pyobject_roundtrip(self):
961 # All datetime types should be able to roundtrip through object
962 a = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0,
963 -1020040340, -2942398, -1, 0, 1, 234523453, 1199164176],
964 dtype=np.int64)
965 # With date units
966 for unit in ['M8[D]', 'M8[W]', 'M8[M]', 'M8[Y]']:
967 b = a.copy().view(dtype=unit)
968 b[0] = '-0001-01-01'
969 b[1] = '-0001-12-31'
970 b[2] = '0000-01-01'
971 b[3] = '0001-01-01'
972 b[4] = '1969-12-31'
973 b[5] = '1970-01-01'
974 b[6] = '9999-12-31'
975 b[7] = '10000-01-01'
976 b[8] = 'NaT'
977
978 assert_equal(b.astype(object).astype(unit), b,
979 f"Error roundtripping unit {unit}")
980 # With time units
981 for unit in ['M8[as]', 'M8[16fs]', 'M8[ps]', 'M8[us]',
982 'M8[300as]', 'M8[20us]']:
983 b = a.copy().view(dtype=unit)
984 b[0] = '-0001-01-01T00'
985 b[1] = '-0001-12-31T00'
986 b[2] = '0000-01-01T00'
987 b[3] = '0001-01-01T00'
988 b[4] = '1969-12-31T23:59:59.999999'
989 b[5] = '1970-01-01T00'
990 b[6] = '9999-12-31T23:59:59.999999'
991 b[7] = '10000-01-01T00'
992 b[8] = 'NaT'
993
994 assert_equal(b.astype(object).astype(unit), b,
995 f"Error roundtripping unit {unit}")
996
997 def test_month_truncation(self):
998 # Make sure that months are truncating correctly
999 assert_equal(np.array('1945-03-01', dtype='M8[M]'),
1000 np.array('1945-03-31', dtype='M8[M]'))
1001 assert_equal(np.array('1969-11-01', dtype='M8[M]'),
1002 np.array('1969-11-30T23:59:59.99999', dtype='M').astype('M8[M]'))
1003 assert_equal(np.array('1969-12-01', dtype='M8[M]'),
1004 np.array('1969-12-31T23:59:59.99999', dtype='M').astype('M8[M]'))
1005 assert_equal(np.array('1970-01-01', dtype='M8[M]'),
1006 np.array('1970-01-31T23:59:59.99999', dtype='M').astype('M8[M]'))
1007 assert_equal(np.array('1980-02-01', dtype='M8[M]'),
1008 np.array('1980-02-29T23:59:59.99999', dtype='M').astype('M8[M]'))
1009
1010 def test_different_unit_comparison(self):
1011 # Check some years with date units
1012 for unit1 in ['Y', 'M', 'D']:
1013 dt1 = np.dtype(f'M8[{unit1}]')
1014 for unit2 in ['Y', 'M', 'D']:
1015 dt2 = np.dtype(f'M8[{unit2}]')
1016 assert_equal(np.array('1945', dtype=dt1),
1017 np.array('1945', dtype=dt2))
1018 assert_equal(np.array('1970', dtype=dt1),
1019 np.array('1970', dtype=dt2))
1020 assert_equal(np.array('9999', dtype=dt1),
1021 np.array('9999', dtype=dt2))
1022 assert_equal(np.array('10000', dtype=dt1),
1023 np.array('10000-01-01', dtype=dt2))
1024 assert_equal(np.datetime64('1945', unit1),
1025 np.datetime64('1945', unit2))
1026 assert_equal(np.datetime64('1970', unit1),
1027 np.datetime64('1970', unit2))
1028 assert_equal(np.datetime64('9999', unit1),
1029 np.datetime64('9999', unit2))
1030 assert_equal(np.datetime64('10000', unit1),
1031 np.datetime64('10000-01-01', unit2))
1032 # Check some datetimes with time units
1033 for unit1 in ['6h', 'h', 'm', 's', '10ms', 'ms', 'us']:
1034 dt1 = np.dtype(f'M8[{unit1}]')
1035 for unit2 in ['h', 'm', 's', 'ms', 'us']:
1036 dt2 = np.dtype(f'M8[{unit2}]')
1037 assert_equal(np.array('1945-03-12T18', dtype=dt1),
1038 np.array('1945-03-12T18', dtype=dt2))
1039 assert_equal(np.array('1970-03-12T18', dtype=dt1),
1040 np.array('1970-03-12T18', dtype=dt2))
1041 assert_equal(np.array('9999-03-12T18', dtype=dt1),
1042 np.array('9999-03-12T18', dtype=dt2))
1043 assert_equal(np.array('10000-01-01T00', dtype=dt1),
1044 np.array('10000-01-01T00', dtype=dt2))
1045 assert_equal(np.datetime64('1945-03-12T18', unit1),
1046 np.datetime64('1945-03-12T18', unit2))
1047 assert_equal(np.datetime64('1970-03-12T18', unit1),
1048 np.datetime64('1970-03-12T18', unit2))
1049 assert_equal(np.datetime64('9999-03-12T18', unit1),
1050 np.datetime64('9999-03-12T18', unit2))
1051 assert_equal(np.datetime64('10000-01-01T00', unit1),
1052 np.datetime64('10000-01-01T00', unit2))
1053 # Check some days with units that won't overflow
1054 for unit1 in ['D', '12h', 'h', 'm', 's', '4s', 'ms', 'us']:
1055 dt1 = np.dtype(f'M8[{unit1}]')
1056 for unit2 in ['D', 'h', 'm', 's', 'ms', 'us']:
1057 dt2 = np.dtype(f'M8[{unit2}]')
1058 assert_(np.equal(np.array('1932-02-17', dtype='M').astype(dt1),
1059 np.array('1932-02-17T00:00:00', dtype='M').astype(dt2),
1060 casting='unsafe'))
1061 assert_(np.equal(np.array('10000-04-27', dtype='M').astype(dt1),
1062 np.array('10000-04-27T00:00:00', dtype='M').astype(dt2),
1063 casting='unsafe'))
1064
1065 # Shouldn't be able to compare datetime and timedelta
1066 a = np.array('2012-12-21', dtype='M8[D]')
1067 b = np.array(3, dtype='m8[D]')
1068 assert_raises(TypeError, np.less, a, b)
1069 # not even if "unsafe"
1070 assert_raises(TypeError, np.less, a, b, casting='unsafe')
1071
1072 def test_datetime_like(self):
1073 a = np.array([3], dtype='m8[4D]')
1074 b = np.array(['2012-12-21'], dtype='M8[D]')
1075
1076 assert_equal(np.ones_like(a).dtype, a.dtype)
1077 assert_equal(np.zeros_like(a).dtype, a.dtype)
1078 assert_equal(np.empty_like(a).dtype, a.dtype)
1079 assert_equal(np.ones_like(b).dtype, b.dtype)
1080 assert_equal(np.zeros_like(b).dtype, b.dtype)
1081 assert_equal(np.empty_like(b).dtype, b.dtype)
1082
1083 def test_datetime_unary(self):
1084 for tda, tdb, tdzero, tdone, tdmone in \
1085 [
1086 # One-dimensional arrays
1087 (np.array([3], dtype='m8[D]'),
1088 np.array([-3], dtype='m8[D]'),
1089 np.array([0], dtype='m8[D]'),
1090 np.array([1], dtype='m8[D]'),
1091 np.array([-1], dtype='m8[D]')),
1092 # NumPy scalars
1093 (np.timedelta64(3, '[D]'),
1094 np.timedelta64(-3, '[D]'),
1095 np.timedelta64(0, '[D]'),
1096 np.timedelta64(1, '[D]'),
1097 np.timedelta64(-1, '[D]'))]:
1098 # negative ufunc
1099 assert_equal(-tdb, tda)
1100 assert_equal((-tdb).dtype, tda.dtype)
1101 assert_equal(np.negative(tdb), tda)
1102 assert_equal(np.negative(tdb).dtype, tda.dtype)
1103
1104 # positive ufunc
1105 assert_equal(np.positive(tda), tda)
1106 assert_equal(np.positive(tda).dtype, tda.dtype)
1107 assert_equal(np.positive(tdb), tdb)
1108 assert_equal(np.positive(tdb).dtype, tdb.dtype)
1109
1110 # absolute ufunc
1111 assert_equal(np.absolute(tdb), tda)
1112 assert_equal(np.absolute(tdb).dtype, tda.dtype)
1113
1114 # sign ufunc
1115 assert_equal(np.sign(tda), tdone)
1116 assert_equal(np.sign(tdb), tdmone)
1117 assert_equal(np.sign(tdzero), tdzero)
1118 assert_equal(np.sign(tda).dtype, tda.dtype)
1119
1120 # The ufuncs always produce native-endian results
1121 assert_
1122
1123 def test_datetime_add(self):
1124 for dta, dtb, dtc, dtnat, tda, tdb, tdc in \
1125 [
1126 # One-dimensional arrays
1127 (np.array(['2012-12-21'], dtype='M8[D]'),
1128 np.array(['2012-12-24'], dtype='M8[D]'),
1129 np.array(['2012-12-21T11'], dtype='M8[h]'),
1130 np.array(['NaT'], dtype='M8[D]'),
1131 np.array([3], dtype='m8[D]'),
1132 np.array([11], dtype='m8[h]'),
1133 np.array([3 * 24 + 11], dtype='m8[h]')),
1134 # NumPy scalars
1135 (np.datetime64('2012-12-21', '[D]'),
1136 np.datetime64('2012-12-24', '[D]'),
1137 np.datetime64('2012-12-21T11', '[h]'),
1138 np.datetime64('NaT', '[D]'),
1139 np.timedelta64(3, '[D]'),
1140 np.timedelta64(11, '[h]'),
1141 np.timedelta64(3 * 24 + 11, '[h]'))]:
1142 # m8 + m8
1143 assert_equal(tda + tdb, tdc)
1144 assert_equal((tda + tdb).dtype, np.dtype('m8[h]'))
1145 # m8 + bool
1146 assert_equal(tdb + True, tdb + 1)
1147 assert_equal((tdb + True).dtype, np.dtype('m8[h]'))
1148 # m8 + int
1149 assert_equal(tdb + 3 * 24, tdc)
1150 assert_equal((tdb + 3 * 24).dtype, np.dtype('m8[h]'))
1151 # bool + m8
1152 assert_equal(False + tdb, tdb)
1153 assert_equal((False + tdb).dtype, np.dtype('m8[h]'))
1154 # int + m8
1155 assert_equal(3 * 24 + tdb, tdc)
1156 assert_equal((3 * 24 + tdb).dtype, np.dtype('m8[h]'))
1157 # M8 + bool
1158 assert_equal(dta + True, dta + 1)
1159 assert_equal(dtnat + True, dtnat)
1160 assert_equal((dta + True).dtype, np.dtype('M8[D]'))
1161 # M8 + int
1162 assert_equal(dta + 3, dtb)
1163 assert_equal(dtnat + 3, dtnat)
1164 assert_equal((dta + 3).dtype, np.dtype('M8[D]'))
1165 # bool + M8
1166 assert_equal(False + dta, dta)
1167 assert_equal(False + dtnat, dtnat)
1168 assert_equal((False + dta).dtype, np.dtype('M8[D]'))
1169 # int + M8
1170 assert_equal(3 + dta, dtb)
1171 assert_equal(3 + dtnat, dtnat)
1172 assert_equal((3 + dta).dtype, np.dtype('M8[D]'))
1173 # M8 + m8
1174 assert_equal(dta + tda, dtb)
1175 assert_equal(dtnat + tda, dtnat)
1176 assert_equal((dta + tda).dtype, np.dtype('M8[D]'))
1177 # m8 + M8
1178 assert_equal(tda + dta, dtb)
1179 assert_equal(tda + dtnat, dtnat)
1180 assert_equal((tda + dta).dtype, np.dtype('M8[D]'))
1181
1182 # In M8 + m8, the result goes to higher precision
1183 assert_equal(np.add(dta, tdb, casting='unsafe'), dtc)
1184 assert_equal(np.add(dta, tdb, casting='unsafe').dtype,
1185 np.dtype('M8[h]'))
1186 assert_equal(np.add(tdb, dta, casting='unsafe'), dtc)
1187 assert_equal(np.add(tdb, dta, casting='unsafe').dtype,
1188 np.dtype('M8[h]'))
1189
1190 # M8 + M8
1191 assert_raises(TypeError, np.add, dta, dtb)
1192
1193 def test_datetime_subtract(self):
1194 for dta, dtb, dtc, dtd, dte, dtnat, tda, tdb, tdc in \
1195 [
1196 # One-dimensional arrays
1197 (np.array(['2012-12-21'], dtype='M8[D]'),
1198 np.array(['2012-12-24'], dtype='M8[D]'),
1199 np.array(['1940-12-24'], dtype='M8[D]'),
1200 np.array(['1940-12-24T00'], dtype='M8[h]'),
