Skip to content

Commit

Permalink
Treat parse as primary parsing functions
Browse files Browse the repository at this point in the history
  • Loading branch information
omus committed Jan 31, 2025
1 parent 9e413e2 commit 68a90ec
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 36 deletions.
44 changes: 19 additions & 25 deletions src/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,25 @@ begin
const ISOZonedDateTimeNoMillisecondFormat = DateFormat("yyyy-mm-dd\\THH:MM:SSzzz")
end

Base.parse(::Type{ZonedDateTime}, str::AbstractString) = ZonedDateTime(str)
function Base.parse(::Type{ZonedDateTime}, str::AbstractString)
res = tryparse(ZonedDateTime, str, ISOZonedDateTimeFormat)
return isnothing(res) ? parse(ZonedDateTime, str, ISOZonedDateTimeNoMillisecondFormat) : res
end

function Base.parse(::Type{ZonedDateTime}, str::AbstractString, df::DateFormat)
argtypes = Tuple{Type{<:TimeType},AbstractString,DateFormat}
try
invoke(parse, argtypes, ZonedDateTime, str, df)
catch e
if e isa ArgumentError
rethrow(ArgumentError(
"Unable to parse string \"$str\" using format $df. $(e.msg)"
))
else
rethrow()
end
end
end

function tryparsenext_fixedtz(str, i, len, min_width::Int=1, max_width::Int=0)
i == len && str[i] === 'Z' && return ("Z", i+1)
Expand Down Expand Up @@ -102,30 +120,6 @@ function Dates.format(io::IO, d::DatePart{'Z'}, zdt, locale)
write(io, string(zdt.zone)) # In most cases will be an abbreviation.
end

function ZonedDateTime(str::AbstractString)
res = tryparse(ZonedDateTime, str, ISOZonedDateTimeFormat)
return isnothing(res) ? ZonedDateTime(str, ISOZonedDateTimeNoMillisecondFormat) : res
end

function ZonedDateTime(str::AbstractString, df::DateFormat)
try
parse(ZonedDateTime, str, df)
catch e
if e isa ArgumentError
rethrow(ArgumentError(
"Unable to parse string \"$str\" using format $df. $(e.msg)"
))
else
rethrow()
end
end
end

function ZonedDateTime(str::AbstractString, format::AbstractString; locale::AbstractString="english")
ZonedDateTime(str, DateFormat(format, locale))
end


"""
_parsesub_tzabbr(str, [i, len]) -> Union{Tuple{AbstractString, Integer}, Exception}
Expand Down
9 changes: 9 additions & 0 deletions src/types/zoneddatetime.jl
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,15 @@ function ZonedDateTime(date::Date, args...; kwargs...)
return ZonedDateTime(DateTime(date), args...; kwargs...)
end

# Parsing constructors

ZonedDateTime(str::AbstractString) = parse(ZonedDateTime, str)
ZonedDateTime(str::AbstractString, df::DateFormat) = parse(ZonedDateTime, str, df)

function ZonedDateTime(str::AbstractString, format::AbstractString; locale::AbstractString="english")
return parse(ZonedDateTime, str, DateFormat(format, locale))
end

# Promotion

# Because of the promoting fallback definitions for TimeType, we need a special case for
Expand Down
34 changes: 23 additions & 11 deletions test/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,6 @@ end
ZonedDateTime("2018-11-01-0600", dateformat"yyyy-mm-ddzzzz"),
ZonedDateTime(2018, 11, 1, tz"UTC-06"),
)

# Validate that error message contains the original string and the format used
str = "2018-11-01"
try
ZonedDateTime(str)
catch e
@test e isa ArgumentError
@test occursin(str, e.msg)
@test occursin(string(TimeZones.ISOZonedDateTimeFormat), e.msg) ||
occursin(string(TimeZones.ISOZonedDateTimeNoMillisecondFormat), e.msg)
end
end

@testset "self parseable" begin
Expand All @@ -92,6 +81,29 @@ end
end
end

# Validate that error message contains the original string and the format used
@testset "contextual error" begin
str = "2018-11-01"

try
parse(ZonedDateTime, str)
@test false
catch e
@test e isa ArgumentError
@test occursin(str, e.msg)
@test occursin(string(TimeZones.ISOZonedDateTimeNoMillisecondFormat), e.msg)
end

try
ZonedDateTime(str)
@test false
catch e
@test e isa ArgumentError
@test occursin(str, e.msg)
@test occursin(string(TimeZones.ISOZonedDateTimeNoMillisecondFormat), e.msg)
end
end

@testset "_parsesub_tzabbr" begin
empty_msg = "Time zone abbreviation must start with a letter or the less-than (<) character"
not_closed_msg = "Expected expanded time zone abbreviation end with the greater-than sign (>)"
Expand Down

0 comments on commit 68a90ec

Please sign in to comment.