diff --git a/src/arithmetic.jl b/src/arithmetic.jl index e1991b711..9438ca19d 100644 --- a/src/arithmetic.jl +++ b/src/arithmetic.jl @@ -17,7 +17,7 @@ function Base.:(-)(zdt::ZonedDateTime, p::TimePeriod) return ZonedDateTime(DateTime(zdt, UTC) - p, timezone(zdt); from_utc=true) end -function broadcasted(::typeof(+), r::StepRange{ZonedDateTime}, p::DatePeriod) +function broadcasted(::typeof(+), r::StepRange{<:ZonedDateTime}, p::DatePeriod) start, step, stop = first(r), Base.step(r), last(r) # Since the local time + period can result in an invalid local datetime when working with @@ -41,10 +41,10 @@ function broadcasted(::typeof(+), r::StepRange{ZonedDateTime}, p::DatePeriod) return StepRange(start, step, stop) end -function broadcasted(::typeof(+), r::StepRange{ZonedDateTime}, p::TimePeriod) +function broadcasted(::typeof(+), r::StepRange{<:ZonedDateTime}, p::TimePeriod) return StepRange(r.start + p, r.step, r.stop + p) end -broadcasted(::typeof(+), p::Period, r::StepRange{ZonedDateTime}) = broadcasted(+, r, p) -broadcasted(::typeof(-), r::StepRange{ZonedDateTime}, p::Period) = broadcasted(+, r, -p) -broadcasted(::typeof(-), p::Period, r::StepRange{ZonedDateTime}) = broadcasted(-, r, p) +broadcasted(::typeof(+), p::Period, r::StepRange{<:ZonedDateTime}) = broadcasted(+, r, p) +broadcasted(::typeof(-), r::StepRange{<:ZonedDateTime}, p::Period) = broadcasted(+, r, -p) +broadcasted(::typeof(-), p::Period, r::StepRange{<:ZonedDateTime}) = broadcasted(-, r, p) diff --git a/src/types/zoneddatetime.jl b/src/types/zoneddatetime.jl index 2c832e8d9..378dd8cd6 100644 --- a/src/types/zoneddatetime.jl +++ b/src/types/zoneddatetime.jl @@ -6,22 +6,20 @@ using Dates: AbstractDateTime, argerror, validargs # A `DateTime` that includes `TimeZone` information. # """ -struct ZonedDateTime <: AbstractDateTime +struct ZonedDateTime{T<:TimeZone} <: AbstractDateTime utc_datetime::DateTime - timezone::TimeZone + timezone::T zone::FixedTimeZone # The current zone for the utc_datetime. +end - function ZonedDateTime(utc_datetime::DateTime, timezone::TimeZone, zone::FixedTimeZone) - return new(utc_datetime, timezone, zone) +function ZonedDateTime( + utc_datetime::DateTime, timezone::VariableTimeZone, zone::FixedTimeZone +) + if timezone.cutoff !== nothing && utc_datetime >= timezone.cutoff + throw(UnhandledTimeError(timezone)) end - function ZonedDateTime(utc_datetime::DateTime, timezone::VariableTimeZone, zone::FixedTimeZone) - if timezone.cutoff !== nothing && utc_datetime >= timezone.cutoff - throw(UnhandledTimeError(timezone)) - end - - return new(utc_datetime, timezone, zone) - end + return ZonedDateTime{VariableTimeZone}(utc_datetime, timezone, zone) end """ @@ -181,11 +179,11 @@ function Base.hash(zdt::ZonedDateTime, h::UInt) return h end -Base.typemin(::Type{ZonedDateTime}) = ZonedDateTime(typemin(DateTime), utc_tz; from_utc=true) -Base.typemax(::Type{ZonedDateTime}) = ZonedDateTime(typemax(DateTime), utc_tz; from_utc=true) +Base.typemin(::Type{<:ZonedDateTime}) = ZonedDateTime(typemin(DateTime), utc_tz; from_utc=true) +Base.typemax(::Type{<:ZonedDateTime}) = ZonedDateTime(typemax(DateTime), utc_tz; from_utc=true) # Note: The `validargs` function is as part of the Dates parsing interface. -function Dates.validargs(::Type{ZonedDateTime}, y::Int64, m::Union{Int64, Int32}, d::Int64, h::Int64, mi::Int64, s::Int64, ms::Int64, tz::AbstractString) +function Dates.validargs(::Type{<:ZonedDateTime}, y::Int64, m::Union{Int64, Int32}, d::Int64, h::Int64, mi::Int64, s::Int64, ms::Int64, tz::AbstractString) err = validargs(DateTime, y, Int64(m), d, h, mi, s, ms) err === nothing || return err istimezone(tz) || return argerror("TimeZone: \"$tz\" is not a recognized time zone") diff --git a/test/arithmetic.jl b/test/arithmetic.jl index 2c8f66aa7..13de497ae 100644 --- a/test/arithmetic.jl +++ b/test/arithmetic.jl @@ -55,7 +55,7 @@ spring_zdt = ZonedDateTime(spring, warsaw) # Arithmetic with a StepRange should always work even when the start/stop lands on # ambiguous or non-existent DateTimes. -@testset "StepRange{ZonedDateTime}" begin +@testset "StepRange{<:ZonedDateTime}" begin @testset "time-period" begin dt = DateTime(2015, 6, 1) @@ -71,7 +71,7 @@ spring_zdt = ZonedDateTime(spring, warsaw) ) @test results == expected @test length(results) == 2 - @test results isa StepRange{ZonedDateTime} + @test results isa StepRange{<:ZonedDateTime} end @testset "date-period" begin @@ -89,7 +89,7 @@ spring_zdt = ZonedDateTime(spring, warsaw) ) @test results == expected @test length(results) == 2 - @test results isa StepRange{ZonedDateTime} + @test results isa StepRange{<:ZonedDateTime} end @testset "ambiguous" begin diff --git a/test/io.jl b/test/io.jl index 7f8cda4b8..ef6d4a7a2 100644 --- a/test/io.jl +++ b/test/io.jl @@ -76,8 +76,7 @@ zdt = ZonedDateTime(dt, warsaw) zdt_vector = [zdt] @test sprint(show, MIME("text/plain"), zdt_vector) == summary(zdt_vector) * ":\n 1942-12-25T01:23:45+01:00" -prefix = VERSION >= v"1.5.0-DEV.224" ? "" : "ZonedDateTime" -@test sprint(show, zdt_vector; context=:compact => true) == "$prefix[ZonedDateTime(1942, 12, 25, 1, 23, 45, tz\"Europe/Warsaw\")]" +@test sprint(show, zdt_vector; context=:compact => true) == "ZonedDateTime{VariableTimeZone}[ZonedDateTime(1942, 12, 25, 1, 23, 45, tz\"Europe/Warsaw\")]" # TimeZone parsing diff --git a/test/types/zoneddatetime.jl b/test/types/zoneddatetime.jl index e776e5bb9..24c9fbb01 100644 --- a/test/types/zoneddatetime.jl +++ b/test/types/zoneddatetime.jl @@ -430,4 +430,18 @@ using Dates: Hour, Second, UTM, @dateformat_str @test typemin(ZonedDateTime) <= ZonedDateTime(typemin(DateTime), utc) @test typemax(ZonedDateTime) >= ZonedDateTime(typemax(DateTime), utc) end + + @testset "isbits(::ZonedDateTime)" begin + # https://github.com/JuliaTime/TimeZones.jl/issues/271 + + @testset "typeof($zone)" for zone in (tz"America/Winnipeg", FixedTimeZone("0123")) + # We are not isbits until we fix the timezone to also be isbits + zdt = ZonedDateTime(Date(2000), zone) + if isbits(zone) + @test isbits(zdt) + else + @test_broken isbits(zdt) + end + end + end end