Skip to content

Commit b82a753

Browse files
committed
Revise all datetime pqparse methods to be more consistent.
1 parent 6a5b9f8 commit b82a753

File tree

1 file changed

+30
-25
lines changed

1 file changed

+30
-25
lines changed

src/parsing.jl

+30-25
Original file line numberDiff line numberDiff line change
@@ -238,21 +238,31 @@ end
238238
# see https://github.com/invenia/LibPQ.jl/issues/33
239239
_trunc_seconds(str) = replace(str, r"(\.[\d]{3})\d+" => s"\g<1>")
240240

241-
_DEFAULT_TYPE_MAP[:timestamp] = DateTime
242-
const TIMESTAMP_FORMAT = dateformat"y-m-d HH:MM:SS.s" # .s is optional here
243-
function pqparse(::Type{DateTime}, str::AbstractString)
241+
# Utility function for handling "infinity" strings for datetime types to reduce duplication
242+
function _tryparse_datetime_inf(
243+
typ::Type{T}, str, f=typ
244+
)::Union{T, Nothing} where T <: Dates.AbstractDateTime
244245
if str == "infinity"
245246
depwarn_timetype_inf()
246-
return typemax(DateTime)
247+
return f(typemax(DateTime))
247248
elseif str == "-infinity"
248249
depwarn_timetype_inf()
249-
return typemin(DateTime)
250+
return f(typemin(DateTime))
250251
end
251252

252-
# Cut off digits after the third after the decimal point,
253-
# since DateTime in Julia currently handles only milliseconds, see Issue #33
254-
str = replace(str, r"(\.[\d]{3})\d+" => s"\g<1>")
255-
return parse(DateTime, str, TIMESTAMP_FORMAT)
253+
return nothing
254+
end
255+
256+
_DEFAULT_TYPE_MAP[:timestamp] = DateTime
257+
const TIMESTAMP_FORMAT = dateformat"y-m-d HH:MM:SS.s" # .s is optional here
258+
function pqparse(::Type{DateTime}, str::AbstractString)
259+
parsed = _tryparse_datetime_inf(DateTime, str)
260+
isnothing(parsed) || return parsed
261+
262+
parsed = tryparse(DateTime, str, TIMESTAMP_FORMAT)
263+
isnothing(parsed) || return parsed
264+
265+
return parse(DateTime, _trunc_seconds(str), TIMESTAMP_FORMAT)
256266
end
257267

258268
# ISO, YMD
@@ -265,34 +275,29 @@ const TIMESTAMPTZ_FORMATS = (
265275
)
266276

267277
function pqparse(::Type{ZonedDateTime}, str::AbstractString)
268-
if str == "infinity"
269-
depwarn_timetype_inf()
270-
return ZonedDateTime(typemax(DateTime), tz"UTC")
271-
elseif str == "-infinity"
272-
depwarn_timetype_inf()
273-
return ZonedDateTime(typemin(DateTime), tz"UTC")
274-
end
278+
parsed = _tryparse_datetime_inf(ZonedDateTime, str, Base.Fix2(ZonedDateTime, tz"UTC"))
279+
isnothing(parsed) || return parsed
275280

276281
for fmt in TIMESTAMPTZ_FORMATS[1:(end - 1)]
277282
parsed = tryparse(ZonedDateTime, str, fmt)
278-
parsed !== nothing && return parsed
283+
isnothing(parsed) || return parsed
279284
end
280285

281286
return parse(ZonedDateTime, _trunc_seconds(str), TIMESTAMPTZ_FORMATS[end])
282287
end
283288

284289
function pqparse(::Type{UTCDateTime}, str::AbstractString)
285-
if str == "infinity"
286-
depwarn_timetype_inf()
287-
return UTCDateTime(typemax(DateTime))
288-
elseif str == "-infinity"
289-
depwarn_timetype_inf()
290-
return UTCDateTime(typemin(DateTime))
291-
end
290+
parsed = _tryparse_datetime_inf(UTCDateTime, str)
291+
isnothing(parsed) || return parsed
292292

293293
# Postgres should always give us strings ending with +00 if our timezone is set to UTC
294294
# which is the default
295-
return parse(UTCDateTime, _trunc_seconds(replace(str, "+00" => "")), TIMESTAMP_FORMAT)
295+
str = replace(str, "+00" => "")
296+
297+
parsed = tryparse(UTCDateTime, str, TIMESTAMP_FORMAT)
298+
isnothing(parsed) || return parsed
299+
300+
return parse(UTCDateTime, _trunc_seconds(str), TIMESTAMP_FORMAT)
296301
end
297302

298303
_DEFAULT_TYPE_MAP[:date] = Date

0 commit comments

Comments
 (0)