Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZonedDateTime can't parse it's own output #83

Open
Keno opened this issue Aug 10, 2017 · 21 comments
Open

ZonedDateTime can't parse it's own output #83

Keno opened this issue Aug 10, 2017 · 21 comments

Comments

@Keno
Copy link

Keno commented Aug 10, 2017

This seems unfortunate:

julia> ZonedDateTime(DateTime(2014,1,1), TimeZone("Europe/Warsaw"))
2014-01-01T00:00:00+01:00

julia> ZonedDateTime("2014-01-01T00:00:00+01:00")
ERROR: ArgumentError: Unable to parse date time. Expected directive Delim(.) at char 20
@omus
Copy link
Member

omus commented Aug 10, 2017

It's definite possible to get it to parse the output.

Unfortunately the output only shows the UTC offset for that specific timestamp which means that parsing it will result a loss of information since we would have to parse the string as a FixedTimeZone("+01:00") rather than TimeZone("Europe/Warsaw"). Maybe I should change the default show to be 2014-01-01T00:00:00 Europe/Warsaw.

@Keno
Copy link
Author

Keno commented Aug 10, 2017

The output is actually fine with me. My concern is more the parsing. In Base, we hack the ISODateTime parsing to make the .sss optional, but here we don't. Of course the ISO8601 complete representation doesn't include milliseconds at all.

@Keno
Copy link
Author

Keno commented Aug 10, 2017

Although it does say

If necessary for a particular application a decimal fraction of hour, minute or second may be included. If a
decimal fraction is included, lower order time elements (if any) shall be omitted and the decimal fraction shall
be divided from the integer part by the decimal sign specified in ISO 31-0, i.e. the comma [,] or full stop [.]. Of
these, the comma is the preferred sign. If the magnitude of the number is less than unity, the decimal sign
shall be preceded by two zeros in accordance with 3.6. 

so maybe in parsing of various components, we should always allow . and , and treat it as decimal separators?

@Keno
Copy link
Author

Keno commented Aug 10, 2017

cc also @quinnj

@quinnj
Copy link
Collaborator

quinnj commented Aug 10, 2017

I'm following along :)

@omus
Copy link
Member

omus commented Aug 10, 2017

The DateFormat specification could use a re-think. It would be nice if when parsing you could state a section was optional. Something like df"yyyy-mm-dd HH:MM:SS(.sss)zzz". Additionally, I dislike that I'm using zzz for reading in +01:00. It would be better to break up that into multiple components like sign, hour, minutes. Something like ±{zone-hour}:{zone-minute} (I'm not sure what letters would be good here...)

@Keno
Copy link
Author

Keno commented Aug 10, 2017

I don't think I actually mind zzz that much, because for UTC, the standard specifies Z, which I'd like to match as well.

@Keno
Copy link
Author

Keno commented Aug 10, 2017

As for letters, there's always hᶻ of course.

@omus
Copy link
Member

omus commented Aug 10, 2017

Mostly the optional specifiers for parsing would be useful.

@omus
Copy link
Member

omus commented May 2, 2018

@rofinn just ran into this one:

julia> ZonedDateTime("2017-01-28T11:59:59+00:00")
ERROR: ArgumentError: Unable to parse date time. Expected directive Delim(.) at char 20

@yakir12
Copy link

yakir12 commented Nov 2, 2018

I ran into the same problem as well (I ended up adding a silly Millisecond(1) to everything). But this touches the problem that the string representation of this type is not complete (the location of the time zone is missing).
How to save zoned date & time is an issue a lot of people get hit by. It would be great if there was a function that took an instance of ZonedDateTime and output all the necessary parts (local time and location?) as strings so it could get saved correctly.

@omus
Copy link
Member

omus commented Nov 2, 2018

Something related would be to make sure that repr for ZonedDateTime print as parsable Julia code ZonedDateTime(2018, 11, 2, 12, 55, tz"America/Winnipeg") and have print display the current compact representation 2018-11-02T12:55:00-05:00.

@omus
Copy link
Member

omus commented Nov 2, 2018

Related: JuliaLang/julia#29909

@yakir12
Copy link

yakir12 commented Nov 2, 2018

Excuse my ignorance, but is 2018-11-02T12:55:00-05:00 really enough for correctly saving a zoned date & time...? I thought you'd need the location as well, and not "just" the UTC-offset, à la this example.

@iamed2
Copy link
Member

iamed2 commented Nov 2, 2018

You correctly save the instant in time but you lose information for, e.g., date math.

@galenlynch
Copy link

This is still a problem:

