Skip to content

Commit 3c51b54

Browse files
author
hhaensel
committed
support unitless timedelta64, keep unit per default, add keyword canonicalize, add global setting CANONICALIZE_TIMEDELTA64 for rule conversion
1 parent 66459c6 commit 3c51b54

File tree

1 file changed

+40
-15
lines changed

1 file changed

+40
-15
lines changed

src/Convert/numpy.jl

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const CANONICALIZE_TIMEDELTA64 = Ref(false)
2+
13
struct pyconvert_rule_numpysimplevalue{R,S} <: Function end
24

35
function (::pyconvert_rule_numpysimplevalue{R,SAFE})(::Type{T}, x::Py) where {R,SAFE,T}
@@ -47,33 +49,54 @@ end
4749
export pydatetime64
4850

4951
function pytimedelta64(
50-
_years::Union{Nothing,Integer}=nothing, _months::Union{Nothing,Integer}=nothing, _days::Integer=0, _hours::Integer=0, _minutes::Integer=0, _seconds::Integer=0, _milliseconds::Integer=0, _microseconds::Integer=0, _nanoseconds::Integer=0, _weeks::Integer=0;
51-
years::Union{Nothing,Integer}=_years, months::Union{Nothing,Integer}=_years, days::Integer=_days, hours::Integer=_hours, minutes::Integer=_minutes, seconds::Integer=_seconds, microseconds::Integer=_microseconds, milliseconds::Integer=_milliseconds, nanoseconds::Integer=_nanoseconds, weeks::Integer=_weeks)
52-
year_or_month_given = (years !== nothing || months !== nothing)
52+
_years::Union{Nothing,Integer}=nothing, _months::Union{Nothing,Integer}=nothing,
53+
_days::Union{Nothing,Integer}=nothing, _hours::Union{Nothing,Integer}=nothing,
54+
_minutes::Union{Nothing,Integer}=nothing, _seconds::Union{Nothing,Integer}=nothing,
55+
_milliseconds::Union{Nothing,Integer}=nothing, _microseconds::Union{Nothing,Integer}=nothing,
56+
_nanoseconds::Union{Nothing,Integer}=nothing, _weeks::Union{Nothing,Integer}=nothing;
57+
years::Union{Nothing,Integer}=_years, months::Union{Nothing,Integer}=_months,
58+
days::Union{Nothing,Integer}=_days, hours::Union{Nothing,Integer}=_hours,
59+
minutes::Union{Nothing,Integer}=_minutes, seconds::Union{Nothing,Integer}=_seconds,
60+
milliseconds::Union{Nothing,Integer}=_milliseconds, microseconds::Union{Nothing,Integer}=_microseconds,
61+
nanoseconds::Union{Nothing,Integer}=_nanoseconds, weeks::Union{Nothing,Integer}=_weeks,
62+
canonicalize::Bool = false)
63+
5364
y::Integer = something(years, 0)
5465
m::Integer = something(months, 0)
66+
d::Integer = something(days, 0)
67+
h::Integer = something(hours, 0)
68+
min::Integer = something(minutes, 0)
69+
s::Integer = something(seconds, 0)
70+
ms::Integer = something(milliseconds, 0)
71+
µs::Integer = something(microseconds, 0)
72+
ns::Integer = something(nanoseconds, 0)
73+
w::Integer = something(weeks, 0)
5574
cp = sum((
56-
Year(y), Month(m),
57-
# you cannot mix year or month with any of the below units in python
58-
# in case of wrong usage a descriptive error message will by thrown by the underlying python function
59-
Day(days), Hour(hours), Minute(minutes), Second(seconds), Millisecond(milliseconds), Microsecond(microseconds), Nanosecond(nanoseconds), Week(weeks))
75+
Year(y), Month(m), Week(w), Day(d), Hour(h), Minute(min), Second(s), Millisecond(ms), Microsecond(µs), Nanosecond(ns))
6076
)
6177
# make sure the correct unit is used when value is 0
62-
if isempty(cp.periods) && year_or_month_given
63-
pytimedelta64(Month(0))
78+
if isempty(cp.periods)
79+
Units = (Second, Year, Month, Week, Day, Hour, Minute, Second, Millisecond, Microsecond, Nanosecond)
80+
index::Integer = findlast(!isnothing, (0, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds));
81+
pytimedelta64(Units[index](0))
6482
else
65-
pytimedelta64(cp)
83+
pytimedelta64(cp; canonicalize)
6684
end
6785
end
68-
function pytimedelta64(@nospecialize(x::T)) where T <: Period
69-
index = findfirst(==(T), (Year, Month, Week, Day, Hour, Minute, Second, Millisecond, Microsecond, Nanosecond, T))::Int
86+
function pytimedelta64(@nospecialize(x::T); canonicalize::Bool = false) where T <: Period
87+
canonicalize && return pytimedelta64(@__MODULE__().canonicalize(x))
88+
89+
index = findfirst(T .== (Year, Month, Week, Day, Hour, Minute, Second, Millisecond, Microsecond, Nanosecond, T))::Int
7090
unit = ("Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "")[index]
7191
pyimport("numpy").timedelta64(x.value, unit)
7292
end
73-
function pytimedelta64(x::CompoundPeriod)
74-
x = canonicalize(x)
93+
function pytimedelta64(x::CompoundPeriod; canonicalize::Bool = false)
94+
canonicalize && (x = @__MODULE__().canonicalize(x))
7595
isempty(x.periods) ? pytimedelta64(Second(0)) : sum(pytimedelta64.(x.periods))
7696
end
97+
function pytimedelta64(x::Integer)
98+
pyimport("numpy").timedelta64(x)
99+
end
77100
export pytimedelta64
78101

79102
function pyconvert_rule_datetime64(::Type{DateTime}, x::Py)
@@ -91,7 +114,9 @@ function pyconvert_rule_timedelta64(::Type{CompoundPeriod}, x::Py)
91114
units = ("Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns")
92115
types = (Year, Month, Week, Day, Hour, Minute, Second, Millisecond, Microsecond, Nanosecond)
93116
T = types[findfirst(==(unit), units)::Int]
94-
pyconvert_return(CompoundPeriod(T(value * count)) |> canonicalize)
117+
cp = CompoundPeriod(T(value * count))
118+
CANONICALIZE_TIMEDELTA64[] && (cp = @__MODULE__().canonicalize(cp))
119+
pyconvert_return(cp)
95120
end
96121

97122
function pyconvert_rule_timedelta64(::Type{T}, x::Py) where T<:Period

0 commit comments

Comments
 (0)