JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.74k stars 5.49k forks source link

DateFormat cannot parse ISO 8601 times with decimal fractions #35409

Open non-Jedi opened 4 years ago

non-Jedi commented 4 years ago

According to Wikipedia, for an ISO 8601 time:

Decimal fractions may be added to any of the three time elements. However, a fraction may only be added to the lowest order time element in the representation. A decimal mark, either a comma or a dot (without any preference as stated in resolution 10 of the 22nd General Conference CGPM in 2003,[25] but with a preference for a comma according to ISO 8601:2004)[26] is used as a separator between the time element and its fraction. To denote "14 hours, 30 and one half minutes", do not include a seconds figure. Represent it as "14:30,5", "1430,5", "14:30.5", or "1430.5". There is no limit on the number of decimal places for the decimal fraction.

So first, the DateFormat machinery should be upgraded to be compatible with decimal fractions and then we also need to make sure ISODateTimeFormat and ISOTimeFormat correctly handles said fractions.

Currently:

julia> using Dates

julia> Time("05:03,5")
ERROR: ArgumentError: Unable to parse date time. Expected directive Delim(:) at char 6
Stacktrace:
 [1] macro expansion at /builddir/julia-1.4.0/usr/share/julia/stdlib/v1.4/Dates/src/parse.jl:104 [inlined]
 [2] tryparsenext_core(::String, ::Int64, ::Int64, ::DateFormat{Symbol("HH:MM:SS.s"),Tuple{Dates.DatePart{'H'},Dates.Delim{Char,1},Dates.DatePart{'M'},Dates.Delim{Char,1},Dates.DatePart{'S'},Dates.Delim{Char,1},Dates.DatePart{'s'}}}, ::Bool) at /builddir/julia-1.4.0/usr/share/julia/stdlib/v1.4/Dates/src/parse.jl:40
 [3] macro expansion at /builddir/julia-1.4.0/usr/share/julia/stdlib/v1.4/Dates/src/parse.jl:150 [inlined]
 [4] tryparsenext_internal at /builddir/julia-1.4.0/usr/share/julia/stdlib/v1.4/Dates/src/parse.jl:127 [inlined]
 [5] parse at /builddir/julia-1.4.0/usr/share/julia/stdlib/v1.4/Dates/src/parse.jl:282 [inlined]
 [6] Time at /builddir/julia-1.4.0/usr/share/julia/stdlib/v1.4/Dates/src/io.jl:524 [inlined] (repeats 2 times)
 [7] top-level scope at REPL[2]:1
 [8] run_backend(::REPL.REPLBackend) at /home/adam/.julia/packages/Revise/2NCCI/src/Revise.jl:1036
 [9] (::Revise.var"#85#87"{REPL.REPLBackend})() at ./task.jl:358
non-Jedi commented 4 years ago

There's really two issues here:

  1. The smallest unit available in Dates is millisecond. Through decimals fractions, ISO 8601 allows arbitrary precision times.
  2. ISO 8601 allows for both "," and "." decimal separators and the DateFormat machinery has no way of expressing this.

1 seems intractable to me and should probably be punted to a third-party library, but 2 seems useful and possible. I am hesitant to introduce additional syntax to DateFormat though. Would it be better to change the constructors in Dates to accept additional DateFormat options treating the order they are passed as the order of priority for parsing? Then the default without passing a DateFormat could be that two versions of ISOTimeFormat are used with parsing with comma-separator used as a fallback.