From e7e5e40f774be2df9c30b90bbf58730b082c9485 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 10 Nov 2017 08:48:40 -0600 Subject: [PATCH 1/4] Import Dates conversion functions --- src/conversions.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/conversions.jl b/src/conversions.jl index c855797b7..f75a1d461 100644 --- a/src/conversions.jl +++ b/src/conversions.jl @@ -1,4 +1,4 @@ -import Compat.Dates: now, julian2datetime, unix2datetime +import Compat.Dates: unix2datetime, datetime2unix, julian2datetime, datetime2julian, now # UTC is an abstract type defined in Dates, for some reason const utc_tz = FixedTimeZone("UTC") @@ -46,33 +46,33 @@ function astimezone(zdt::ZonedDateTime, tz::FixedTimeZone) end function zdt2julian(zdt::ZonedDateTime) - Dates.datetime2julian(utc(zdt)) + datetime2julian(utc(zdt)) end function zdt2julian(::Type{T}, zdt::ZonedDateTime) where T<:Integer - floor(T, Dates.datetime2julian(utc(zdt))) + floor(T, datetime2julian(utc(zdt))) end function zdt2julian(::Type{T}, zdt::ZonedDateTime) where T<:Number - convert(T, Dates.datetime2julian(utc(zdt))) + convert(T, datetime2julian(utc(zdt))) end function julian2zdt(jd::Real) - ZonedDateTime(Dates.julian2datetime(jd), utc_tz, from_utc=true) + ZonedDateTime(julian2datetime(jd), utc_tz, from_utc=true) end function zdt2unix(zdt::ZonedDateTime) - Dates.datetime2unix(utc(zdt)) + datetime2unix(utc(zdt)) end function zdt2unix(::Type{T}, zdt::ZonedDateTime) where T<:Integer - floor(T, Dates.datetime2unix(utc(zdt))) + floor(T, datetime2unix(utc(zdt))) end function zdt2unix(::Type{T}, zdt::ZonedDateTime) where T<:Number - convert(T, Dates.datetime2unix(utc(zdt))) + convert(T, datetime2unix(utc(zdt))) end function unix2zdt(seconds::Integer) - ZonedDateTime(Dates.unix2datetime(seconds), utc_tz, from_utc=true) + ZonedDateTime(unix2datetime(seconds), utc_tz, from_utc=true) end From f3831151034b4e6ca8454f39af8edd2c21cc9e1a Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 10 Nov 2017 08:52:27 -0600 Subject: [PATCH 2/4] Implement today(::TimeZone) --- src/TimeZones.jl | 2 +- src/conversions.jl | 23 ++++++++++++++++++++++- test/conversions.jl | 6 ++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/TimeZones.jl b/src/TimeZones.jl index e4d7e9df1..b7d01677d 100644 --- a/src/TimeZones.jl +++ b/src/TimeZones.jl @@ -29,7 +29,7 @@ export TimeZone, @tz_str, istimezone, FixedTimeZone, VariableTimeZone, ZonedDate # Re-export from Dates yearmonthday, yearmonth, monthday, year, month, week, day, dayofmonth, # conversion.jl - now, astimezone, + now, today, astimezone, # local.jl localzone, # ranges.jl diff --git a/src/conversions.jl b/src/conversions.jl index f75a1d461..f1382b750 100644 --- a/src/conversions.jl +++ b/src/conversions.jl @@ -1,4 +1,5 @@ -import Compat.Dates: unix2datetime, datetime2unix, julian2datetime, datetime2julian, now +import Compat.Dates: unix2datetime, datetime2unix, julian2datetime, datetime2julian, + now, today # UTC is an abstract type defined in Dates, for some reason const utc_tz = FixedTimeZone("UTC") @@ -20,6 +21,26 @@ function now(tz::TimeZone) ZonedDateTime(utc, tz, from_utc=true) end +""" + today(tz::TimeZone) -> Date + +Returns the date portion of `now(tz)` in local time. + +# Examples + +```julia +julia> a, b = now(tz"Pacific/Midway"), now(tz"Pacific/Apia") +(2017-11-09T03:47:04.226-11:00, 2017-11-10T04:47:04.226+14:00) + +julia> a - b +0 milliseconds + +julia> today(tz"Pacific/Midway"), today(tz"Pacific/Apia") +(2017-11-09, 2017-11-10) +``` +""" +today(tz::TimeZone) = Date(localtime(now(tz))) + """ astimezone(zdt::ZonedDateTime, tz::TimeZone) -> ZonedDateTime diff --git a/test/conversions.jl b/test/conversions.jl index 1b75ba53a..c7e586352 100644 --- a/test/conversions.jl +++ b/test/conversions.jl @@ -2,6 +2,8 @@ import Compat.Dates utc = FixedTimeZone("UTC") warsaw = resolve("Europe/Warsaw", tzdata["europe"]...) +apia = resolve("Pacific/Apia", tzdata["australasia"]...) +midway = resolve("Pacific/Midway", tzdata["australasia"]...) # Converting a ZonedDateTime into a DateTime dt = DateTime(2015, 1, 1, 0) @@ -22,6 +24,10 @@ zdt = now(warsaw) @test zdt.timezone == warsaw @test Dates.datetime2unix(TimeZones.utc(zdt)) ≈ Dates.datetime2unix(dt) +# today function +@test abs(today() - today(warsaw)) <= Dates.Day(1) +@test today(apia) - today(midway) == Dates.Day(1) + # Changing time zones dt = DateTime(2015, 1, 1, 0) From 73cca75bcd8505c9ef844b3203d0ae115a15916b Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 10 Nov 2017 08:56:55 -0600 Subject: [PATCH 3/4] Implement todayat --- src/TimeZones.jl | 2 +- src/conversions.jl | 24 ++++++++++++++++++++++++ test/conversions.jl | 15 +++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/TimeZones.jl b/src/TimeZones.jl index b7d01677d..782bed681 100644 --- a/src/TimeZones.jl +++ b/src/TimeZones.jl @@ -29,7 +29,7 @@ export TimeZone, @tz_str, istimezone, FixedTimeZone, VariableTimeZone, ZonedDate # Re-export from Dates yearmonthday, yearmonth, monthday, year, month, week, day, dayofmonth, # conversion.jl - now, today, astimezone, + now, today, todayat, astimezone, # local.jl localzone, # ranges.jl diff --git a/src/conversions.jl b/src/conversions.jl index f1382b750..556aeed61 100644 --- a/src/conversions.jl +++ b/src/conversions.jl @@ -1,5 +1,6 @@ import Compat.Dates: unix2datetime, datetime2unix, julian2datetime, datetime2julian, now, today +using Mocking # UTC is an abstract type defined in Dates, for some reason const utc_tz = FixedTimeZone("UTC") @@ -41,6 +42,29 @@ julia> today(tz"Pacific/Midway"), today(tz"Pacific/Apia") """ today(tz::TimeZone) = Date(localtime(now(tz))) +""" + todayat(tod::Time, tz::TimeZone, [amb]) -> ZonedDateTime + +Creates a `ZonedDateTime` for today at the specified time of day. If the result is ambiguous +in the given `TimeZone` then `amb` can be supplied to resolve ambiguity. + +# Examples + +```julia +julia> today(tz"Europe/Warsaw") +2017-11-09 + +julia> todayat(Time(10, 30), tz"Europe/Warsaw") +2017-11-09T10:30:00+01:00 +``` +""" +function todayat(tod::Time, tz::VariableTimeZone, amb::Union{Integer,Bool}) + ZonedDateTime((@mock today(tz)) + tod, tz, amb) +end + +todayat(tod::Time, tz::TimeZone) = ZonedDateTime((@mock today(tz)) + tod, tz) + + """ astimezone(zdt::ZonedDateTime, tz::TimeZone) -> ZonedDateTime diff --git a/test/conversions.jl b/test/conversions.jl index c7e586352..a8fbd3a7e 100644 --- a/test/conversions.jl +++ b/test/conversions.jl @@ -1,4 +1,5 @@ import Compat.Dates +using Mocking utc = FixedTimeZone("UTC") warsaw = resolve("Europe/Warsaw", tzdata["europe"]...) @@ -28,6 +29,20 @@ zdt = now(warsaw) @test abs(today() - today(warsaw)) <= Dates.Day(1) @test today(apia) - today(midway) == Dates.Day(1) +# todayat function +zdt = now(warsaw) +now_time = Time(TimeZones.localtime(zdt)) +@test todayat(now_time, warsaw) == zdt + +if !compiled_modules_enabled + patch = @patch today(tz::TimeZone) = Date(1916, 10, 1) + apply(patch) do + @test_throws AmbiguousTimeError todayat(Time(0), warsaw) + @test todayat(Time(0), warsaw, 1) == ZonedDateTime(1916, 10, 1, 0, warsaw, 1) + @test todayat(Time(0), warsaw, 2) == ZonedDateTime(1916, 10, 1, 0, warsaw, 2) + end +end + # Changing time zones dt = DateTime(2015, 1, 1, 0) From 25b7a66c22e6a4e0be71cd7b630ae8d21d262e81 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Mon, 29 Jan 2018 17:10:04 -0600 Subject: [PATCH 4/4] Add documentation about `today` and `todayat` --- docs/current.md | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/docs/current.md b/docs/current.md index 54f0223e9..7cf320419 100644 --- a/docs/current.md +++ b/docs/current.md @@ -1,6 +1,6 @@ ## Current Time / System Time Zone -Julia provides the `now()` method to retrieve your current system's time as a `DateTime`. The TimeZones.jl package provides an additional method to the `now` function providing the current time as a `ZonedDateTime`: +Julia provides the `now()` method to retrieve your current system's time as a `DateTime`. The TimeZones.jl package provides an additional `now(::TimeZone)` method providing the current time as a `ZonedDateTime`: ```julia now(tz"Europe/Warsaw") @@ -11,3 +11,47 @@ To get the `TimeZone` currently specified on you system you can use `localzone() ```julia now(localzone()) ``` + +## Today + +Similar to `now` the TimeZones package also provides a `today(::TimeZone)` method which allows you to determine the current date as a `Date` in the specified `TimeZone`. + +```julia +julia> a, b = now(tz"Pacific/Midway"), now(tz"Pacific/Apia") +(2018-01-29T12:01:53.504-11:00, 2018-01-30T13:01:53.504+14:00) + +julia> a - b +0 milliseconds + +julia> today(tz"Pacific/Midway"), today(tz"Pacific/Apia") +(2018-01-29, 2018-01-30) +``` + +You should be careful not to use `today()` when working with `ZonedDateTime`s as you may end up using the wrong day. For example: + +```julia +julia> midway, apia = tz"Pacific/Midway", tz"Pacific/Apia" +(Pacific/Midway (UTC-11), Pacific/Apia (UTC+13/UTC+14)) + +julia> ZonedDateTime(today() + Time(11), midway) +2018-01-29T11:00:00-11:00 + +julia> ZonedDateTime(today() + Time(11), apia) # Should be 2018-01-30 +2018-01-29T11:00:00+14:00 + +julia> ZonedDateTime(today(midway) + Time(11), midway) +2018-01-29T11:00:00-11:00 + +julia> ZonedDateTime(today(apia) + Time(11), apia) +2018-01-30T11:00:00+14:00 +``` + +Alternatively, you can use the `todayat` function which takes care of this for you: + +```julia +julia> todayat(Time(11), tz"Pacific/Midway") +2018-01-29T11:00:00-11:00 + +julia> todayat(Time(11), tz"Pacific/Apia") +2018-01-30T11:00:00+14:00 +```