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

fix: datetime tryparse (#265) #267

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 43 additions & 17 deletions src/parsing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,38 @@ Base.convert(::Type{String}, pqv::PQValue) = String(pqv)
Base.length(pqv::PQValue) = length(string_view(pqv))
Base.lastindex(pqv::PQValue) = lastindex(string_view(pqv))

# Julia bug override, see https://github.com/iamed2/LibPQ.jl/issues/265
# and https://github.com/iamed2/LibPQ.jl/pull/248 for more details
function _tryparse(::Type{T}, str, timeformat) where {T}
@static if v"1.6.6" <= VERSION < v"1.7.0" || VERSION > v"1.7.2"
return tryparse(T, str, timeformat)
else
try
return tryparse(T, str, timeformat)
catch err
if !(err isa InexactError)
rethrow(err)
end
end
return nothing
end
end

function _tryparse(::Type{T}, str) where {T}
@static if v"1.6.6" <= VERSION < v"1.7.0" || VERSION > v"1.7.2"
return tryparse(T, str)
else
try
return tryparse(T, str)
catch err
if !(err isa InexactError)
rethrow(err)
end
end
return nothing
end
end

# Fallback, because Base requires string iteration state to be indices into the string.
# In an ideal world, PQValue would be an AbstractString and this particular method would
# not be necessary.
Expand Down Expand Up @@ -259,9 +291,10 @@ function pqparse(::Type{DateTime}, str::AbstractString)
parsed = _tryparse_datetime_inf(DateTime, str)
isnothing(parsed) || return parsed

parsed = tryparse(DateTime, str, TIMESTAMP_FORMAT)
parsed = _tryparse(DateTime, str, TIMESTAMP_FORMAT)
isnothing(parsed) || return parsed

# If there's an error we want to see it here
return parse(DateTime, _trunc_seconds(str), TIMESTAMP_FORMAT)
end

Expand All @@ -279,10 +312,11 @@ function pqparse(::Type{ZonedDateTime}, str::AbstractString)
isnothing(parsed) || return parsed

for fmt in TIMESTAMPTZ_FORMATS[1:(end - 1)]
parsed = tryparse(ZonedDateTime, str, fmt)
parsed = _tryparse(ZonedDateTime, str, fmt)
isnothing(parsed) || return parsed
end

# If there's an error we want to see it here
return parse(ZonedDateTime, _trunc_seconds(str), TIMESTAMPTZ_FORMATS[end])
end

Expand All @@ -294,9 +328,10 @@ function pqparse(::Type{UTCDateTime}, str::AbstractString)
# which is the default
str = replace(str, "+00" => "")

parsed = tryparse(UTCDateTime, str, TIMESTAMP_FORMAT)
parsed = _tryparse(UTCDateTime, str, TIMESTAMP_FORMAT)
isnothing(parsed) || return parsed

# If there's an error we want to see it here
return parse(UTCDateTime, _trunc_seconds(str), TIMESTAMP_FORMAT)
end

Expand All @@ -315,20 +350,11 @@ end

_DEFAULT_TYPE_MAP[:time] = Time
function pqparse(::Type{Time}, str::AbstractString)
@static if v"1.6.6" <= VERSION < v"1.7.0" || VERSION > v"1.7.2"
result = tryparse(Time, str)
# If there's an error we want to see it here
return isnothing(result) ? parse(Time, _trunc_seconds(str)) : result
else
try
return parse(Time, str)
catch err
if !(err isa InexactError)
rethrow(err)
end
end
return parse(Time, _trunc_seconds(str))
end
parsed = _tryparse(Time, str)
isnothing(parsed) || return parsed

# If there's an error we want to see it here
return parse(Time, _trunc_seconds(str))
end

# InfExtendedTime support for Dates.TimeType
Expand Down