TimeZones.jl icon indicating copy to clipboard operation
TimeZones.jl copied to clipboard

Parse date-time with optional timezone in the format.

Open mdashti opened this issue 5 years ago • 5 comments

Currently, this invocation of ZonedDateTime constructor throws an error:

julia> ZonedDateTime("1988-04-29 09:00", "yyyy-mm-dd HH:MM")
ERROR: ArgumentError: Unable to parse string "1988-04-29 09:00" using format dateformat"yyyy-mm-dd HH:MM". Unknown time zone ""
Stacktrace:
 [1] (::getfield(TimeZones, Symbol("##3#4")){String})() at /Users/dashti/.julia/packages/TimeZones/M8H2J/src/types/timezone.jl:54
 [2] get!(::getfield(TimeZones, Symbol("##3#4")){String}, ::Dict{String,Tuple{TimeZone,TimeZones.Class}}, ::String) at ./dict.jl:452
 [3] TimeZone(::String, ::TimeZones.Class) at /Users/dashti/.julia/packages/TimeZones/M8H2J/src/types/timezone.jl:46 (repeats 2 times)
 [4] ZonedDateTime(::Int64, ::Int64, ::Int64, ::Int64, ::Int64, ::Int64, ::Int64, ::String) at /Users/dashti/.julia/packages/TimeZones/M8H2J/src/types/zoneddatetime.jl:127
 [5] parse at /Users/sabae/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.2/Dates/src/parse.jl:285 [inlined]
 [6] ZonedDateTime(::String, ::Dates.DateFormat{Symbol("yyyy-mm-dd HH:MM"),Tuple{Dates.DatePart{'y'},Dates.Delim{Char,1},Dates.DatePart{'m'},Dates.Delim{Char,1},Dates.DatePart{'d'},Dates.Delim{Char,1},Dates.DatePart{'H'},Dates.Delim{Char,1},Dates.DatePart{'M'}}}) at /Users/dashti/.julia/packages/TimeZones/M8H2J/src/parse.jl:85
 [7] #ZonedDateTime#29(::String, ::Type{ZonedDateTime}, ::String, ::String) at /Users/dashti/.julia/packages/TimeZones/M8H2J/src/parse.jl:98
 [8] ZonedDateTime(::String, ::String) at /Users/dashti/.julia/packages/TimeZones/M8H2J/src/parse.jl:98
 [9] top-level scope at REPL[6]:1

The reason is that no timezone is specified in the date format. You might say that I should use DateTime("1988-04-29 09:00", "yyyy-mm-dd HH:MM"), but what if I'm programming a library function and receiving the format as a parameter. Then, I have to have something like this (which is UGLY):

function parse_date_into_utc(input::String, format::String) :: DateTime
    if occursin("z", format) || occursin("Z", format)
        zdt = TimeZones.ZonedDateTime(input, format)
        zdt.utc_datetime
    else
        DateTime(input, format)
    end
end

Ideally, it should be possible to implement the same like this:

function parse_date_into_utc(input::String, format::String) :: DateTime
    zdt = TimeZones.ZonedDateTime(input, format)
    zdt.utc_datetime
end

The main reason for the error is that an empty timezone string produces an error in here. Can we have a default timezone (e.g., user-specified, UTC or local timezone) for this case?

mdashti avatar Aug 29 '19 09:08 mdashti

The default would have to be user specified otherwise people could be very surprised when we assume the local time zone or UTC.

omus avatar Sep 11 '19 20:09 omus

I think this a keyword could be added to specify the DateFormat does not contain a time zone.

Asides:

  • You should really use dateformat"yyyy-mm-dd HH:MM" if you want performant code. Constructing the DateFormat object is rather of expensive
  • Prefer using parse(ZonedDateTime, ::String, ::DateFormat). I have plans to deprecate the ZonedDateTime constructor with a date format.

omus avatar Sep 11 '19 20:09 omus

The default would have to be user specified otherwise people could be very surprised when we assume the local time zone or UTC.

@omus Agreed, It's better for it to be user-defined.

mdashti avatar Sep 11 '19 20:09 mdashti

Any updates on this?

I have a similar issue: I would like to parse a string with no time zone info directly into a ZonedDateTime by supplying the time zone myself.

As an example, instead of this workaround

using Dates
using TimeZones

t_string = "2021-11-13T12:34:56Z"

fmt = Dates.DateFormat("yyyy-mm-ddTHH:MM:SS\\Z")
t = Dates.DateTime(t_string, fmt)
TimeZones.ZonedDateTime(t, TimeZones.tz"UTC")

I would like something like this

TimeZones.ZonedDateTime(t_string, fmt, TimeZones.tz"UTC")

(@omus : Is your comment about preferring parse still valid? It seems that the constructor for ZonedDateTime is still around)

robertdj avatar Nov 13 '21 16:11 robertdj

Unfortunately no updates at this time. PRs are welcome.

I do still recommend using parse to make your intent clear. The constructor is around and probably will continue to be around due to how the compact printing works in Dates.

omus avatar Nov 13 '21 16:11 omus