Fix support for PostgreSQL timestamp fields.
PostgreSQL uses a format similar to IS8601 but allows values expressed with tenths or hundreths of seconds rather than just milliseconds. `2020-01-01 12:34:98.3+00` as opposed to `2020-01-01 12:34:98.300+00`, for example. The `times` module in the Nim stdlib supports only milliseconds with exactly three digits. To bridge this gap we detect the two unsupported cases and pad the fractional seconds out to millisecond precision.
This commit is contained in:
parent
61e06842af
commit
1f57e0dccc
@ -1,14 +1,16 @@
|
||||
import json, macros, options, sequtils, strutils, times, timeutils, unicode,
|
||||
uuids
|
||||
|
||||
import nre except toSeq
|
||||
|
||||
const UNDERSCORE_RUNE = "_".toRunes[0]
|
||||
const PG_TIMESTAMP_FORMATS = [
|
||||
"yyyy-MM-dd HH:mm:sszz",
|
||||
"yyyy-MM-dd HH:mm:ss'.'fzz",
|
||||
"yyyy-MM-dd HH:mm:ss'.'ffzz",
|
||||
"yyyy-MM-dd HH:mm:ss'.'fffzz"
|
||||
]
|
||||
|
||||
var PG_PARTIAL_FORMAT_REGEX = re"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.)(\d{1,3})(\S+)?"
|
||||
|
||||
type
|
||||
MutateClauses* = object
|
||||
columns*: seq[string]
|
||||
@ -69,9 +71,27 @@ type DbArrayParseState = enum
|
||||
|
||||
proc parsePGDatetime*(val: string): DateTime =
|
||||
var errStr = ""
|
||||
|
||||
# Try to parse directly using known format strings.
|
||||
for df in PG_TIMESTAMP_FORMATS:
|
||||
try: return val.parse(df)
|
||||
except: errStr &= "\n" & getCurrentExceptionMsg()
|
||||
except: errStr &= "\n\t" & getCurrentExceptionMsg()
|
||||
|
||||
# PostgreSQL will truncate any trailing 0's in the millisecond value leading
|
||||
# to values like `2020-01-01 16:42.3+00`. This cannot currently be parsed by
|
||||
# the standard times format as it expects exactly three digits for
|
||||
# millisecond values. So we have to detect this and pad out the millisecond
|
||||
# value to 3 digits.
|
||||
let match = val.match(PG_PARTIAL_FORMAT_REGEX)
|
||||
if match.isSome:
|
||||
let c = match.get.captures
|
||||
try:
|
||||
let corrected = c[0] & alignLeft(c[1], 3, '0') & c[2]
|
||||
return corrected.parse(PG_TIMESTAMP_FORMATS[1])
|
||||
except:
|
||||
errStr &= "\n\t" & PG_TIMESTAMP_FORMATS[1] &
|
||||
" after padding out milliseconds to full 3-digits"
|
||||
|
||||
raise newException(ValueError, "Cannot parse PG date. Tried:" & errStr)
|
||||
|
||||
proc parseDbArray*(val: string): seq[string] =
|
||||
|
Loading…
x
Reference in New Issue
Block a user