Skip to content

Commit b88128b

Browse files
Define CompoundPeriod conversion for Real
1 parent 0c49003 commit b88128b

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ Standard library changes
180180
#### Dates
181181
182182
The undocumented function `adjust` is no longer exported but is now documented
183+
* `CompoundPeriod(x::Real, ::Type{T}) where {T}` now supports conversions from `T <: Nanoseconds` to `T <: Weeks`.
183184
184185
#### Statistics
185186

stdlib/Dates/src/periods.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ periods(x::CompoundPeriod) = x.periods
175175

176176
"""
177177
CompoundPeriod(periods) -> CompoundPeriod
178+
CompoundPeriod(::Real, ::Type{Period}) -> CompoundPeriod
178179
179180
Construct a `CompoundPeriod` from a `Vector` of `Period`s. All `Period`s of the same type
180181
will be added together.
@@ -192,6 +193,9 @@ julia> Dates.CompoundPeriod(Dates.Month(1), Dates.Week(-2))
192193
193194
julia> Dates.CompoundPeriod(Dates.Minute(50000))
194195
50000 minutes
196+
197+
julia> Dates.canonicalize(Dates.CompoundPeriod(1.5, Dates.Day))
198+
1 day, 12 hours
195199
```
196200
"""
197201
CompoundPeriod(p::Vector{<:Period}) = CompoundPeriod(Vector{Period}(p))
@@ -201,6 +205,26 @@ CompoundPeriod(t::Time) = CompoundPeriod(Period[Hour(t), Minute(t), Second(t), M
201205

202206
CompoundPeriod(p::Period...) = CompoundPeriod(Period[p...])
203207

208+
time_per_time(::Type{P}, ::Type{P}) where {P} = 1
209+
function define_time_per_times(periods)
210+
for i = eachindex(periods)
211+
T, n = periods[i]
212+
N = Int64(1)
213+
for j = (i - 1):-1:firstindex(periods) # less-precise periods
214+
Tc, nc = periods[j]
215+
N *= nc
216+
@eval time_per_time(::Type{$T}, ::Type{$Tc}) = $N
217+
end
218+
end
219+
end
220+
221+
define_time_per_times([(:Week, 7), (:Day, 24), (:Hour, 60), (:Minute, 60), (:Second, 1000),
222+
(:Millisecond, 1000), (:Microsecond, 1000), (:Nanosecond, 1)])
223+
224+
function CompoundPeriod(x::Real, ::Type{T}) where {T <: Period}
225+
nf = time_per_time(Nanosecond, T)
226+
return CompoundPeriod(Nanosecond(ceil(x * nf)))
227+
end
204228

205229
"""
206230
canonicalize(::CompoundPeriod) -> CompoundPeriod

stdlib/Dates/test/periods.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,23 @@ end
397397
@test_throws MethodError (Dates.Month(1) + Dates.Day(1)) - Dates.Date(2009,2,1)
398398
end
399399

400+
@testset "compound period from Real" begin
401+
ccp(x, p) = Dates.canonicalize(Dates.CompoundPeriod(x, p))
402+
@test string(ccp(1.5, Dates.Minute)) == "1 minute, 30 seconds"
403+
@test string(ccp((Dates.Second(Dates.Week(1))+Dates.Second(1)).value, Dates.Second)) == "1 week, 1 second"
404+
@test string(ccp(1.5, Dates.Day)) == "1 day, 12 hours"
405+
@test string(ccp(1.5+7, Dates.Day)) == "1 week, 1 day, 12 hours"
406+
@test string(ccp(1.4, Dates.Second)) == "1 second, 400 milliseconds"
407+
@test string(ccp(10.1, Dates.Week)) == "10 weeks, 16 hours, 48 minutes"
408+
@test string(ccp(10.1, Dates.Week) - Dates.Minute(6)) == "10 weeks, 16 hours, 42 minutes"
409+
@test ccp(1000000, Dates.Nanosecond) == Dates.canonicalize(Dates.Millisecond(1))
410+
@test ccp(1000, Dates.Millisecond) == Dates.canonicalize(Dates.Second(1))
411+
@test ccp(60, Dates.Second) == Dates.canonicalize(Dates.Minute(1))
412+
@test ccp(60, Dates.Minute) == Dates.canonicalize(Dates.Hour(1))
413+
@test ccp(24, Dates.Hour) == Dates.canonicalize(Dates.Day(1))
414+
@test ccp(7, Dates.Day) == Dates.canonicalize(Dates.Week(1))
415+
end
416+
400417
@testset "canonicalize Period" begin
401418
# reduce individual Period into most basic CompoundPeriod
402419
@test Dates.canonicalize(Dates.Nanosecond(1000000)) == Dates.canonicalize(Dates.Millisecond(1))

0 commit comments

Comments
 (0)