@@ -27,6 +27,70 @@ const NUMPY_SIMPLE_TYPES = [
27
27
(" complex128" , ComplexF64),
28
28
]
29
29
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
+
30
94
function init_numpy ()
31
95
for (t, T) in NUMPY_SIMPLE_TYPES
32
96
isbool = occursin (" bool" , t)
@@ -52,4 +116,14 @@ function init_numpy()
52
116
iscomplex && pyconvert_add_rule (name, Complex, rule)
53
117
isnumber && pyconvert_add_rule (name, Number, rule)
54
118
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)
55
129
end
0 commit comments