diff options
-rw-r--r-- | lib/pure/times.nim | 10 | ||||
-rw-r--r-- | tests/js/ttimes.nim | 43 | ||||
-rw-r--r-- | tests/stdlib/ttimes.nim | 173 |
3 files changed, 75 insertions, 151 deletions
diff --git a/lib/pure/times.nim b/lib/pure/times.nim index cbf3e6413..6251c70d9 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -423,18 +423,14 @@ proc toUnix*(t: Time): int64 {.benign, tags: [], raises: [], noSideEffect.} = ## Convert ``t`` to a unix timestamp (seconds since ``1970-01-01T00:00:00Z``). runnableExamples: doAssert fromUnix(0).toUnix() == 0 - t.seconds proc fromWinTime*(win: int64): Time = ## Convert a Windows file time (100-nanosecond intervals since ``1601-01-01T00:00:00Z``) ## to a ``Time``. - let hnsecsSinceEpoch = (win - epochDiff) - var seconds = hnsecsSinceEpoch div rateDiff - var nanos = ((hnsecsSinceEpoch mod rateDiff) * 100).int - if nanos < 0: - nanos += convert(Seconds, Nanoseconds, 1) - seconds -= 1 + const hnsecsPerSec = convert(Seconds, Nanoseconds, 1) div 100 + let nanos = floorMod(win, hnsecsPerSec) * 100 + let seconds = floorDiv(win - epochDiff, hnsecsPerSec) result = initTime(seconds, nanos) proc toWinTime*(t: Time): int64 = diff --git a/tests/js/ttimes.nim b/tests/js/ttimes.nim deleted file mode 100644 index ad7fdd211..000000000 --- a/tests/js/ttimes.nim +++ /dev/null @@ -1,43 +0,0 @@ -discard """ - action: run -""" - -import times - -# $ date --date='@2147483647' -# Tue 19 Jan 03:14:07 GMT 2038 - -block yeardayTest: - doAssert fromUnix(2147483647).utc.yearday == 18 - -block localTime: - var local = now() - let utc = local.utc - doAssert local.toTime == utc.toTime - -let a = fromUnix(1_000_000_000) -let b = fromUnix(1_500_000_000) -doAssert b - a == initDuration(seconds = 500_000_000) - -# Because we can't change the timezone JS uses, we define a simple static timezone for testing. - -proc zonedTimeFromTime(time: Time): ZonedTime = - result.utcOffset = -7200 - result.isDst = false - result.time = time - -proc zonedTimeFromAdjTime(adjTime: Time): ZonedTIme = - result.utcOffset = -7200 - result.isDst = false - result.time = adjTime + initDuration(seconds = -7200) - -let utcPlus2 = newTimezone("", zonedTimeFromTime, zonedTimeFromAdjTime) - -block timezoneTests: - let dt = initDateTime(01, mJan, 2017, 12, 00, 00, utcPlus2) - doAssert $dt == "2017-01-01T12:00:00+02:00" - doAssert $dt.utc == "2017-01-01T10:00:00Z" - doAssert $dt.utc.inZone(utcPlus2) == $dt - -doAssert $initDateTime(01, mJan, 1911, 12, 00, 00, utc()) == "1911-01-01T12:00:00Z" -doAssert $initDateTime(01, mJan, 0023, 12, 00, 00, utc()) == "0023-01-01T12:00:00Z" \ No newline at end of file diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim index e2fdf2a1f..fcafe933a 100644 --- a/tests/stdlib/ttimes.nim +++ b/tests/stdlib/ttimes.nim @@ -1,12 +1,20 @@ -# test the new time module discard """ file: "ttimes.nim" + target: "c js" output: '''[Suite] ttimes ''' """ -import - times, os, strutils, unittest +import times, strutils, unittest + +when not defined(js): + import os + +# Normally testament configures unittest with environment variables, +# but that doesn't work for the JS target. So instead we must set the correct +# settings here. +addOutputFormatter( + newConsoleOutputFormatter(PRINT_FAILURES, colorOutput = false)) proc staticTz(hours, minutes, seconds: int = 0): Timezone {.noSideEffect.} = let offset = hours * 3600 + minutes * 60 + seconds @@ -23,99 +31,12 @@ proc staticTz(hours, minutes, seconds: int = 0): Timezone {.noSideEffect.} = newTimezone("", zonedTimeFromTime, zonedTImeFromAdjTime) -# $ date --date='@2147483647' -# Tue 19 Jan 03:14:07 GMT 2038 - -proc checkFormat(t: DateTime, format, expected: string) = - let actual = t.format(format) - if actual != expected: - echo "Formatting failure!" - echo "expected: ", expected - echo "actual : ", actual - doAssert false - -let t2 = fromUnix(160070789).utc() # Mon 27 Jan 16:06:29 GMT 1975 -t2.checkFormat("d dd ddd dddd h hh H HH m mm M MM MMM MMMM s" & - " ss t tt y yy yyy yyyy yyyyy z zz zzz", - "27 27 Mon Monday 4 04 16 16 6 06 1 01 Jan January 29 29 P PM 5 75 975 1975 01975 Z Z Z") - -var t4 = fromUnix(876124714).utc # Mon 6 Oct 08:58:34 BST 1997 -t4.checkFormat("M MM MMM MMMM", "10 10 Oct October") - -# Interval tests -(t4 - initTimeInterval(years = 2)).checkFormat("yyyy", "1995") -(t4 - initTimeInterval(years = 7, minutes = 34, seconds = 24)).checkFormat("yyyy mm ss", "1990 24 10") - -# checking dayOfWeek matches known days -doAssert getDayOfWeek(01, mJan, 0000) == dSat -doAssert getDayOfWeek(01, mJan, -0023) == dSat -doAssert getDayOfWeek(21, mSep, 1900) == dFri -doAssert getDayOfWeek(01, mJan, 1970) == dThu -doAssert getDayOfWeek(21, mSep, 1970) == dMon -doAssert getDayOfWeek(01, mJan, 2000) == dSat -doAssert getDayOfWeek(01, mJan, 2021) == dFri - -# toUnix tests with GM timezone -let t4L = fromUnix(876124714).utc -doAssert toUnix(toTime(t4L)) == 876124714 -doAssert toUnix(toTime(t4L)) + t4L.utcOffset == toUnix(toTime(t4)) - -# adding intervals -var - a1L = toUnix(toTime(t4L + initTimeInterval(hours = 1))) + t4L.utcOffset - a1G = toUnix(toTime(t4)) + 60 * 60 -doAssert a1L == a1G - -# subtracting intervals -a1L = toUnix(toTime(t4L - initTimeInterval(hours = 1))) + t4L.utcOffset -a1G = toUnix(toTime(t4)) - (60 * 60) -doAssert a1L == a1G - -# Comparison between Time objects should be detected by compiler -# as 'noSideEffect'. -proc cmpTimeNoSideEffect(t1: Time, t2: Time): bool {.noSideEffect.} = - result = t1 == t2 -doAssert cmpTimeNoSideEffect(0.fromUnix, 0.fromUnix) -# Additionally `==` generic for seq[T] has explicit 'noSideEffect' pragma -# so we can check above condition by comparing seq[Time] sequences -let seqA: seq[Time] = @[] -let seqB: seq[Time] = @[] -doAssert seqA == seqB - -for tz in [ - (staticTz(seconds = 0), "+0", "+00", "+00:00"), # UTC - (staticTz(seconds = -3600), "+1", "+01", "+01:00"), # CET - (staticTz(seconds = -39600), "+11", "+11", "+11:00"), # two digits - (staticTz(seconds = -1800), "+0", "+00", "+00:30"), # half an hour - (staticTz(seconds = 7200), "-2", "-02", "-02:00"), # positive - (staticTz(seconds = 38700), "-10", "-10", "-10:45")]: # positive with three quaters hour - let dt = initDateTime(1, mJan, 2000, 00, 00, 00, tz[0]) - doAssert dt.format("z") == tz[1] - doAssert dt.format("zz") == tz[2] - doAssert dt.format("zzz") == tz[3] - -block countLeapYears: - # 1920, 2004 and 2020 are leap years, and should be counted starting at the following year - doAssert countLeapYears(1920) + 1 == countLeapYears(1921) - doAssert countLeapYears(2004) + 1 == countLeapYears(2005) - doAssert countLeapYears(2020) + 1 == countLeapYears(2021) - -block timezoneConversion: - var l = now() - let u = l.utc - l = u.local - - doAssert l.timezone == local() - doAssert u.timezone == utc() - template parseTest(s, f, sExpected: string, ydExpected: int) = let parsed = s.parse(f, utc()) parsedStr = $parsed - if parsedStr != sExpected: - echo "GOT ", parsedStr, " EXPECTED ", sExpected, " FORMAT ", f check parsedStr == sExpected - check(parsed.yearday == ydExpected) + check parsed.yearday == ydExpected template parseTestExcp(s, f: string) = expect ValueError: @@ -192,7 +113,7 @@ suite "ttimes": # Generate tests for multiple timezone files where available # Set the TZ env var for each test - when defined(Linux) or defined(macosx): + when defined(linux) or defined(macosx): const tz_dir = "/usr/share/zoneinfo" const f = "yyyy-MM-dd HH:mm zzz" @@ -333,7 +254,19 @@ suite "ttimes": check isLeapYear(2000) check (not isLeapYear(1900)) - test "subtract months": + test "TimeInterval": + let t = fromUnix(876124714).utc # Mon 6 Oct 08:58:34 BST 1997 + # Interval tests + let t2 = t - 2.years + check t2.year == 1995 + let t3 = (t - 7.years - 34.minutes - 24.seconds) + check t3.year == 1990 + check t3.minute == 24 + check t3.second == 10 + check (t + 1.hours).toTime.toUnix == t.toTime.toUnix + 60 * 60 + check (t - 1.hours).toTime.toUnix == t.toTime.toUnix - 60 * 60 + + test "TimeInterval - months": var dt = initDateTime(1, mFeb, 2017, 00, 00, 00, utc()) check $(dt - initTimeInterval(months = 1)) == "2017-01-01T00:00:00Z" dt = initDateTime(15, mMar, 2017, 00, 00, 00, utc()) @@ -404,14 +337,17 @@ suite "ttimes": let day = 24.hours let tomorrow = now + day check tomorrow - now == initDuration(days = 1) - - test "fromWinTime/toWinTime": - check 0.fromUnix.toWinTime.fromWinTime.toUnix == 0 - check (-1).fromWinTime.nanosecond == convert(Seconds, Nanoseconds, 1) - 100 - check -1.fromWinTime.toWinTime == -1 - # One nanosecond is discarded due to differences in time resolution - check initTime(0, 101).toWinTime.fromWinTime.nanosecond == 100 - check initTime(0, 101).toWinTime.fromWinTime.nanosecond == 100 + + # Disabled for JS because it fails due to precision errors + # (The JS target uses float64 for int64). + when not defined(js): + test "fromWinTime/toWinTime": + check 0.fromUnix.toWinTime.fromWinTime.toUnix == 0 + check (-1).fromWinTime.nanosecond == convert(Seconds, Nanoseconds, 1) - 100 + check (-1).fromWinTime.toWinTime == -1 + # One nanosecond is discarded due to differences in time resolution + check initTime(0, 101).toWinTime.fromWinTime.nanosecond == 100 + check initTime(0, 101).toWinTime.fromWinTime.nanosecond == 100 test "issue 7620": let layout = "M/d/yyyy' 'h:mm:ss' 'tt' 'z" @@ -477,6 +413,18 @@ suite "ttimes": expect ValueError: discard initTimeFormat("foo'") + for tz in [ + (staticTz(seconds = 0), "+0", "+00", "+00:00"), # UTC + (staticTz(seconds = -3600), "+1", "+01", "+01:00"), # CET + (staticTz(seconds = -39600), "+11", "+11", "+11:00"), # two digits + (staticTz(seconds = -1800), "+0", "+00", "+00:30"), # half an hour + (staticTz(seconds = 7200), "-2", "-02", "-02:00"), # positive + (staticTz(seconds = 38700), "-10", "-10", "-10:45")]: # positive with three quaters hour + let dt = initDateTime(1, mJan, 2000, 00, 00, 00, tz[0]) + doAssert dt.format("z") == tz[1] + doAssert dt.format("zz") == tz[2] + doAssert dt.format("zzz") == tz[3] + test "parse": check $parse("20180101", "yyyyMMdd", utc()) == "2018-01-01T00:00:00Z" parseTestExcp("+120180101", "yyyyMMdd") @@ -497,3 +445,26 @@ suite "ttimes": discard parse("'", "''") parseTestExcp("2000 A", "yyyy g") + + test "countLeapYears": + # 1920, 2004 and 2020 are leap years, and should be counted starting at the following year + check countLeapYears(1920) + 1 == countLeapYears(1921) + check countLeapYears(2004) + 1 == countLeapYears(2005) + check countLeapYears(2020) + 1 == countLeapYears(2021) + + test "timezoneConversion": + var l = now() + let u = l.utc + l = u.local + + check l.timezone == local() + check u.timezone == utc() + + test "getDayOfWeek": + check getDayOfWeek(01, mJan, 0000) == dSat + check getDayOfWeek(01, mJan, -0023) == dSat + check getDayOfWeek(21, mSep, 1900) == dFri + check getDayOfWeek(01, mJan, 1970) == dThu + check getDayOfWeek(21, mSep, 1970) == dMon + check getDayOfWeek(01, mJan, 2000) == dSat + check getDayOfWeek(01, mJan, 2021) == dFri |