Skip to content

Commit 4f3195a

Browse files
author
Christopher Doris
committed
refactor(numpydates): add rescale support and expand convert methods for datetime64 and timedelta64
- Implement rescale function to handle unit changes in DateTime64 and TimeDelta64 instead of throwing errors - Expand Base.convert methods for InlineDateTime64 and InlineTimeDelta64 to support more types - Add new pyconvert rules for NumpyDates.DatesInstant and NumpyDates.DatesPeriod in numpy.jl This enhances type conversions and removes previous limitations on unit scaling.
1 parent ba2ee61 commit 4f3195a

File tree

5 files changed

+50
-19
lines changed

5 files changed

+50
-19
lines changed

src/Convert/numpy.jl

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ function pyconvert_rule_datetime64(::Type{DateTime64}, x::Py)
1414
end
1515

1616
function pyconvert_rule_datetime64(::Type{T}, x::Py) where {T<:InlineDateTime64}
17-
pyconvert_return(T(C.PySimpleObject_GetValue(DateTime64, x)))
17+
pyconvert_tryconvert(T, C.PySimpleObject_GetValue(DateTime64, x))
1818
end
1919

20-
function pyconvert_rule_datetime64(::Type{DateTime}, x::Py)
20+
function pyconvert_rule_datetime64(::Type{T}, x::Py) where {T<:NumpyDates.DatesInstant}
2121
d = C.PySimpleObject_GetValue(DateTime64, x)
2222
if isnan(d)
2323
pyconvert_unconverted()
2424
else
25-
pyconvert_tryconvert(DateTime, d)
25+
pyconvert_tryconvert(T, d)
2626
end
2727
end
2828

@@ -48,8 +48,17 @@ function pyconvert_rule_timedelta64(::Type{TimeDelta64}, x::Py)
4848
pyconvert_return(C.PySimpleObject_GetValue(TimeDelta64, x))
4949
end
5050

51-
function pyconvert_rule_datetime64(::Type{T}, x::Py) where {T<:InlineTimeDelta64}
52-
pyconvert_return(T(C.PySimpleObject_GetValue(TimeDelta64, x)))
51+
function pyconvert_rule_timedelta64(::Type{T}, x::Py) where {T<:InlineTimeDelta64}
52+
pyconvert_tryconvert(T, C.PySimpleObject_GetValue(TimeDelta64, x))
53+
end
54+
55+
function pyconvert_rule_timedelta64(::Type{T}, x::Py) where {T<:NumpyDates.DatesPeriod}
56+
d = C.PySimpleObject_GetValue(TimeDelta64, x)
57+
if isnan(d)
58+
pyconvert_unconverted()
59+
else
60+
pyconvert_tryconvert(T, d)
61+
end
5362
end
5463

5564
function pyconvert_rule_timedelta64(::Type{Missing}, x::Py)
@@ -125,7 +134,11 @@ function init_numpy()
125134
PYCONVERT_PRIORITY_ARRAY,
126135
)
127136
pyconvert_add_rule("numpy:datetime64", InlineDateTime64, pyconvert_rule_datetime64)
128-
pyconvert_add_rule("numpy:datetime64", DateTime, pyconvert_rule_datetime64)
137+
pyconvert_add_rule(
138+
"numpy:datetime64",
139+
NumpyDates.DatesInstant,
140+
pyconvert_rule_datetime64,
141+
)
129142
pyconvert_add_rule("numpy:datetime64", Missing, pyconvert_rule_datetime64)
130143
pyconvert_add_rule("numpy:datetime64", Nothing, pyconvert_rule_datetime64)
131144

@@ -137,6 +150,11 @@ function init_numpy()
137150
PYCONVERT_PRIORITY_ARRAY,
138151
)
139152
pyconvert_add_rule("numpy:timedelta64", InlineTimeDelta64, pyconvert_rule_timedelta64)
153+
pyconvert_add_rule(
154+
"numpy:timedelta64",
155+
NumpyDates.DatesPeriod,
156+
pyconvert_rule_timedelta64,
157+
)
140158
pyconvert_add_rule("numpy:timedelta64", Missing, pyconvert_rule_timedelta64)
141159
pyconvert_add_rule("numpy:timedelta64", Nothing, pyconvert_rule_timedelta64)
142160
end

