summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/pure/times.nim49
-rw-r--r--tests/stdlib/ttimes.nim45
2 files changed, 61 insertions, 33 deletions
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index 3b0b9b625..dc216477b 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -330,7 +330,7 @@ proc `$`*(dur: Duration): string =
     remS.inc 1
 
   const unitStrings: array[FixedTimeUnit, string] = [
-    "nanoseconds", "microsecond", "millisecond", "second", "minute", "hour", "day", "week"
+    "nanosecond", "microsecond", "millisecond", "second", "minute", "hour", "day", "week"
   ]
 
   for unit in countdown(Weeks, Seconds):
@@ -1093,27 +1093,52 @@ proc `+`*(dt: DateTime, dur: Duration): DateTime =
 proc `-`*(dt: DateTime, dur: Duration): DateTime =
   (dt.toTime - dur).inZone(dt.timezone)
 
-proc `+=`*(time: var Time, interval: TimeInterval) =
-  ## Modifies `time` by adding `interval`.
-  time = toTime(time.local + interval)
+proc isStaticInterval(interval: TimeInterval): bool =
+  interval.years == 0 and interval.months == 0 and
+    interval.days == 0 and interval.weeks == 0
+
+proc evaluateStaticInterval(interval: TimeInterval): Duration =
+  assert interval.isStaticInterval
+  initDuration(nanoseconds = interval.nanoseconds,
+    microseconds = interval.microseconds,
+    milliseconds = interval.milliseconds,
+    seconds = interval.seconds,
+    minutes = interval.minutes,
+    hours = interval.hours)
 
 proc `+`*(time: Time, interval: TimeInterval): Time =
-  ## Adds `interval` to `time`
-  ## by converting to a ``DateTime`` in the local timezone,
-  ## adding the interval, and converting back to ``Time``.
+  ## Adds `interval` to `time`.
+  ## If `interval` contains any years, months, weeks or days the operation
+  ## is performed in the local timezone.
   ##
   ## ``echo getTime() + 1.day``
-  result = toTime(time.local + interval)
+  if interval.isStaticInterval:
+    time + evaluateStaticInterval(interval)
+  else:
+    toTime(time.local + interval)
 
-proc `-=`*(time: var Time, interval: TimeInterval) =
-  ## Modifies `time` by subtracting `interval`.
-  time = toTime(time.local - interval)
+proc `+=`*(time: var Time, interval: TimeInterval) =
+  ## Modifies `time` by adding `interval`.
+  ## If `interval` contains any years, months, weeks or days the operation
+  ## is performed in the local timezone.
+  time = time + interval
 
 proc `-`*(time: Time, interval: TimeInterval): Time =
   ## Subtracts `interval` from Time `time`.
+  ## If `interval` contains any years, months, weeks or days the operation
+  ## is performed in the local timezone.
   ##
   ## ``echo getTime() - 1.day``
-  result = toTime(time.local - interval)
+  if interval.isStaticInterval:
+    time - evaluateStaticInterval(interval)
+  else:
+    toTime(time.local - interval)
+
+proc `-=`*(time: var Time, interval: TimeInterval) =
+  ## Modifies `time` by subtracting `interval`.
+  ## If `interval` contains any years, months, weeks or days the operation
+  ## is performed in the local timezone.
+  time = time - interval
 
 proc formatToken(dt: DateTime, token: string, buf: var string) =
   ## Helper of the format proc to parse individual tokens.
diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim
index 8f32fea33..f35965286 100644
--- a/tests/stdlib/ttimes.nim
+++ b/tests/stdlib/ttimes.nim
@@ -65,26 +65,6 @@ a1L = toUnix(toTime(t4L - initTimeInterval(hours = 1))) + t4L.utcOffset
 a1G = toUnix(toTime(t4)) - (60 * 60)
 doAssert a1L == a1G
 
-# add/subtract TimeIntervals and Time/TimeInfo
-let now = getTime().utc
-doAssert now + convert(Seconds, Nanoseconds, 1).nanoseconds == now + 1.seconds
-doAssert now + 1.weeks == now + 7.days
-doAssert now - 1.seconds == now - 3.seconds + 2.seconds
-doAssert now + 65.seconds == now + 1.minutes + 5.seconds
-doAssert now + 60.minutes == now + 1.hours
-doAssert now + 24.hours == now + 1.days
-doAssert now + 13.months == now + 1.years + 1.months
-var ti1 = now + 1.years
-ti1 = ti1 - 1.years
-doAssert ti1 == now
-ti1 = ti1 + 1.days
-doAssert ti1 == now + 1.days
-
-# Bug with adding a day to a Time
-let day = 24.hours
-let tomorrow = now + day
-doAssert tomorrow - now == initDuration(days = 1)
-
 # Comparison between Time objects should be detected by compiler
 # as 'noSideEffect'.
 proc cmpTimeNoSideEffect(t1: Time, t2: Time): bool {.noSideEffect.} =
@@ -284,7 +264,7 @@ suite "ttimes":
     putEnv("TZ", orig_tz)
 
   else:
-    # not on Linux or macosx: run one parseTest only
+    # not on Linux or macosx: run in the local timezone only
     test "parseTest":
       runTimezoneTests()
 
@@ -407,3 +387,26 @@ suite "ttimes":
     check dt1 <= dt2
     dt2 = dt2 + 1.seconds
     check dt1 < dt2
+
+  test "adding/subtracting TimeInterval":
+    # add/subtract TimeIntervals and Time/TimeInfo
+    let now = getTime().utc
+    check now + convert(Seconds, Nanoseconds, 1).nanoseconds == now + 1.seconds
+    check now + 1.weeks == now + 7.days
+    check now - 1.seconds == now - 3.seconds + 2.seconds
+    check now + 65.seconds == now + 1.minutes + 5.seconds
+    check now + 60.minutes == now + 1.hours
+    check now + 24.hours == now + 1.days
+    check now + 13.months == now + 1.years + 1.months
+    check toUnix(fromUnix(0) + 2.seconds) == 2
+    check toUnix(fromUnix(0) - 2.seconds) == -2
+    var ti1 = now + 1.years
+    ti1 = ti1 - 1.years
+    check ti1 == now
+    ti1 = ti1 + 1.days
+    check ti1 == now + 1.days
+
+    # Bug with adding a day to a Time
+    let day = 24.hours
+    let tomorrow = now + day
+    check tomorrow - now == initDuration(days = 1)
\ No newline at end of file