From d86d9de15084ced06a6da1c9b97deb4efd4bf3f3 Mon Sep 17 00:00:00 2001 From: Rory Finnegan Date: Fri, 20 Jan 2023 13:47:17 -0800 Subject: [PATCH 1/2] Adding support for UTCDateTime conversions. --- Project.toml | 4 ++- src/LaxZonedDateTimes.jl | 14 ++++++++++ test/laxzoneddatetimes.jl | 57 ++++++++++++++++++++++++++++++++++++--- test/runtests.jl | 1 + 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/Project.toml b/Project.toml index 70135ca..a96d8a7 100644 --- a/Project.toml +++ b/Project.toml @@ -1,16 +1,18 @@ name = "LaxZonedDateTimes" uuid = "e4c54217-8d3e-5504-a69c-0db1bad43e12" authors = ["Invenia Technical Computing"] -version = "1.3.1" +version = "1.4.0" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" Intervals = "d8418881-c3e1-53bb-8760-2df7ec849ed5" TimeZones = "f269a46b-ccf7-5d73-abea-4c690281aa53" +UTCDateTimes = "0f7cfa37-7abf-4834-b969-a8aa512401c2" [compat] Intervals = "1.5" TimeZones = "0.11, 1" +UTCDateTimes = "1.1" julia = "1" [extras] diff --git a/src/LaxZonedDateTimes.jl b/src/LaxZonedDateTimes.jl index 2f562a1..59e9245 100644 --- a/src/LaxZonedDateTimes.jl +++ b/src/LaxZonedDateTimes.jl @@ -6,6 +6,7 @@ using Dates: AbstractDateTime, DatePeriod, DateTime, Dates, Millisecond, Period, using Intervals using TimeZones using TimeZones: Local, UTC, interpret, timezone +using UTCDateTimes export LaxZonedDateTime, ZDT, @@ -39,6 +40,11 @@ function LaxZonedDateTime() LaxZonedDateTime(DateTime(0), utc, utc, false) end +function LaxZonedDateTime(utcdt::UTCDateTime) + utc = TimeZone("UTC") + LaxZonedDateTime(DateTime(utcdt), utc, utc, true) +end + function LaxZonedDateTime(zdt::ZonedDateTime) LaxZonedDateTime(DateTime(zdt), timezone(zdt), zdt.zone, true) end @@ -210,6 +216,9 @@ Base.promote_rule(::Type{LaxZonedDateTime},::Type{ZonedDateTime}) = LaxZonedDate Base.convert(::Type{LaxZonedDateTime}, x::ZonedDateTime) = LaxZonedDateTime(x) Base.convert(::Type{ZonedDateTime}, x::LaxZonedDateTime) = ZonedDateTime(x) +Base.convert(::Type{LaxZonedDateTime}, x::UTCDateTime) = LaxZonedDateTime(x) +Base.convert(::Type{UTCDateTime}, x::LaxZonedDateTime) = UTCDateTime(x) + function Base.isless(a::LaxZonedDateTime, b::LaxZonedDateTime) if !isrepresentable(a) || !isrepresentable(b) return false @@ -274,6 +283,11 @@ function TimeZones.ZonedDateTime(lzdt::LaxZonedDateTime, resolve_by::Symbol=:thr end end +# Not very performant, but just reuse the ZonedDateTime constructor above for UTCDateTimes +function UTCDateTimes.UTCDateTime(lzdt::LaxZonedDateTime, args...) + return UTCDateTime(ZonedDateTime(lzdt, args...)) +end + const ZDT = Union{ZonedDateTime, LaxZonedDateTime} include("accessors.jl") diff --git a/test/laxzoneddatetimes.jl b/test/laxzoneddatetimes.jl index 7f32a6f..b1125dc 100644 --- a/test/laxzoneddatetimes.jl +++ b/test/laxzoneddatetimes.jl @@ -2,9 +2,13 @@ utc = TimeZone("UTC") fixed = FixedTimeZone("UTC-06:00") dt = DateTime(2016, 8, 11, 2, 30) + utcdt = UTCDateTime(dt) + + @test ZonedDateTime(LaxZonedDateTime(utcdt)) == ZonedDateTime(utcdt) for t in (utc, fixed) @test ZonedDateTime(LaxZonedDateTime(dt, t)) == ZonedDateTime(dt, t) + for p in (Hour(1), Day(1)) @test LaxZonedDateTime(dt, t) + p == LaxZonedDateTime(dt + p, t) @test LaxZonedDateTime(dt, t) - p == LaxZonedDateTime(dt - p, t) @@ -55,7 +59,7 @@ end @test isequal(non_existent - Hour(0), LaxZonedDateTime()) @test isequal((non_existent + Hour(1)) + Hour(1), LaxZonedDateTime()) - @test isequal((non_existent + Hour(1)) + Day(1), LaxZonedDateTime()) + @test isequal((non_existent + Hour(1)) + Day(1), LaxZonedDateTime()) end @testset "compare" begin @@ -64,7 +68,7 @@ end a = LaxZonedDateTime(ZonedDateTime(2014,winnipeg)) b = ZonedDateTime(2015,winnipeg) @test a < b - + a = ZonedDateTime(2016, 11, 6, 1, 30, winnipeg, 1) b = ZonedDateTime(2016, 11, 6, 1, winnipeg, 2) @@ -187,5 +191,50 @@ end @test_throws NonExistentTimeError ZonedDateTime(dne, :throw) @test_throws NonExistentTimeError ZonedDateTime(dne) end - -end \ No newline at end of file + +end + +@testset "convert to UTCDateTime" begin + + @testset "basic" begin + lzdt = LaxZonedDateTime(DateTime(2020, 1, 1, 9, 30), winnipeg) + expected = UTCDateTime(ZonedDateTime(DateTime(2020, 1, 1, 9, 30), winnipeg)) + @test UTCDateTime(lzdt) == expected + end + + @testset "Ambiguous" begin + # Occurs during Fall DST - it's the same hour just in two different timezones + amb = LaxZonedDateTime(DateTime(2016, 11, 6, 1, 45), winnipeg) + + utcdt = UTCDateTime(amb, :first) + exp_first = UTCDateTime(ZonedDateTime(2016, 11, 6, 1, 45, winnipeg, 1)) + @test utcdt == exp_first + + utcdt = UTCDateTime(amb, :last) + exp_last = UTCDateTime(ZonedDateTime(2016, 11, 6, 1, 45, winnipeg, 2)) + @test utcdt == exp_last + + @test_throws AmbiguousTimeError UTCDateTime(amb, :throw) + @test_throws AmbiguousTimeError UTCDateTime(amb) + + end + + @testset "NonExistent" begin + # Occurs during Spring DST + dne = LaxZonedDateTime(DateTime(2016, 3, 13, 2, 45), winnipeg) + + # :first gets the time just before the transition occurred + utcdt = UTCDateTime(dne, :first) + exp_first = UTCDateTime(ZonedDateTime(2016, 3, 13, 1, 59, 59, 999, winnipeg)) + @test utcdt == exp_first + + # :last gets the hour after the transition occurred + utcdt = UTCDateTime(dne, :last) + exp_last = UTCDateTime(ZonedDateTime(2016, 3, 13, 3, 0, winnipeg)) + @test utcdt == exp_last + + @test_throws NonExistentTimeError UTCDateTime(dne, :throw) + @test_throws NonExistentTimeError UTCDateTime(dne) + end + +end diff --git a/test/runtests.jl b/test/runtests.jl index 503b6a2..0c253bf 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -5,6 +5,7 @@ using LaxZonedDateTimes: isrepresentable, NonExistent using Test using TimeZones using TimeZones: Transition, timezone +using UTCDateTimes const winnipeg = TimeZone("America/Winnipeg") From e4976861a04b768a473edc17ee077cf9788e3310 Mon Sep 17 00:00:00 2001 From: Rory Finnegan Date: Fri, 24 Feb 2023 11:21:22 -0800 Subject: [PATCH 2/2] Update src/LaxZonedDateTimes.jl Co-authored-by: Eric Davies --- src/LaxZonedDateTimes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaxZonedDateTimes.jl b/src/LaxZonedDateTimes.jl index 59e9245..d08d2b0 100644 --- a/src/LaxZonedDateTimes.jl +++ b/src/LaxZonedDateTimes.jl @@ -41,7 +41,7 @@ function LaxZonedDateTime() end function LaxZonedDateTime(utcdt::UTCDateTime) - utc = TimeZone("UTC") + utc = tz"UTC" LaxZonedDateTime(DateTime(utcdt), utc, utc, true) end