Date types default to date-time as specified.

- `parseDateOrDateTime attempts to parse times starting from the most
  specific (date and time) to least specific.
- `set` and `add` functions allow adding multiple content items at once
  using varargs.
This commit is contained in:
Jonathan Bernard 2023-04-15 07:03:24 -05:00
parent 419d794c68
commit c4717b4b00
2 changed files with 37 additions and 26 deletions

View File

@ -12,16 +12,16 @@ const DATE_TIME_FMTS = [
"yyyy-MM-dd'T'HH:mm:ss'.'fffzzz", "yyyy-MM-dd'T'HH:mm:ss'.'fffzzz",
] ]
const ALL_FMTS = DATE_FMTS.toSeq & DATE_TIME_FMTS.toSeq const ALL_FMTS = DATE_TIME_FMTS.toSeq & DATE_FMTS.toSeq
proc parseDateTimeStr( proc parseDateTimeStr(
dateStr: string, dateStr: string,
dateFmts: openarray[string] dateFmts: openarray[string]
): DateTime {.inline.} = ): DateTime {.inline, raises:[ValueError].} =
for fmt in dateFmts: for fmt in dateFmts:
try: result = parse(dateStr, fmt) try: result = parse(dateStr, fmt)
except: discard except ValueError: discard
if not result.isInitialized: if not result.isInitialized:
raise newException(ValueError, "cannot parse date: " & dateStr ) raise newException(ValueError, "cannot parse date: " & dateStr )

View File

@ -523,8 +523,8 @@ func newVC3_Sound*(
func newVC3_UID*(value: string, group = none[string]()): VC3_UID = func newVC3_UID*(value: string, group = none[string]()): VC3_UID =
return VC3_UID(name: "UID", value: value, group: group) return VC3_UID(name: "UID", value: value, group: group)
func newVC3_URL*(value: string, group = none[string]()): VC3_Url = func newVC3_URL*(value: string, group = none[string]()): VC3_URL =
return VC3_Url(name: "URL", value: value, group: group) return VC3_URL(name: "URL", value: value, group: group)
func newVC3_Version*(group = none[string]()): VC3_Version = func newVC3_Version*(group = none[string]()): VC3_Version =
return VC3_Version(name: "VERSION", value: "3.0", group: group) return VC3_Version(name: "VERSION", value: "3.0", group: group)
@ -652,11 +652,11 @@ func sortstring*(vc3: VCard3): Option[VC3_SortString] = vc3.content.sortstring
func sound*(c: VC3_ContentList): seq[VC3_Sound] = findAll[VC3_Sound](c) func sound*(c: VC3_ContentList): seq[VC3_Sound] = findAll[VC3_Sound](c)
func sound*(vc3: VCard3): seq[VC3_Sound] = vc3.content.sound func sound*(vc3: VCard3): seq[VC3_Sound] = vc3.content.sound
func uid*(c: VC3_ContentList): Option[VC3_Uid] = findFirst[VC3_Uid](c) func uid*(c: VC3_ContentList): Option[VC3_UID] = findFirst[VC3_UID](c)
func uid*(vc3: VCard3): Option[VC3_Uid] = vc3.content.uid func uid*(vc3: VCard3): Option[VC3_UID] = vc3.content.uid
func url*(c: VC3_ContentList): Option[VC3_Url] = findFirst[VC3_Url](c) func url*(c: VC3_ContentList): Option[VC3_URL] = findFirst[VC3_URL](c)
func url*(vc3: VCard3): Option[VC3_Url] = vc3.content.url func url*(vc3: VCard3): Option[VC3_URL] = vc3.content.url
func version*(c: VC3_ContentList): VC3_Version = func version*(c: VC3_ContentList): VC3_Version =
let found = findFirst[VC3_Version](c) let found = findFirst[VC3_Version](c)
@ -680,26 +680,30 @@ func xTypes*(vc3: VCard3): seq[VC3_XType] = vc3.content.xTypes
# Setters # Setters
# ============================================================================= # =============================================================================
func set*[T](vc3: var VCard3, newContent: var T): void = func set*[T](vc3: var VCard3, content: varargs[T]): void =
let existingIdx = vc3.content.indexOfIt(it of T) for c in content:
if existingIdx < 0: var nc = c
newContent.contentId = vc3.takeContentId let existingIdx = vc3.content.indexOfIt(it of T)
vc3.content.add(newContent) if existingIdx < 0:
else: nc.contentId = vc3.takeContentId
newContent.contentId = vc3.content[existingIdx].contentId vc3.content.add(nc)
vc3.content[existingIdx] = newContent else:
nc.contentId = vc3.content[existingIdx].contentId
vc3.content[existingIdx] = nc
func set*[T](vc3: VCard3, newContent: var T): VCard3 = func set*[T](vc3: VCard3, content: varargs[T]): VCard3 =
result = vc3 result = vc3
result.set(newContent) result.set(content)
func add*[T](vc3: var VCard3, newContent: T): void = func add*[T](vc3: var VCard3, content: varargs[T]): void =
newContent.contentId = vc3.takeContentId for c in content:
vc3.content.add(newContent) var nc = c
nc.contentId = vc3.takeContentId
vc3.content.add(nc)
func add*[T](vc3: VCard3, newContent: T): VCard3 = func add*[T](vc3: VCard3, content: varargs[T]): VCard3 =
result = vc3 result = vc3
result.add(newContent) result.add(content)
func updateOrAdd*[T](vc3: var VCard3, content: seq[T]): VCard3 = func updateOrAdd*[T](vc3: var VCard3, content: seq[T]): VCard3 =
for c in content: for c in content:
@ -707,6 +711,13 @@ func updateOrAdd*[T](vc3: var VCard3, content: seq[T]): VCard3 =
if existingIdx < 0: vc3.content.add(c) if existingIdx < 0: vc3.content.add(c)
else: c.content[existingIdx] = c else: c.content[existingIdx] = c
func updateOrAdd*[T](vc3: VCard3, content: seq[T]): VCard3 =
result = vc3
for c in content:
let existingIdx = result.content.indexOfIt(it.contentId == c.contentId)
if existingIdx < 0: result.content.add(c)
else: c.content[existingIdx] = c
# TODO: simplify with macros? # TODO: simplify with macros?
# macro generateImmutableVersion()... # macro generateImmutableVersion()...
# generateImmutableVersion("set", "add", "setName", "addSource") # generateImmutableVersion("set", "add", "setName", "addSource")
@ -1781,10 +1792,10 @@ proc parseContentLines(p: var VC3Parser): seq[VC3_Content] =
isInline = params.existsWithValue("ENCODING", "B"))) isInline = params.existsWithValue("ENCODING", "B")))
of $cnUid: of $cnUid:
result.add(newVC3_Uid(group = group, value = p.readValue)) result.add(newVC3_UID(group = group, value = p.readValue))
of $cnUrl: of $cnUrl:
result.add(newVC3_Url(group = group, value = p.readValue)) result.add(newVC3_URL(group = group, value = p.readValue))
of $cnVersion: of $cnVersion:
p.expect("3.0") p.expect("3.0")