@@ -27,6 +27,70 @@ const NUMPY_SIMPLE_TYPES = [
2727 (" complex128" , ComplexF64),
2828]
2929
30+ function pydatetime64 (
31+ _year:: Int = 0 , _month:: Int = 1 , _day:: Int = 1 , _hour:: Int = 0 , _minute:: Int = 0 ,_second:: Int = 0 , _millisecond:: Int = 0 , _microsecond:: Int = 0 , _nanosecond:: Int = 0 ;
32+ year:: Int = _year, month:: Int = _month, day:: Int = _day, hour:: Int = _hour, minute:: Int = _minute, second:: Int = _second,
33+ millisecond:: Int = _millisecond, microsecond:: Int = _microsecond, nanosecond:: Int = _nanosecond
34+ )
35+ pyimport (" numpy" ). datetime64 (" $(DateTime (year, month, day, hour, minute, second)) " ) + pytimedelta64 (;millisecond, microsecond, nanosecond)
36+ end
37+ function pydatetime64 (@nospecialize (x:: T )) where T <: Period
38+ T <: Union{Week, Day, Hour, Minute, Second, Millisecond, Microsecond} ||
39+ error (" Unsupported Period type: " , " Year, Month and Nanosecond are not supported, consider using pytimedelta64 instead." )
40+ args = T .== (Day, Second, Millisecond, Microsecond, Minute, Hour, Week)
41+ pydatetime64 (x. value .* args... )
42+ end
43+ function pydatetime64 (x:: CompoundPeriod )
44+ x = canonicalize (x)
45+ isempty (x. periods) ? pydatetime64 (Second (0 )) : sum (pydatetime64 .(x. periods))
46+ end
47+ export pydatetime64
48+
49+ function pytimedelta64 (
50+ _year:: Int = 0 , _month:: Int = 0 , _day:: Int = 0 , _hour:: Int = 0 , _minute:: Int = 0 , _second:: Int = 0 , _millisecond:: Int = 0 , _microsecond:: Int = 0 , _nanosecond:: Int = 0 , _week:: Int = 0 ;
51+ year:: Int = _year, month:: Int = _month, day:: Int = _day, hour:: Int = _hour, minute:: Int = _minute, second:: Int = _second, microsecond:: Int = _microsecond, millisecond:: Int = _millisecond, nanosecond:: Int = _nanosecond, week:: Int = _week)
52+ pytimedelta64 (sum ((
53+ Year (year), Month (month), # you cannot mix year or month with any of the below units in python, the error will be thrown by `pytimedelta64(::CompoundPeriod)`
54+ Day (day), Hour (hour), Minute (minute), Second (second), Millisecond (millisecond), Microsecond (microsecond), Nanosecond (nanosecond))
55+ ))
56+ end
57+ function pytimedelta64 (@nospecialize (x:: T )) where T <: Period
58+ index = findfirst (== (T), (Year, Month, Week, Day, Hour, Minute, Second, Millisecond, Microsecond, Nanosecond, T))
59+ unit = (" Y" , " M" , " W" , " D" , " h" , " m" , " s" , " ms" , " us" , " ns" , " " )[index]
60+ pyimport (" numpy" ). timedelta64 (x. value, unit)
61+ end
62+ function pytimedelta64 (x:: CompoundPeriod )
63+ x = canonicalize (x)
64+ isempty (x. periods) ? pytimedelta64 (Second (0 )) : sum (pytimedelta64 .(x. periods))
65+ end
66+ export pytimedelta64
67+
68+ function pyconvert_rule_datetime64 (:: Type{DateTime} , x:: Py )
69+ unit, value = pyconvert (Tuple, pyimport (" numpy" ). datetime_data (x))
70+ # strangely, datetime_data does not return the value correctly
71+ # so we retrieve the value from the byte representation
72+ value = reinterpret (Int64, pyconvert (Vector, x))[1 ]
73+ units = (" Y" , " M" , " W" , " D" , " h" , " m" , " s" , " ms" , " us" , " ns" )
74+ types = (Year, Month, Week, Day, Hour, Minute, Second, Millisecond, Microsecond, Nanosecond)
75+ T = types[findfirst (== (unit), units)]
76+ pyconvert_return (DateTime (_base_datetime) + T (value))
77+ end
78+
79+ function pyconvert_rule_timedelta64 (:: Type{CompoundPeriod} , x:: Py )
80+ unit, value = pyconvert (Tuple, pyimport (" numpy" ). datetime_data (x))
81+ # strangely, datetime_data does not return the value correctly
82+ # so we retrieve the value from the byte representation
83+ value = reinterpret (Int64, pyconvert (Vector, x))[1 ]
84+ units = (" Y" , " M" , " W" , " D" , " h" , " m" , " s" , " ms" , " us" , " ns" )
85+ types = (Year, Month, Week, Day, Hour, Minute, Second, Millisecond, Microsecond, Nanosecond)
86+ T = types[findfirst (== (unit), units)]
87+ pyconvert_return (CompoundPeriod (T (value)) |> canonicalize)
88+ end
89+
90+ function pyconvert_rule_timedelta64 (:: Type{T} , x:: Py ) where T<: Period
91+ pyconvert_return (convert (T, pyconvert_rule_timedelta64 (CompoundPeriod, x)))
92+ end
93+
3094function init_numpy ()
3195 for (t, T) in NUMPY_SIMPLE_TYPES
3296 isbool = occursin (" bool" , t)
@@ -52,4 +116,14 @@ function init_numpy()
52116 iscomplex && pyconvert_add_rule (name, Complex, rule)
53117 isnumber && pyconvert_add_rule (name, Number, rule)
54118 end
119+
120+ priority = PYCONVERT_PRIORITY_ARRAY
121+ pyconvert_add_rule (" numpy:datetime64" , DateTime, pyconvert_rule_datetime64, priority)
122+ for T in (CompoundPeriod, Year, Month, Day, Hour, Minute, Second, Millisecond, Microsecond, Nanosecond, Week)
123+ pyconvert_add_rule (" numpy:timedelta64" , T, pyconvert_rule_timedelta64, priority)
124+ end
125+
126+ priority = PYCONVERT_PRIORITY_CANONICAL
127+ pyconvert_add_rule (" numpy:datetime64" , DateTime, pyconvert_rule_datetime64, priority)
128+ pyconvert_add_rule (" numpy:timedelta64" , Nanosecond, pyconvert_rule_timedelta, priority)
55129end
0 commit comments