julia> ZonedDateTime("2017-04-14 10:58:40-04", dateformat"YYYY-mm-dd HH:MM:SS.ssszz")
ERROR: ArgumentError: Unable to parse string "2017-04-14 10:58:40-04" using format dateformat"YYYY-mm-dd HH:MM:SS.ssszz". Unable to parse date time. Expected directive Delim(.) at char 20
Stacktrace:
 [1] macro expansion at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Dates/src/parse.jl:104 [inlined]
 [2] tryparsenext_core(::String, ::Int64, ::Int64, ::DateFormat{Symbol("YYYY-mm-dd HH:MM:SS.ssszz"),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'},Dates.Delim{Char,1},Dates.DatePart{'S'},Dates.Delim{Char,1},Dates.DatePart{'s'},Dates.DatePart{'z'}}}, ::Bool) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Dates/src/parse.jl:40
 [3] macro expansion at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Dates/src/parse.jl:150 [inlined]
 [4] tryparsenext_internal at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Dates/src/parse.jl:127 [inlined]
 [5] parse at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Dates/src/parse.jl:282 [inlined]
 [6] ZonedDateTime(::String, ::DateFormat{Symbol("YYYY-mm-dd HH:MM:SS.ssszz"),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'},Dates.Delim{Char,1},Dates.DatePart{'S'},Dates.Delim{Char,1},Dates.DatePart{'s'},Dates.DatePart{'z'}}}) at /home/glynch/.julia/packages/TimeZones/Z0kpK/src/parse.jl:85
 [7] top-level scope at none:0

@omus
Copy link
Member

omus commented Jun 14, 2019

This is still a problem

Your particular example will always be an issue. If you are passing in a DateFormat explicitly where you are trying to parse milliseconds the parsing will fail.

As a stop gap measure I'm planning on supporting:

parse(ZonedDateTime, str)

which would handle both dateformat"YYYY-mm-dd HH:MM:SSzzz" and dateformat"YYYY-mm-dd HH:MM:SS.ssszzz" as a special case.

I'm also doing so research into different date parsing/formatting syntaxes to see what alternatives I can find and introduce into the Dates stdlib.

@dehann
Copy link

dehann commented Aug 12, 2020

Hi @omus , we just came across this too:

julia> str = string(ZonedDateTime("2020-08-12T12:00:00.000+00:00"))
"2020-08-12T12:00:00+00:00"

julia> parse(ZonedDateTime, str)
ERROR: ArgumentError: Unable to parse date time. Expected directive Delim(.) at char 20
Stacktrace:
 [1] macro expansion at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Dates/src/parse.jl:104 [inlined]
 [2] tryparsenext_core(::String, ::Int64, ::Int64, ::DateFormat{Symbol("yyyy-mm-ddTHH:MM:SS.ssszzz"),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'},Dates.Delim{Char,1},Dates.DatePart{'S'},Dates.Delim{Char,1},Dates.DatePart{'s'},Dates.DatePart{'z'}}}, ::Bool) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Dates/src/parse.jl:38
 [3] macro expansion at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Dates/src/parse.jl:150 [inlined]
 [4] tryparsenext_internal at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Dates/src/parse.jl:125 [inlined]
 [5] parse(::Type{ZonedDateTime}, ::String, ::DateFormat{Symbol("yyyy-mm-ddTHH:MM:SS.ssszzz"),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'},Dates.Delim{Char,1},Dates.DatePart{'S'},Dates.Delim{Char,1},Dates.DatePart{'s'},Dates.DatePart{'z'}}}) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Dates/src/parse.jl:282
 [6] parse(::Type{ZonedDateTime}, ::String) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Dates/src/parse.jl:281
 [7] top-level scope at REPL[13]:1

Ref the Time Standard:
https://en.wikipedia.org/wiki/ISO_8601

@acdupont
Copy link

This seems unfortunate:

julia> ZonedDateTime(DateTime(2014,1,1), TimeZone("Europe/Warsaw"))
2014-01-01T00:00:00+01:00

julia> ZonedDateTime("2014-01-01T00:00:00+01:00")
ERROR: ArgumentError: Unable to parse date time. Expected directive Delim(.) at char 20

Is there plans to fix this? I was going to open an issue as I ran to this exact problem. Shouldn't ZonedDateTime be able to parse an valid ISO 8601 string?

@acdupont
Copy link

It's definite possible to get it to parse the output.

Unfortunately the output only shows the UTC offset for that specific timestamp which means that parsing it will result a loss of information since we would have to parse the string as a FixedTimeZone("+01:00") rather than TimeZone("Europe/Warsaw"). Maybe I should change the default show to be 2014-01-01T00:00:00 Europe/Warsaw.

The loss of information did not occur at parse time, it occured when converting the ZonedDateTime to a String

@acdupont
Copy link

acdupont commented Nov 13, 2022

Also note that while this 2014-01-01T00:00:00+01:00 fails, this 2014-01-01T00:00:00.000+01:00 can be parsed (added .000 milliseconds).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants