Skip to content

Commit

Permalink
Merge pull request #100 from JuliaTime/cv/today
Browse files Browse the repository at this point in the history
Implement methods for `today` and `todayat`.
  • Loading branch information
omus authored Jan 30, 2018
2 parents 0085362 + 25b7a66 commit 3486f15
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 11 deletions.
46 changes: 45 additions & 1 deletion docs/current.md
Original file line number Diff line number Diff line change
@@ -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")
Expand All @@ -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
```
2 changes: 1 addition & 1 deletion src/TimeZones.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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, todayat, astimezone,
# local.jl
localzone,
# ranges.jl
Expand Down
63 changes: 54 additions & 9 deletions src/conversions.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import Compat.Dates: now, julian2datetime, unix2datetime
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")
Expand All @@ -20,6 +22,49 @@ 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)))

"""
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
Expand All @@ -46,33 +91,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
21 changes: 21 additions & 0 deletions test/conversions.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import Compat.Dates
using Mocking

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)
Expand All @@ -22,6 +25,24 @@ 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)

# 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)
Expand Down

0 comments on commit 3486f15

Please sign in to comment.