Skip to content

Commit 34adabc

Browse files
author
Christopher Doris
committed
test(numpydates): test more constructors
1 parent 4f78f7e commit 34adabc

File tree

1 file changed

+180
-1
lines changed

1 file changed

+180
-1
lines changed

test/NumpyDates.jl

Lines changed: 180 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@testitem "Date -> DateTime64/InlineDateTime64" begin
1+
@testitem "Date -> DateTime64" begin
22
using Dates
33
using PythonCall: NumpyDates
44

@@ -100,6 +100,185 @@
100100
end
101101
end
102102

103+
@testitem "String -> DateTime64" begin
104+
using Dates
105+
using PythonCall: NumpyDates
106+
107+
# Data generated by: uv run test/scripts/np_dates.py
108+
# Format: (string_date, unit_symbol, numpy_int_value)
109+
cases = [
110+
("1969-12-31", :Y, -1),
111+
("1969-12-31", :M, -1),
112+
("1969-12-31", :D, -1),
113+
("1969-12-31", :h, -24),
114+
("1969-12-31", :m, -1440),
115+
("1969-12-31", :s, -86400),
116+
("1969-12-31", :ms, -86400000),
117+
("1969-12-31", :us, -86400000000),
118+
("1969-12-31", :ns, -86400000000000),
119+
("1970-01-01", :Y, 0),
120+
("1970-01-01", :M, 0),
121+
("1970-01-01", :D, 0),
122+
("1970-01-01", :h, 0),
123+
("1970-01-01", :m, 0),
124+
("1970-01-01", :s, 0),
125+
("1970-01-01", :ms, 0),
126+
("1970-01-01", :us, 0),
127+
("1970-01-01", :ns, 0),
128+
("1970-01-02", :Y, 0),
129+
("1970-01-02", :M, 0),
130+
("1970-01-02", :D, 1),
131+
("1970-01-02", :h, 24),
132+
("1970-01-02", :m, 1440),
133+
("1970-01-02", :s, 86400),
134+
("1970-01-02", :ms, 86400000),
135+
("1970-01-02", :us, 86400000000),
136+
("1970-01-02", :ns, 86400000000000),
137+
("1999-12-31", :Y, 29),
138+
("1999-12-31", :M, 359),
139+
("1999-12-31", :D, 10956),
140+
("1999-12-31", :h, 262944),
141+
("1999-12-31", :m, 15776640),
142+
("1999-12-31", :s, 946598400),
143+
("1999-12-31", :ms, 946598400000),
144+
("1999-12-31", :us, 946598400000000),
145+
("1999-12-31", :ns, 946598400000000000),
146+
("2000-02-29", :Y, 30),
147+
("2000-02-29", :M, 361),
148+
("2000-02-29", :D, 11016),
149+
("2000-02-29", :h, 264384),
150+
("2000-02-29", :m, 15863040),
151+
("2000-02-29", :s, 951782400),
152+
("2000-02-29", :ms, 951782400000),
153+
("2000-02-29", :us, 951782400000000),
154+
("2000-02-29", :ns, 951782400000000000),
155+
("1900-01-01", :Y, -70),
156+
("1900-01-01", :M, -840),
157+
("1900-01-01", :D, -25567),
158+
("1900-01-01", :h, -613608),
159+
("1900-01-01", :m, -36816480),
160+
("1900-01-01", :s, -2208988800),
161+
("1900-01-01", :ms, -2208988800000),
162+
("1900-01-01", :us, -2208988800000000),
163+
("1900-01-01", :ns, -2208988800000000000),
164+
("2100-01-01", :Y, 130),
165+
("2100-01-01", :M, 1560),
166+
("2100-01-01", :D, 47482),
167+
("2100-01-01", :h, 1139568),
168+
("2100-01-01", :m, 68374080),
169+
("2100-01-01", :s, 4102444800),
170+
("2100-01-01", :ms, 4102444800000),
171+
("2100-01-01", :us, 4102444800000000),
172+
("2100-01-01", :ns, 4102444800000000000),
173+
]
174+
175+
@testset "$s $usym" for (s, usym, expected) in cases
176+
# DateTime64 from string
177+
dt64 = NumpyDates.DateTime64(s, usym)
178+
@test Dates.value(dt64) == expected
179+
180+
# Inline typed from string
181+
Uconst = NumpyDates.Unit(usym)
182+
inline_typed = NumpyDates.InlineDateTime64{Uconst}(s)
183+
@test Dates.value(inline_typed) == expected
184+
185+
# Inline dynamic from string
186+
inline_dyn = NumpyDates.InlineDateTime64(s, usym)
187+
@test Dates.value(inline_dyn) == expected
188+
@test NumpyDates.unitpair(inline_dyn) == NumpyDates.unitpair(usym)
189+
end
190+
191+
# NaT string handling (all should produce NaT)
192+
@testset "$nat" for nat in ("NaT", "nan", "NAN")
193+
d1 = NumpyDates.DateTime64(nat, :D)
194+
@test isnan(d1)
195+
d2 = NumpyDates.InlineDateTime64{NumpyDates.DAYS}(nat)
196+
@test isnan(d2)
197+
d3 = NumpyDates.InlineDateTime64(nat, :D)
198+
@test isnan(d3)
199+
end
200+
end
201+
202+
@testitem "String and DateFormat -> DateTime64" begin
203+
using Dates
204+
using PythonCall: NumpyDates
205+
206+
# Data based on: uv run test/scripts/np_dates.py and uv run test/scripts/np_datetimes.py
207+
# We deliberately use formats that differ from the default parser to exercise the (str, format, unit) constructors.
208+
cases = [
209+
# date-only with custom format
210+
("1999/12/31", DateFormat("yyyy/mm/dd"), :D, 10956),
211+
("1999/12/31", DateFormat("yyyy/mm/dd"), :s, 946598400),
212+
# datetime with custom format
213+
("2000-02-29 12:34:56", DateFormat("yyyy-mm-dd HH:MM:SS"), :s, 951_827_696),
214+
(
215+
"2000-02-29 12:34:56",
216+
DateFormat("yyyy-mm-dd HH:MM:SS"),
217+
:ns,
218+
951_827_696_000_000_000,
219+
),
220+
]
221+
222+
@testset "$s $f $usym" for (s, f, usym, expected) in cases
223+
# DateTime64 from string + format
224+
dt64 = NumpyDates.DateTime64(s, f, usym)
225+
@test Dates.value(dt64) == expected
226+
227+
# Inline typed from string + format
228+
Uconst = NumpyDates.Unit(usym)
229+
inline_typed = NumpyDates.InlineDateTime64{Uconst}(s, f)
230+
@test Dates.value(inline_typed) == expected
231+
232+
# NOTE: InlineDateTime64(s, f, u) dynamic constructor is not exercised here
233+
# because it currently dispatches to InlineTimeDelta64 in the implementation.
234+
# When fixed, we can add:
235+
# inline_dyn = NumpyDates.InlineDateTime64(s, f, usym)
236+
# @test Dates.value(inline_dyn) == expected
237+
end
238+
end
239+
240+
@testitem "AbstractDateTime64 -> DateTime64" begin
241+
using Dates
242+
using PythonCall: NumpyDates
243+
244+
# Pass-through when units match
245+
d = Date(1970, 1, 2)
246+
x = NumpyDates.DateTime64(d, :D) # expected value 1
247+
y = NumpyDates.DateTime64(x, :D)
248+
@test Dates.value(y) == 1
249+
@test NumpyDates.unitpair(y) == NumpyDates.unitpair(:D)
250+
251+
# NaT changes unit and remains NaT
252+
nat_d = NumpyDates.DateTime64("NaT", :D)
253+
z = NumpyDates.DateTime64(nat_d, :s)
254+
@test isnan(z)
255+
@test NumpyDates.unitpair(z) == NumpyDates.unitpair(:s)
256+
end
257+
258+
@testitem "Integer -> DateTime64" begin
259+
using Dates
260+
using PythonCall: NumpyDates
261+
262+
# DateTime64(value, unit)
263+
x = NumpyDates.DateTime64(946_684_799, :s) # 1999-12-31T23:59:59
264+
@test Dates.value(x) == 946_684_799
265+
@test Dates.DateTime(x) == DateTime(1999, 12, 31, 23, 59, 59)
266+
267+
y = NumpyDates.DateTime64(10_956, :D) # 1999-12-31
268+
@test Dates.value(y) == 10_956
269+
@test Dates.Date(y) == Date(1999, 12, 31)
270+
271+
# InlineDateTime64{U}(value)
272+
s1 = NumpyDates.InlineDateTime64{NumpyDates.SECONDS}(3_600) # +1 hour
273+
@test Dates.value(s1) == 3_600
274+
@test Dates.DateTime(s1) == DateTime(1970, 1, 1, 1, 0, 0)
275+
276+
# InlineDateTime64 with multiplier in the unit parameter
277+
s2 = NumpyDates.InlineDateTime64{(NumpyDates.SECONDS, 2)}(1_800) # 1_800 * 2s = 3_600s
278+
@test Dates.value(s2) == 1_800
279+
@test Dates.DateTime(s2) == DateTime(1970, 1, 1, 1, 0, 0)
280+
end
281+
103282
@testitem "DateTime -> DateTime64/InlineDateTime64" begin
104283
using Dates
105284
using PythonCall: NumpyDates

0 commit comments

Comments
 (0)