Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
a9308cbaf3 | |||
f4e392f910 | |||
600747e1ac | |||
08c0962b40 | |||
a537b980e6 | |||
|
dfee8aae33 | ||
|
f831fd6238 | ||
|
8987a4e268 | ||
|
b4804cdb52 |
@ -1,126 +0,0 @@
|
||||
import times, timeutils, unittest
|
||||
|
||||
let dtFormat = "yyyy-MM-dd HH:mm:ss"
|
||||
|
||||
suite "timeutils":
|
||||
test "format TimeInterval":
|
||||
let interval = seconds(70)
|
||||
check:
|
||||
interval.format("ss's'") == "10s"
|
||||
interval.format("mm'm' ss's'") == "01m 10s"
|
||||
interval.format("mm:ss") == "01:10"
|
||||
|
||||
test "TimeInfo difference":
|
||||
var t1 = getLocalTime(getTime())
|
||||
var t2 = t1 + 30.seconds
|
||||
check t2 - t1 == 30.seconds
|
||||
|
||||
t1 = parse("2016-10-10 09:45:00", "yyyy-MM-dd HH:mm:ss")
|
||||
t2 = parse("2016-10-11 09:45:00", "yyyy-MM-dd HH:mm:ss")
|
||||
check t2 - t1 == 1.days
|
||||
|
||||
t2 = parse("2016-10-11 10:00:00", "yyyy-MM-dd HH:mm:ss")
|
||||
check t2 - t1 == (1.days + 15.minutes)
|
||||
|
||||
test "TimeInfo comparisons":
|
||||
let t1 = getLocalTime(getTime())
|
||||
|
||||
check:
|
||||
t1 < t1 + 10.seconds
|
||||
not (t1 + 10.seconds < t1)
|
||||
not (t1 > t1)
|
||||
|
||||
t1 + 10.seconds > t1
|
||||
not (t1 > t1 + 10.seconds)
|
||||
not (t1 < t1)
|
||||
|
||||
t1 + 10.seconds >= t1
|
||||
t1 >= t1
|
||||
not (t1 >= t1 + 10.seconds)
|
||||
|
||||
t1 <= t1 + 10.seconds
|
||||
t1 <= t1
|
||||
not (t1 + 10.seconds <= t1)
|
||||
|
||||
test "TimeInterval comparisons":
|
||||
check:
|
||||
30.seconds > 10.seconds
|
||||
not (10.seconds > 30.seconds)
|
||||
not (10.seconds > 10.seconds)
|
||||
|
||||
10.minutes < 1.hours
|
||||
not (1.hours < 10.minutes)
|
||||
not (1.hours < 1.hours)
|
||||
|
||||
60.seconds >= 1.minutes
|
||||
60.seconds >= 1.minutes
|
||||
not (60.seconds >= 2.minutes)
|
||||
|
||||
60.seconds <= 1.minutes
|
||||
60.seconds <= 2.minutes
|
||||
not (2.minutes <= 60.seconds)
|
||||
|
||||
test "TimeInfo cmp":
|
||||
let t1 = getLocalTime(getTime())
|
||||
|
||||
check cmp(t1, t1) == 0
|
||||
check cmp(t1, t1 + 10.seconds) == -1
|
||||
check cmp(t1 + 10.seconds, t1) == 1
|
||||
|
||||
test "startOfDay":
|
||||
let t1 = fixedParse("13:42:19", "HH:mm:ss")
|
||||
let t2 = fixedParse("2015-12-31 23:59:59", dtFormat)
|
||||
|
||||
check:
|
||||
fixedParse("00:00:00", "HH:mm:ss") == startOfDay(t1)
|
||||
|
||||
#check fixedParse("2015-12-31 00:00:00", dtFormat) == startOfDay(t2)
|
||||
|
||||
startOfDay(startOfDay(t1)) == startOfDay(t1)
|
||||
|
||||
test "startOfWeek":
|
||||
let t1 = fixedParse("2015-12-31 23:59:59", dtFormat)
|
||||
let t2 = fixedParse("2015-12-26 23:59:59", dtFormat)
|
||||
let t3 = fixedParse("2016-01-01 23:59:59", dtFormat)
|
||||
|
||||
# Not parsing the start of the day in order to work around the bug
|
||||
# mentioned above.
|
||||
check:
|
||||
# Start of week = Monday
|
||||
startOfWeek(t1) == startOfDay(getLocalTime(toTime(fixedParse("2015-12-28 12:01:00", dtFormat))))
|
||||
startOfWeek(t1).weekday == dMon
|
||||
startOfWeek(startOfWeek(t1)) == startOfWeek(t1)
|
||||
|
||||
startOfWeek(t2) == startOfDay(fixedParse("2015-12-21 01:00:00", dtFormat))
|
||||
startOfWeek(t3) == startOfDay(fixedParse("2015-12-28 01:00:00", dtFormat))
|
||||
|
||||
# Start of week = Sunday
|
||||
startOfWeek(t1, dSun) == startOfDay(fixedParse("2015-12-27 01:00:00", dtFormat))
|
||||
startOfWeek(t1, dSun).weekday == dSun
|
||||
startOfWeek(startOfWeek(t1, dSun), dSun) == startOfWeek(t1, dSun)
|
||||
|
||||
startOfWeek(t2, dSun) == startOfDay(fixedParse("2015-12-20 01:00:00", dtFormat))
|
||||
startOfWeek(t3, dSun) == startOfDay(fixedParse("2015-12-27 01:00:00", dtFormat))
|
||||
|
||||
test "times.parse is still broken":
|
||||
let t1 = parse("2015-12-01 12:00:00", dtFormat)
|
||||
let t2 = parse("2015-06-01 12:00:00", dtFormat)
|
||||
|
||||
# parse is broken in that is uses the DST setting of the current time when
|
||||
# parsing dates when it should figure out the DST time for that date. So
|
||||
# depending on if you are currently in DST or not, one of the above dates
|
||||
# will not parse correctly. We want to check that one of those fails to
|
||||
# parse correctly. When they both parse correctly, the times.parse bug has
|
||||
# been fixed and fixedParse is no longer necessary.
|
||||
|
||||
# This test works because passing the time through getLocalTime(toTime())
|
||||
# correctly the DST setting for the time.
|
||||
check t1 != getLocalTime(toTime(t1)) or t2 != getLocalTime(toTime(t2))
|
||||
|
||||
test "fixedParse":
|
||||
let t1 = fixedParse("2015-12-01 12:00:00", dtFormat)
|
||||
let t2 = fixedParse("2015-06-01 12:00:00", dtFormat)
|
||||
|
||||
check: # test both in DST and out of DST
|
||||
t1 == getLocalTime(toTime(t1))
|
||||
t2 == getLocalTime(toTime(t2))
|
115
tests/ttimeutils.nim
Normal file
115
tests/ttimeutils.nim
Normal file
@ -0,0 +1,115 @@
|
||||
import times, unittest
|
||||
import "../timeutils"
|
||||
|
||||
let dtFormat = "yyyy-MM-dd HH:mm:ss"
|
||||
|
||||
suite "timeutils":
|
||||
test "format TimeInterval":
|
||||
let interval = seconds(70)
|
||||
check:
|
||||
interval.format("ss's'") == "10s"
|
||||
interval.format("mm'm' ss's'") == "01m 10s"
|
||||
interval.format("mm:ss") == "01:10"
|
||||
|
||||
test "DateTime difference":
|
||||
var t1 = getTime().local
|
||||
var t2 = t1 + 30.seconds
|
||||
check t2 - t1 == initDuration(seconds = 30)
|
||||
|
||||
t1 = parse("2016-10-10 09:45:00", "yyyy-MM-dd HH:mm:ss")
|
||||
t2 = parse("2016-10-11 09:45:00", "yyyy-MM-dd HH:mm:ss")
|
||||
check t2 - t1 == initDuration(seconds = 24 * 60 * 60)
|
||||
|
||||
t2 = parse("2016-10-11 10:00:00", "yyyy-MM-dd HH:mm:ss")
|
||||
check t2 - t1 == initDuration(seconds = (24 * 60 + 15) * 60)
|
||||
|
||||
test "DateTime comparisons":
|
||||
let t1 = getTime().local
|
||||
|
||||
check:
|
||||
not (t1 < t1)
|
||||
t1 < t1 + 10.seconds
|
||||
not (t1 + 10.seconds < t1)
|
||||
|
||||
t1 <= t1
|
||||
t1 <= t1 + 10.seconds
|
||||
not (t1 + 10.seconds <= t1)
|
||||
|
||||
t1.between(t1 - 10.seconds, t1 + 10.seconds)
|
||||
t1.between(t1, t1 + 10.seconds) # start is inclusive
|
||||
not t1.between(t1 - 10.seconds, t1) # end is exclusive
|
||||
|
||||
test "TimeInterval comparisons":
|
||||
check:
|
||||
timeutils.`<`(10.minutes, 1.hours)
|
||||
not timeutils.`<`(1.hours, 10.minutes)
|
||||
not timeutils.`<`(1.hours, 1.hours)
|
||||
|
||||
timeutils.`<=`(60.seconds, 1.minutes)
|
||||
timeutils.`<=`(60.seconds, 2.minutes)
|
||||
not timeutils.`<=`(2.minutes, 60.seconds)
|
||||
|
||||
test "DateTime cmp":
|
||||
let t1 = getTime().local
|
||||
|
||||
check cmp(t1, t1) == 0
|
||||
check cmp(t1, t1 + 10.seconds) == -1
|
||||
check cmp(t1 + 10.seconds, t1) == 1
|
||||
|
||||
test "startOfDay":
|
||||
let t1 = parse("13:42:19", "HH:mm:ss")
|
||||
let t2 = parse("2015-12-31 23:59:59", dtFormat)
|
||||
|
||||
check:
|
||||
parse("00:00:00", "HH:mm:ss") == startOfDay(t1)
|
||||
|
||||
#check parse("2015-12-31 00:00:00", dtFormat) == startOfDay(t2)
|
||||
|
||||
startOfDay(startOfDay(t1)) == startOfDay(t1)
|
||||
|
||||
test "startOfWeek":
|
||||
let t1 = parse("2015-12-31 23:59:59", dtFormat)
|
||||
let t2 = parse("2015-12-26 23:59:59", dtFormat)
|
||||
let t3 = parse("2016-01-01 23:59:59", dtFormat)
|
||||
|
||||
# Not parsing the start of the day in order to work around the bug
|
||||
# mentioned above.
|
||||
check:
|
||||
# Start of week = Monday
|
||||
startOfWeek(t1) == startOfDay(toTime(parse("2015-12-28 12:01:00", dtFormat)).local)
|
||||
startOfWeek(t1).weekday == dMon
|
||||
startOfWeek(startOfWeek(t1)) == startOfWeek(t1)
|
||||
|
||||
startOfWeek(t2) == startOfDay(parse("2015-12-21 01:00:00", dtFormat))
|
||||
startOfWeek(t3) == startOfDay(parse("2015-12-28 01:00:00", dtFormat))
|
||||
|
||||
# Start of week = Sunday
|
||||
startOfWeek(t1, dSun) == startOfDay(parse("2015-12-27 01:00:00", dtFormat))
|
||||
startOfWeek(t1, dSun).weekday == dSun
|
||||
startOfWeek(startOfWeek(t1, dSun), dSun) == startOfWeek(t1, dSun)
|
||||
|
||||
startOfWeek(t2, dSun) == startOfDay(parse("2015-12-20 01:00:00", dtFormat))
|
||||
startOfWeek(t3, dSun) == startOfDay(parse("2015-12-27 01:00:00", dtFormat))
|
||||
|
||||
test "fixedParse":
|
||||
let t1 = fixedParse("2015-12-01 12:00:00", dtFormat)
|
||||
let t2 = fixedParse("2015-06-01 12:00:00", dtFormat)
|
||||
|
||||
check: # test both in DST and out of DST
|
||||
t1 == toTime(t1).local
|
||||
t2 == toTime(t2).local
|
||||
|
||||
test "parseIso8601":
|
||||
let t1 = parseIso8601("2018-01-01T12:00:00-05:00")
|
||||
let t2 = parseIso8601("2018-01-01T17:00:00Z")
|
||||
|
||||
check:
|
||||
t1 == t2
|
||||
|
||||
test "formatIso8601":
|
||||
let t1 = parseIso8601("2018-01-01T12:00:00-05:00")
|
||||
let t2 = parseIso8601("2018-01-01T17:00:00Z")
|
||||
|
||||
check:
|
||||
t1 == parseIso8601(formatIso8601(t1))
|
||||
t2 == parseIso8601(formatIso8601(t2))
|
@ -1,60 +1,74 @@
|
||||
import times
|
||||
|
||||
const zeroTime = fromSeconds(0)
|
||||
const zeroTime = fromUnix(0)
|
||||
const ISO_8601_FORMATS = @[
|
||||
"yyyy-MM-dd",
|
||||
"yyyy-MM-dd'T'HH:mm:ssz",
|
||||
"yyyy-MM-dd'T'HH:mm:sszzz",
|
||||
"yyyy-MM-dd'T'HH:mm:ss'.'fffzzz",
|
||||
"yyyy-MM-dd HH:mm:ssz",
|
||||
"yyyy-MM-dd HH:mm:sszzz",
|
||||
"yyyy-MM-dd HH:mm:ss'.'fffzzz"
|
||||
]
|
||||
|
||||
proc format*(ti: TimeInterval, fmt: string): string =
|
||||
let info = getGMTime(fromSeconds(0) + ti)
|
||||
let info = (zeroTime + ti).utc
|
||||
return info.format(fmt)
|
||||
|
||||
proc `-`*(a, b: TimeInfo): TimeInterval =
|
||||
return seconds(cast[int](a.toTime - b.toTime))
|
||||
|
||||
proc `>`*(a, b: TimeInfo): bool =
|
||||
return a.toTime > b.toTime
|
||||
|
||||
proc `<`*(a, b: TimeInfo): bool =
|
||||
return a.toTime < b.toTime
|
||||
|
||||
proc `>=`*(a, b: TimeInfo): bool =
|
||||
return a.toTime >= b.toTime
|
||||
|
||||
proc `<=`*(a, b: TimeInfo): bool =
|
||||
return a.toTime <= b.toTime
|
||||
|
||||
proc `>`*(a, b: TimeInterval): bool =
|
||||
return (zeroTime + a) > (zeroTime + b)
|
||||
proc format*(d: Duration, fmt: string): string =
|
||||
let info = (fromUnix(0) + d).utc
|
||||
return info.format(fmt)
|
||||
|
||||
proc `<`*(a, b: TimeInterval): bool =
|
||||
return (zeroTime + a) < (zeroTime + b)
|
||||
|
||||
proc `>=`*(a, b: TimeInterval): bool =
|
||||
return (zeroTime + a) >= (zeroTime + b)
|
||||
|
||||
proc `<=`*(a, b: TimeInterval): bool =
|
||||
return (zeroTime + a) <= (zeroTime + b)
|
||||
|
||||
proc cmp*(a, b: TimeInfo): int =
|
||||
proc between*(a, s, e: DateTime): bool =
|
||||
return times.`<=`(s, a) and times.`<`(a, e)
|
||||
|
||||
proc cmp*(a, b: DateTime): int =
|
||||
if b == a: return 0
|
||||
elif a > b: return 1
|
||||
else: return -1
|
||||
elif times.`<`(a, b): return -1
|
||||
else: return 1
|
||||
|
||||
proc startOfDay*(ti: TimeInfo): TimeInfo =
|
||||
result = ti
|
||||
result.hour = 0
|
||||
result.minute = 0
|
||||
result.second = 0
|
||||
proc startOfDay*(dt: DateTime): DateTime =
|
||||
result = initDateTime(
|
||||
dt.monthday,
|
||||
dt.month,
|
||||
dt.year,
|
||||
0, 0, 0, 0, # hour, minute, second, nanosecond
|
||||
dt.timezone)
|
||||
|
||||
proc startOfWeek*(ti: TimeInfo, startDay = dMon): TimeInfo =
|
||||
proc trimNanoSec*(dt: DateTime): DateTime =
|
||||
result = dt
|
||||
result = initDateTime(
|
||||
dt.monthday,
|
||||
dt.month,
|
||||
dt.year,
|
||||
dt.hour,
|
||||
dt.minute,
|
||||
dt.second,
|
||||
0,
|
||||
dt.timezone)
|
||||
|
||||
proc startOfWeek*(ti: DateTime, startDay = dMon): DateTime =
|
||||
var diff = (ti.weekday.ord - startDay.ord)
|
||||
if diff < 0: diff += 7
|
||||
return (ti - diff.days).startOfDay
|
||||
|
||||
proc parseIso8601*(val: string): DateTime =
|
||||
var errString = ""
|
||||
for df in ISO_8601_FORMATS:
|
||||
try: return val.parse(df)
|
||||
except: errString &= "\n" & getCurrentExceptionMsg()
|
||||
raise newException(Exception, "Could not parse date. Tried:" & errString)
|
||||
|
||||
proc formatIso8601*(d: DateTime): string =
|
||||
return d.format(ISO_8601_FORMATS[2])
|
||||
|
||||
# This is a workaround needed due a bug in Nim's times.parse procedure.
|
||||
# see: https://github.com/nim-lang/Nim/issues/4922
|
||||
proc fixedParse*(value, format: string): TimeInfo =
|
||||
let firstParsed = parse(value, format)
|
||||
let rectified = getLocalTime(toTime(firstParsed))
|
||||
if firstParsed.isDST and not rectified.isDST: return rectified + 1.hours
|
||||
elif not firstParsed.isDST and rectified.isDST: return rectified - 1.hours
|
||||
else: return rectified
|
||||
|
||||
template fixedParse*(value, format: string): DateTime {.deprecated.} =
|
||||
parse(value, format)
|
||||
|
@ -1,11 +1,10 @@
|
||||
# Package
|
||||
|
||||
version = "0.2.0"
|
||||
version = "0.5.4"
|
||||
author = "Jonathan Bernard"
|
||||
description = "Utility methods to fill in the lacking time support in Nim\'s stdlib. This is holding me over until I can write a proper time module for the stdlib and submit it."
|
||||
description = "Utility methods to fill in the lacking time support in Nim\'s stdlib."
|
||||
license = "BSD3"
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 0.15.0"
|
||||
|
||||
requires "nim >= 1.3.1"
|
||||
|
Loading…
x
Reference in New Issue
Block a user