src/NumpyDates/DateTime64.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,8 @@ function DateTime64(d::AbstractDateTime64, unit::UnitArg = defaultunit(d))
4545
elseif isnan(d)
4646
DateTime64(NAT, unit)
4747
else
48-
error(
49-
"not implemented: changing units: $(unitparam(unitpair(d))) to $(unitparam(unit))",
50-
)
48+
v, _ = rescale(value(d), unitpair(d), unit)
49+
DateTime64(v, unit)
5150
end
5251
end
5352

@@ -92,6 +91,8 @@ end
9291

9392
# convert
9493

94+
Base.convert(::Type{DateTime64}, x::DateTime64) = x
95+
Base.convert(::Type{DateTime64}, x::AbstractDateTime64) = DateTime64(x)
9596
Base.convert(::Type{DateTime64}, x::DatesInstant) = DateTime64(x)
9697

9798
# show

src/NumpyDates/InlineDateTime64.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,14 @@ end
9696

9797
# convert
9898

99-
Base.convert(::Type{InlineDateTime64}, x::DatesInstant) = InlineDateTime64(x)
100-
Base.convert(::Type{InlineDateTime64{U}}, x::DatesInstant) where {U} =
101-
InlineDateTime64{U}(x)
99+
Base.convert(::Type{InlineDateTime64}, x::InlineDateTime64) = x
100+
Base.convert(::Type{InlineDateTime64}, x::Union{AbstractDateTime64,DatesInstant}) =
101+
InlineDateTime64(x)
102+
Base.convert(::Type{InlineDateTime64{U}}, x::InlineDateTime64{U}) where {U} = x
103+
Base.convert(
104+
::Type{InlineDateTime64{U}},
105+
x::Union{AbstractDateTime64,DatesInstant},
106+
) where {U} = InlineDateTime64{U}(x)
102107

103108
# show
104109

src/NumpyDates/InlineTimeDelta64.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,14 @@ end
6868

6969
# convert
7070

71-
Base.convert(::Type{InlineTimeDelta64}, p::DatesPeriod) = InlineTimeDelta64(p)
72-
Base.convert(::Type{InlineTimeDelta64{U}}, p::DatesPeriod) where {U} =
73-
InlineTimeDelta64{U}(p)
71+
Base.convert(::Type{InlineTimeDelta64}, p::InlineTimeDelta64) = p
72+
Base.convert(::Type{InlineTimeDelta64}, p::Union{AbstractTimeDelta64,DatesPeriod}) =
73+
InlineTimeDelta64(p)
74+
Base.convert(::Type{InlineTimeDelta64{U}}, p::InlineTimeDelta64{U}) where {U} = p
75+
Base.convert(
76+
::Type{InlineTimeDelta64{U}},
77+
p::Union{AbstractTimeDelta64,DatesPeriod},
78+
) where {U} = InlineTimeDelta64{U}(p)
7479

7580
# show
7681

src/NumpyDates/TimeDelta64.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ function TimeDelta64(d::AbstractTimeDelta64, unit::UnitArg = defaultunit(d))
4242
elseif isnan(d)
4343
TimeDelta64(NAT, unit)
4444
else
45-
error(
46-
"not implemented: changing units: $(unitparam(unitpair(d))) to $(unitparam(unit))",
47-
)
45+
v, r = rescale(value(d), unitpair(d), unit)
46+
iszero(r) || throw(InexactError(:TimeDelta64, TimeDelta64, d, unit))
47+
TimeDelta64(v, unit)
4848
end
4949
end
5050

@@ -67,7 +67,9 @@ end
6767

6868
# convert
6969

70-
Base.convert(::Type{TimeDelta64}, p::DatesPeriod) = TimeDelta64(p)
70+
Base.convert(::Type{TimeDelta64}, p::TimeDelta64) = p
71+
Base.convert(::Type{TimeDelta64}, p::Union{AbstractTimeDelta64,DatesPeriod}) =
72+
TimeDelta64(p)
7173

7274
# show
7375

0 commit comments

Comments
 (0)