summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/pure/times.nim507
-rw-r--r--lib/system/excpt.nim5
-rw-r--r--tests/exception/tdont_overwrite_typename.nim29
-rw-r--r--tests/js/ttimes.nim26
-rw-r--r--web/download.rst20
5 files changed, 318 insertions, 269 deletions
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index fe35c404c..1b088c0ac 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -385,260 +385,6 @@ proc `miliseconds=`*(t: var TimeInterval, milliseconds: int) {.deprecated.} =
   ## version.
   t.milliseconds = milliseconds
 
-when not defined(JS):
-  proc epochTime*(): float {.rtl, extern: "nt$1", tags: [TimeEffect].}
-    ## gets time after the UNIX epoch (1970) in seconds. It is a float
-    ## because sub-second resolution is likely to be supported (depending
-    ## on the hardware/OS).
-
-  proc cpuTime*(): float {.rtl, extern: "nt$1", tags: [TimeEffect].}
-    ## gets time spent that the CPU spent to run the current process in
-    ## seconds. This may be more useful for benchmarking than ``epochTime``.
-    ## However, it may measure the real time instead (depending on the OS).
-    ## The value of the result has no meaning.
-    ## To generate useful timing values, take the difference between
-    ## the results of two ``cpuTime`` calls:
-    ##
-    ## .. code-block:: nim
-    ##   var t0 = cpuTime()
-    ##   doWork()
-    ##   echo "CPU time [s] ", cpuTime() - t0
-
-when not defined(JS):
-  # C wrapper:
-  when defined(freebsd) or defined(netbsd) or defined(openbsd) or
-      defined(macosx):
-    type
-      StructTM {.importc: "struct tm", final.} = object
-        second {.importc: "tm_sec".},
-          minute {.importc: "tm_min".},
-          hour {.importc: "tm_hour".},
-          monthday {.importc: "tm_mday".},
-          month {.importc: "tm_mon".},
-          year {.importc: "tm_year".},
-          weekday {.importc: "tm_wday".},
-          yearday {.importc: "tm_yday".},
-          isdst {.importc: "tm_isdst".}: cint
-        gmtoff {.importc: "tm_gmtoff".}: clong
-  else:
-    type
-      StructTM {.importc: "struct tm", final.} = object
-        second {.importc: "tm_sec".},
-          minute {.importc: "tm_min".},
-          hour {.importc: "tm_hour".},
-          monthday {.importc: "tm_mday".},
-          month {.importc: "tm_mon".},
-          year {.importc: "tm_year".},
-          weekday {.importc: "tm_wday".},
-          yearday {.importc: "tm_yday".},
-          isdst {.importc: "tm_isdst".}: cint
-  type
-    TimeInfoPtr = ptr StructTM
-    Clock {.importc: "clock_t".} = distinct int
-
-  when not defined(windows):
-    # This is not ANSI C, but common enough
-    proc timegm(t: StructTM): Time {.
-      importc: "timegm", header: "<time.h>", tags: [].}
-
-  proc localtime(timer: ptr Time): TimeInfoPtr {.
-    importc: "localtime", header: "<time.h>", tags: [].}
-  proc gmtime(timer: ptr Time): TimeInfoPtr {.
-    importc: "gmtime", header: "<time.h>", tags: [].}
-  proc timec(timer: ptr Time): Time {.
-    importc: "time", header: "<time.h>", tags: [].}
-  proc mktime(t: StructTM): Time {.
-    importc: "mktime", header: "<time.h>", tags: [].}
-  proc getClock(): Clock {.importc: "clock", header: "<time.h>", tags: [TimeEffect].}
-  proc difftime(a, b: Time): float {.importc: "difftime", header: "<time.h>",
-    tags: [].}
-
-  var
-    clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int
-
-  # our own procs on top of that:
-  proc tmToTimeInfo(tm: StructTM, local: bool): TimeInfo =
-    const
-      weekDays: array[0..6, WeekDay] = [
-        dSun, dMon, dTue, dWed, dThu, dFri, dSat]
-    TimeInfo(second: int(tm.second),
-      minute: int(tm.minute),
-      hour: int(tm.hour),
-      monthday: int(tm.monthday),
-      month: Month(tm.month),
-      year: tm.year + 1900'i32,
-      weekday: weekDays[int(tm.weekday)],
-      yearday: int(tm.yearday),
-      isDST: tm.isdst > 0,
-      timezone: if local: getTimezone() else: 0
-    )
-
-
-  proc timeInfoToTM(t: TimeInfo): StructTM =
-    const
-      weekDays: array[WeekDay, int8] = [1'i8,2'i8,3'i8,4'i8,5'i8,6'i8,0'i8]
-    result.second = t.second
-    result.minute = t.minute
-    result.hour = t.hour
-    result.monthday = t.monthday
-    result.month = ord(t.month)
-    result.year = cint(t.year - 1900)
-    result.weekday = weekDays[t.weekday]
-    result.yearday = t.yearday
-    result.isdst = if t.isDST: 1 else: 0
-
-  when not defined(useNimRtl):
-    proc `-` (a, b: Time): int64 =
-      return toBiggestInt(difftime(a, b))
-
-  proc getStartMilsecs(): int =
-    #echo "clocks per sec: ", clocksPerSec, "clock: ", int(getClock())
-    #return getClock() div (clocksPerSec div 1000)
-    when defined(macosx):
-      result = toInt(toFloat(int(getClock())) / (toFloat(clocksPerSec) / 1000.0))
-    else:
-      result = int(getClock()) div (clocksPerSec div 1000)
-    when false:
-      var a: Timeval
-      posix_gettimeofday(a)
-      result = a.tv_sec * 1000'i64 + a.tv_usec div 1000'i64
-      #echo "result: ", result
-
-  proc getTime(): Time = return timec(nil)
-  proc getLocalTime(t: Time): TimeInfo =
-    var a = t
-    let lt = localtime(addr(a))
-    assert(not lt.isNil)
-    result = tmToTimeInfo(lt[], true)
-    # copying is needed anyway to provide reentrancity; thus
-    # the conversion is not expensive
-
-  proc getGMTime(t: Time): TimeInfo =
-    var a = t
-    result = tmToTimeInfo(gmtime(addr(a))[], false)
-    # copying is needed anyway to provide reentrancity; thus
-    # the conversion is not expensive
-
-  proc toTime(timeInfo: TimeInfo): Time =
-    var cTimeInfo = timeInfo # for C++ we have to make a copy
-    # because the header of mktime is broken in my version of libc
-
-    result = mktime(timeInfoToTM(cTimeInfo))
-    # mktime is defined to interpret the input as local time. As timeInfoToTM
-    # does ignore the timezone, we need to adjust this here.
-    result = Time(TimeImpl(result) - getTimezone() + timeInfo.timezone)
-
-  proc timeInfoToTime(timeInfo: TimeInfo): Time = toTime(timeInfo)
-
-  const
-    epochDiff = 116444736000000000'i64
-    rateDiff = 10000000'i64 # 100 nsecs
-
-  proc unixTimeToWinTime*(t: Time): int64 =
-    ## converts a UNIX `Time` (``time_t``) to a Windows file time
-    result = int64(t) * rateDiff + epochDiff
-
-  proc winTimeToUnixTime*(t: int64): Time =
-    ## converts a Windows time to a UNIX `Time` (``time_t``)
-    result = Time((t - epochDiff) div rateDiff)
-
-  proc getTimezone(): int =
-    when defined(freebsd) or defined(netbsd) or defined(openbsd):
-      var a = timec(nil)
-      let lt = localtime(addr(a))
-      # BSD stores in `gmtoff` offset east of UTC in seconds,
-      # but posix systems using west of UTC in seconds
-      return -(lt.gmtoff)
-    else:
-      return timezone
-
-  proc fromSeconds(since1970: float): Time = Time(since1970)
-
-  proc toSeconds(time: Time): float = float(time)
-
-  when not defined(useNimRtl):
-    proc epochTime(): float =
-      when defined(posix):
-        var a: Timeval
-        posix_gettimeofday(a)
-        result = toFloat(a.tv_sec) + toFloat(a.tv_usec)*0.00_0001
-      elif defined(windows):
-        var f: winlean.FILETIME
-        getSystemTimeAsFileTime(f)
-        var i64 = rdFileTime(f) - epochDiff
-        var secs = i64 div rateDiff
-        var subsecs = i64 mod rateDiff
-        result = toFloat(int(secs)) + toFloat(int(subsecs)) * 0.0000001
-      else:
-        {.error: "unknown OS".}
-
-    proc cpuTime(): float =
-      result = toFloat(int(getClock())) / toFloat(clocksPerSec)
-
-elif defined(JS):
-  proc newDate(): Time {.importc: "new Date".}
-  proc internGetTime(): Time {.importc: "new Date", tags: [].}
-
-  proc newDate(value: float): Time {.importc: "new Date".}
-  proc newDate(value: string): Time {.importc: "new Date".}
-  proc getTime(): Time =
-    # Warning: This is something different in JS.
-    return newDate()
-
-  const
-    weekDays: array[0..6, WeekDay] = [
-      dSun, dMon, dTue, dWed, dThu, dFri, dSat]
-
-  proc getLocalTime(t: Time): TimeInfo =
-    result.second = t.getSeconds()
-    result.minute = t.getMinutes()
-    result.hour = t.getHours()
-    result.monthday = t.getDate()
-    result.month = Month(t.getMonth())
-    result.year = t.getFullYear()
-    result.weekday = weekDays[t.getDay()]
-    result.yearday = 0
-    result.timezone = getTimezone()
-
-  proc getGMTime(t: Time): TimeInfo =
-    result.second = t.getUTCSeconds()
-    result.minute = t.getUTCMinutes()
-    result.hour = t.getUTCHours()
-    result.monthday = t.getUTCDate()
-    result.month = Month(t.getUTCMonth())
-    result.year = t.getUTCFullYear()
-    result.weekday = weekDays[t.getUTCDay()]
-    result.yearday = 0
-
-  proc timeInfoToTime(timeInfo: TimeInfo): Time = toTime(timeInfo)
-
-  proc toTime*(timeInfo: TimeInfo): Time =
-    result = internGetTime()
-    result.setMinutes(timeInfo.minute)
-    result.setHours(timeInfo.hour)
-    result.setMonth(ord(timeInfo.month))
-    result.setFullYear(timeInfo.year)
-    result.setDate(timeInfo.monthday)
-    result.setSeconds(timeInfo.second + timeInfo.timezone)
-
-  proc `-` (a, b: Time): int64 =
-    return a.getTime() - b.getTime()
-
-  var
-    startMilsecs = getTime()
-
-  proc getStartMilsecs(): int =
-    ## get the milliseconds from the start of the program
-    return int(getTime() - startMilsecs)
-
-  proc fromSeconds(since1970: float): Time = result = newDate(since1970 * 1000)
-
-  proc toSeconds(time: Time): float = result = time.getTime() / 1000
-
-  proc getTimezone(): int = result = newDate().getTimezoneOffset() * 60
-
-  proc epochTime*(): float {.tags: [TimeEffect].} = newDate().toSeconds()
-
 proc getDateStr*(): string {.rtl, extern: "nt$1", tags: [TimeEffect].} =
   ## gets the current date as a string of the format ``YYYY-MM-DD``.
   var ti = getLocalTime(getTime())
@@ -1333,6 +1079,259 @@ proc toTimeInterval*(t: Time): TimeInterval =
   var tInfo = t.getLocalTime()
   initInterval(0, tInfo.second, tInfo.minute, tInfo.hour, tInfo.weekday.ord, tInfo.month.ord, tInfo.year)
 
+when not defined(JS):
+  proc epochTime*(): float {.rtl, extern: "nt$1", tags: [TimeEffect].}
+    ## gets time after the UNIX epoch (1970) in seconds. It is a float
+    ## because sub-second resolution is likely to be supported (depending
+    ## on the hardware/OS).
+
+  proc cpuTime*(): float {.rtl, extern: "nt$1", tags: [TimeEffect].}
+    ## gets time spent that the CPU spent to run the current process in
+    ## seconds. This may be more useful for benchmarking than ``epochTime``.
+    ## However, it may measure the real time instead (depending on the OS).
+    ## The value of the result has no meaning.
+    ## To generate useful timing values, take the difference between
+    ## the results of two ``cpuTime`` calls:
+    ##
+    ## .. code-block:: nim
+    ##   var t0 = cpuTime()
+    ##   doWork()
+    ##   echo "CPU time [s] ", cpuTime() - t0
+
+when not defined(JS):
+  # C wrapper:
+  when defined(freebsd) or defined(netbsd) or defined(openbsd) or
+      defined(macosx):
+    type
+      StructTM {.importc: "struct tm", final.} = object
+        second {.importc: "tm_sec".},
+          minute {.importc: "tm_min".},
+          hour {.importc: "tm_hour".},
+          monthday {.importc: "tm_mday".},
+          month {.importc: "tm_mon".},
+          year {.importc: "tm_year".},
+          weekday {.importc: "tm_wday".},
+          yearday {.importc: "tm_yday".},
+          isdst {.importc: "tm_isdst".}: cint
+        gmtoff {.importc: "tm_gmtoff".}: clong
+  else:
+    type
+      StructTM {.importc: "struct tm", final.} = object
+        second {.importc: "tm_sec".},
+          minute {.importc: "tm_min".},
+          hour {.importc: "tm_hour".},
+          monthday {.importc: "tm_mday".},
+          month {.importc: "tm_mon".},
+          year {.importc: "tm_year".},
+          weekday {.importc: "tm_wday".},
+          yearday {.importc: "tm_yday".},
+          isdst {.importc: "tm_isdst".}: cint
+  type
+    TimeInfoPtr = ptr StructTM
+    Clock {.importc: "clock_t".} = distinct int
+
+  when not defined(windows):
+    # This is not ANSI C, but common enough
+    proc timegm(t: StructTM): Time {.
+      importc: "timegm", header: "<time.h>", tags: [].}
+
+  proc localtime(timer: ptr Time): TimeInfoPtr {.
+    importc: "localtime", header: "<time.h>", tags: [].}
+  proc gmtime(timer: ptr Time): TimeInfoPtr {.
+    importc: "gmtime", header: "<time.h>", tags: [].}
+  proc timec(timer: ptr Time): Time {.
+    importc: "time", header: "<time.h>", tags: [].}
+  proc mktime(t: StructTM): Time {.
+    importc: "mktime", header: "<time.h>", tags: [].}
+  proc getClock(): Clock {.importc: "clock", header: "<time.h>", tags: [TimeEffect].}
+  proc difftime(a, b: Time): float {.importc: "difftime", header: "<time.h>",
+    tags: [].}
+
+  var
+    clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int
+
+  # our own procs on top of that:
+  proc tmToTimeInfo(tm: StructTM, local: bool): TimeInfo =
+    const
+      weekDays: array[0..6, WeekDay] = [
+        dSun, dMon, dTue, dWed, dThu, dFri, dSat]
+    TimeInfo(second: int(tm.second),
+      minute: int(tm.minute),
+      hour: int(tm.hour),
+      monthday: int(tm.monthday),
+      month: Month(tm.month),
+      year: tm.year + 1900'i32,
+      weekday: weekDays[int(tm.weekday)],
+      yearday: int(tm.yearday),
+      isDST: tm.isdst > 0,
+      timezone: if local: getTimezone() else: 0
+    )
+
+
+  proc timeInfoToTM(t: TimeInfo): StructTM =
+    const
+      weekDays: array[WeekDay, int8] = [1'i8,2'i8,3'i8,4'i8,5'i8,6'i8,0'i8]
+    result.second = t.second
+    result.minute = t.minute
+    result.hour = t.hour
+    result.monthday = t.monthday
+    result.month = ord(t.month)
+    result.year = cint(t.year - 1900)
+    result.weekday = weekDays[t.weekday]
+    result.yearday = t.yearday
+    result.isdst = if t.isDST: 1 else: 0
+
+  when not defined(useNimRtl):
+    proc `-` (a, b: Time): int64 =
+      return toBiggestInt(difftime(a, b))
+
+  proc getStartMilsecs(): int =
+    #echo "clocks per sec: ", clocksPerSec, "clock: ", int(getClock())
+    #return getClock() div (clocksPerSec div 1000)
+    when defined(macosx):
+      result = toInt(toFloat(int(getClock())) / (toFloat(clocksPerSec) / 1000.0))
+    else:
+      result = int(getClock()) div (clocksPerSec div 1000)
+    when false:
+      var a: Timeval
+      posix_gettimeofday(a)
+      result = a.tv_sec * 1000'i64 + a.tv_usec div 1000'i64
+      #echo "result: ", result
+
+  proc getTime(): Time = return timec(nil)
+  proc getLocalTime(t: Time): TimeInfo =
+    var a = t
+    let lt = localtime(addr(a))
+    assert(not lt.isNil)
+    result = tmToTimeInfo(lt[], true)
+    # copying is needed anyway to provide reentrancity; thus
+    # the conversion is not expensive
+
+  proc getGMTime(t: Time): TimeInfo =
+    var a = t
+    result = tmToTimeInfo(gmtime(addr(a))[], false)
+    # copying is needed anyway to provide reentrancity; thus
+    # the conversion is not expensive
+
+  proc toTime(timeInfo: TimeInfo): Time =
+    var cTimeInfo = timeInfo # for C++ we have to make a copy
+    # because the header of mktime is broken in my version of libc
+
+    result = mktime(timeInfoToTM(cTimeInfo))
+    # mktime is defined to interpret the input as local time. As timeInfoToTM
+    # does ignore the timezone, we need to adjust this here.
+    result = Time(TimeImpl(result) - getTimezone() + timeInfo.timezone)
+
+  proc timeInfoToTime(timeInfo: TimeInfo): Time = toTime(timeInfo)
+
+  const
+    epochDiff = 116444736000000000'i64
+    rateDiff = 10000000'i64 # 100 nsecs
+
+  proc unixTimeToWinTime*(t: Time): int64 =
+    ## converts a UNIX `Time` (``time_t``) to a Windows file time
+    result = int64(t) * rateDiff + epochDiff
+
+  proc winTimeToUnixTime*(t: int64): Time =
+    ## converts a Windows time to a UNIX `Time` (``time_t``)
+    result = Time((t - epochDiff) div rateDiff)
+
+  proc getTimezone(): int =
+    when defined(freebsd) or defined(netbsd) or defined(openbsd):
+      var a = timec(nil)
+      let lt = localtime(addr(a))
+      # BSD stores in `gmtoff` offset east of UTC in seconds,
+      # but posix systems using west of UTC in seconds
+      return -(lt.gmtoff)
+    else:
+      return timezone
+
+  proc fromSeconds(since1970: float): Time = Time(since1970)
+
+  proc toSeconds(time: Time): float = float(time)
+
+  when not defined(useNimRtl):
+    proc epochTime(): float =
+      when defined(posix):
+        var a: Timeval
+        posix_gettimeofday(a)
+        result = toFloat(a.tv_sec) + toFloat(a.tv_usec)*0.00_0001
+      elif defined(windows):
+        var f: winlean.FILETIME
+        getSystemTimeAsFileTime(f)
+        var i64 = rdFileTime(f) - epochDiff
+        var secs = i64 div rateDiff
+        var subsecs = i64 mod rateDiff
+        result = toFloat(int(secs)) + toFloat(int(subsecs)) * 0.0000001
+      else:
+        {.error: "unknown OS".}
+
+    proc cpuTime(): float =
+      result = toFloat(int(getClock())) / toFloat(clocksPerSec)
+
+elif defined(JS):
+  proc newDate(): Time {.importc: "new Date".}
+  proc internGetTime(): Time {.importc: "new Date", tags: [].}
+
+  proc newDate(value: float): Time {.importc: "new Date".}
+  proc newDate(value: cstring): Time {.importc: "new Date".}
+  proc getTime(): Time =
+    # Warning: This is something different in JS.
+    return newDate()
+
+  const
+    weekDays: array[0..6, WeekDay] = [
+      dSun, dMon, dTue, dWed, dThu, dFri, dSat]
+
+  proc getLocalTime(t: Time): TimeInfo =
+    result.second = t.getSeconds()
+    result.minute = t.getMinutes()
+    result.hour = t.getHours()
+    result.monthday = t.getDate()
+    result.month = Month(t.getMonth())
+    result.year = t.getFullYear()
+    result.weekday = weekDays[t.getDay()]
+    result.timezone = getTimezone()
+
+    result.yearday = result.monthday - 1
+    for month in mJan..<result.month:
+      result.yearday += getDaysInMonth(month, result.year)
+
+  proc getGMTime(t: Time): TimeInfo =
+    result.second = t.getUTCSeconds()
+    result.minute = t.getUTCMinutes()
+    result.hour = t.getUTCHours()
+    result.monthday = t.getUTCDate()
+    result.month = Month(t.getUTCMonth())
+    result.year = t.getUTCFullYear()
+    result.weekday = weekDays[t.getUTCDay()]
+
+    result.yearday = result.monthday - 1
+    for month in mJan..<result.month:
+      result.yearday += getDaysInMonth(month, result.year)
+
+  proc timeInfoToTime(timeInfo: TimeInfo): Time = toTime(timeInfo)
+
+  proc toTime*(timeInfo: TimeInfo): Time = newDate($timeInfo)
+
+  proc `-` (a, b: Time): int64 =
+    return a.getTime() - b.getTime()
+
+  var
+    startMilsecs = getTime()
+
+  proc getStartMilsecs(): int =
+    ## get the milliseconds from the start of the program
+    return int(getTime() - startMilsecs)
+
+  proc fromSeconds(since1970: float): Time = result = newDate(since1970 * 1000)
+
+  proc toSeconds(time: Time): float = result = time.getTime() / 1000
+
+  proc getTimezone(): int = result = newDate().getTimezoneOffset() * 60
+
+  proc epochTime*(): float {.tags: [TimeEffect].} = newDate().toSeconds()
+
 
 when isMainModule:
   # this is testing non-exported function
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index bae5de9d3..8ed1fbb38 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -73,7 +73,8 @@ proc popSafePoint {.compilerRtl, inl.} =
   excHandler = excHandler.prev
 
 proc pushCurrentException(e: ref Exception) {.compilerRtl, inl.} =
-  e.parent = currException
+  #if e.parent.isNil:
+  #  e.parent = currException
   currException = e
 
 proc popCurrentException {.compilerRtl, inl.} =
@@ -279,7 +280,7 @@ proc raiseExceptionAux(e: ref Exception) =
       quitOrDebug()
 
 proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
-  e.name = ename
+  if e.name.isNil: e.name = ename
   when hasSomeStackTrace:
     e.trace = ""
     rawWriteStackTrace(e.trace)
diff --git a/tests/exception/tdont_overwrite_typename.nim b/tests/exception/tdont_overwrite_typename.nim
new file mode 100644
index 000000000..147ccc001
--- /dev/null
+++ b/tests/exception/tdont_overwrite_typename.nim
@@ -0,0 +1,29 @@
+discard """
+  output: '''Check passed
+Check passed'''
+"""
+
+# bug #5628
+
+proc checkException(ex: ref Exception) =
+  doAssert(ex.name == "ValueError")
+  doAssert(ex.msg == "SecondException")
+  doAssert(ex.parent != nil)
+  doAssert(ex.parent.name == "KeyError")
+  doAssert(ex.parent.msg == "FirstException")
+  echo "Check passed"
+
+var e: ref Exception
+try:
+  try:
+    raise newException(KeyError, "FirstException")
+  except:
+    raise newException(ValueError, "SecondException", getCurrentException())
+except:
+  e = getCurrentException()
+
+try:
+  checkException(e) # passes here
+  raise e
+except ValueError:
+  checkException(getCurrentException()) # fails here
diff --git a/tests/js/ttimes.nim b/tests/js/ttimes.nim
new file mode 100644
index 000000000..20ba14245
--- /dev/null
+++ b/tests/js/ttimes.nim
@@ -0,0 +1,26 @@
+# test times module with js
+discard """
+  action: run
+"""
+
+import times
+
+# $ date --date='@2147483647'
+# Tue 19 Jan 03:14:07 GMT 2038
+
+block yeardayTest:
+  # check if yearday attribute is properly set on TimeInfo creation
+  doAssert fromSeconds(2147483647).getGMTime().yearday == 18
+
+block localTimezoneTest:
+  # check if timezone is properly set during Time to TimeInfo conversion
+  doAssert fromSeconds(2147483647).getLocalTime().timezone == getTimezone()
+
+block timestampPersistenceTest:
+  # check if timestamp persists during TimeInfo to Time conversion
+  const
+    timeString = "2017-03-21T12:34:56+03:00"
+    timeStringGmt = "2017-03-21T09:34:56+00:00"
+    fmt = "yyyy-MM-dd'T'HH:mm:sszzz"
+
+  doAssert $timeString.parse(fmt).toTime().getGMTime() == timeStringGmt
diff --git a/web/download.rst b/web/download.rst
index d2c6a0fc2..dd086cbaa 100644
--- a/web/download.rst
+++ b/web/download.rst
@@ -9,7 +9,8 @@ Windows
 Zips
 %%%%
 
-We now encourage you to install via the provided zipfiles:
+Since the website moved to https, only installation via the provided zipfiles
+is supported:
 
 * | 32 bit: `nim-0.16.0_x32.zip <download/nim-0.16.0_x32.zip>`_
   | SHA-256  69af94a6875a02543c1bf0fa03c665f126f8500a2c0e226c32571e64c6842e57
@@ -25,21 +26,14 @@ You can find the required DLLs here, if you lack them for some reason:
   | SHA-256  198112d3d6dc74d7964ba452158d44bfa57adef4dc47be8c39903f2a24e4a555
 
 
-Exes
-%%%%
+These versions of mingw are known to work:
 
-You can download an installer for both 32 bit and 64 bit versions of
-Windows below. Note that these installers have some known issues and
-so will unlikely to be provided further in the future. These
-installers have everything you need to use Nim, including a C compiler.
+* | 32 bit: `mingw32-6.3.0 <download/mingw32-6.3.0.7z>`_
+  | SHA-256  1239a56d4c42e146b2cb25dc4d0871bd83f569d0a51a9198e84d010e0a75745a
+* | 64 bit: `mingw64-6.3.0 <download/mingw64-6.3.0.7z>`_
+  | SHA-256  9a23d12d96a10e67093c1f2042275c6a7d29da9e2ead573d0f24f4a6d53761a1
 
-* | 32 bit: `nim-0.16.0_x32.exe <download/nim-0.16.0_x32.exe>`_
-  | SHA-256  37c55d9f9b3a2947559901c8bbd10b6a16191b562ca2bebdc145a6c24f5d004e
-* | 64 bit: `nim-0.16.0_x64.exe <download/nim-0.16.0_x64.exe>`_
-  | SHA-256  13934282b01cbcaf7ad7aecb67e954dd0ea2b576c6c8102016cb9a9a30cce744
 
-These installers also include Aporia, Nimble and other useful Nim tools to get
-you started with Nim development!
 
 Installation based on generated C code
 --------------------------------------