diff --git a/NEWS.md b/NEWS.md index 6db22fa1f8be7..4a0ab4c066689 100644 --- a/NEWS.md +++ b/NEWS.md @@ -180,6 +180,7 @@ Standard library changes #### Dates The undocumented function `adjust` is no longer exported but is now documented +* `CompoundPeriod(x::Real, ::Type{T}) where {T}` now supports conversions from `T <: Nanoseconds` to `T <: Weeks`. #### Statistics diff --git a/stdlib/Dates/src/periods.jl b/stdlib/Dates/src/periods.jl index c1d94d3d62321..4d0fd6c50e1dc 100644 --- a/stdlib/Dates/src/periods.jl +++ b/stdlib/Dates/src/periods.jl @@ -175,6 +175,7 @@ periods(x::CompoundPeriod) = x.periods """ CompoundPeriod(periods) -> CompoundPeriod + CompoundPeriod(::Real, ::Type{Period}) -> CompoundPeriod Construct a `CompoundPeriod` from a `Vector` of `Period`s. All `Period`s of the same type will be added together. @@ -192,6 +193,9 @@ julia> Dates.CompoundPeriod(Dates.Month(1), Dates.Week(-2)) julia> Dates.CompoundPeriod(Dates.Minute(50000)) 50000 minutes + +julia> Dates.canonicalize(Dates.CompoundPeriod(1.5, Dates.Day)) +1 day, 12 hours ``` """ CompoundPeriod(p::Vector{<:Period}) = CompoundPeriod(Vector{Period}(p)) @@ -201,6 +205,10 @@ CompoundPeriod(t::Time) = CompoundPeriod(Period[Hour(t), Minute(t), Second(t), M CompoundPeriod(p::Period...) = CompoundPeriod(Period[p...]) +function CompoundPeriod(x::Real, ::Type{T}) where {T <: Period} + nf = value(convert(Nanosecond, T(1))) + return CompoundPeriod(Nanosecond(ceil(x * nf))) +end """ canonicalize(::CompoundPeriod) -> CompoundPeriod diff --git a/stdlib/Dates/test/periods.jl b/stdlib/Dates/test/periods.jl index 7cebfc55e7735..ff6968a7eaf1f 100644 --- a/stdlib/Dates/test/periods.jl +++ b/stdlib/Dates/test/periods.jl @@ -397,6 +397,23 @@ end @test_throws MethodError (Dates.Month(1) + Dates.Day(1)) - Dates.Date(2009,2,1) end +@testset "compound period from Real" begin + ccp(x, p) = Dates.canonicalize(Dates.CompoundPeriod(x, p)) + @test string(ccp(1.5, Dates.Minute)) == "1 minute, 30 seconds" + @test string(ccp((Dates.Second(Dates.Week(1))+Dates.Second(1)).value, Dates.Second)) == "1 week, 1 second" + @test string(ccp(1.5, Dates.Day)) == "1 day, 12 hours" + @test string(ccp(1.5+7, Dates.Day)) == "1 week, 1 day, 12 hours" + @test string(ccp(1.4, Dates.Second)) == "1 second, 400 milliseconds" + @test string(ccp(10.1, Dates.Week)) == "10 weeks, 16 hours, 48 minutes" + @test string(ccp(10.1, Dates.Week) - Dates.Minute(6)) == "10 weeks, 16 hours, 42 minutes" + @test ccp(1000000, Dates.Nanosecond) == Dates.canonicalize(Dates.Millisecond(1)) + @test ccp(1000, Dates.Millisecond) == Dates.canonicalize(Dates.Second(1)) + @test ccp(60, Dates.Second) == Dates.canonicalize(Dates.Minute(1)) + @test ccp(60, Dates.Minute) == Dates.canonicalize(Dates.Hour(1)) + @test ccp(24, Dates.Hour) == Dates.canonicalize(Dates.Day(1)) + @test ccp(7, Dates.Day) == Dates.canonicalize(Dates.Week(1)) +end + @testset "canonicalize Period" begin # reduce individual Period into most basic CompoundPeriod @test Dates.canonicalize(Dates.Nanosecond(1000000)) == Dates.canonicalize(Dates.Millisecond(1))