How do I parse the string "29 February" into a date structure

using Dates
julia> format = Dates.DateFormat("d U")
dateformat"d U"

julia> parse(Date,"28 February",format) + Dates.Year(2020-1)
2020-02-28

julia> parse(Date,"29 February",format) + Dates.Year(2020-1)
ERROR: ArgumentError: Day: 29 out of range (1:28)
Stacktrace:
 [1] Date(::Int64, ::Int64, ::Int64) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/Dates/src/types.jl:223
 [2] parse(::Type{Date}, ::String, ::DateFormat{Symbol("d U"),Tuple{Dates.DatePart{'d'},Dates.Delim{Char,1},Dates.DatePart{'U'}}}) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/Dates/src/parse.jl:285
 [3] top-level scope at none:0

E.g. (but less simple to allow both formats at once (with or w/o comma), not sure how without some exception-handling logic):

julia> parse(Date,"29 February 2020", Dates.DateFormat("d U Y"))
2020-02-29

julia> parse(Date,"February 29, 2020", Dates.DateFormat("U d, Y"))
2020-02-29

The leap-year day isn’t valid every year (only approximately, not exactly, every 4 years), so your error seems intentional by the Dates module author and thus you must do similar to above. For e.g. 2019 shouldn’t work, as for your Dates.Year(2020-1) example, nor for a legal year.

I believe this is intended behavior.

The error is in the statement parse(Date, "29 February", format). When you don’t specify the year, it is defaulted to 1 CE. And as far as my memory goes, that year wasn’t a leap year. :slightly_smiling_face:

julia> parse(Date, "28 February", format)
0001-02-28

julia> parse(Date, "29 February", format)
ERROR: ArgumentError: Day: 29 out of range (1:28)

But:

julia> parse(Date, "29 February 0", dateformat"d U Y")
0000-02-29
julia> parse(Date, "29 February 0", dateformat"d U Y") + Dates.Year(2020)
2020-02-29
4 Likes
function clean_date_string(s,DefaultYear=2020)
    format = Dates.DateFormat("d U Y")
    date = Date(2000,1,1)
    try
        date = parse(Date,s * " 2000",format) + Dates.Year(DefaultYear - 2000)
    catch
        println("Error: in function clean_date_string")
        println("Error: Unable to parse <$s>")
        flush(stdout)
        exit(0)
    end
    return Dates.format(date,"YYYY-mm-dd")
end

I end up with this solution which allows the input string “29 February”

2 Likes