summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-04-13 13:13:55 -0700
committerAraq <rumpf_a@web.de>2013-04-13 13:13:55 -0700
commit7eee6282cfcaab4de65fc8407ef87ddaf569b634 (patch)
tree4d7078539cb17b3925ae1715c18802fb7b364029 /lib
parent75b508032b9da285f30d4ec7f2af4c63075b8611 (diff)
parent4deaae98306effd887703f8b7493b0d9c91efbc9 (diff)
downloadNim-7eee6282cfcaab4de65fc8407ef87ddaf569b634.tar.gz
Merge pull request #384 from Tass/master
Fixes #334.
Diffstat (limited to 'lib')
-rw-r--r--lib/pure/times.nim166
1 files changed, 100 insertions, 66 deletions
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index b86c72ed3..553973517 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -29,7 +29,7 @@ var
   timezone {.importc, header: "<time.h>".}: int
   tzname {.importc, header: "<time.h>" .}: array[0..1, cstring]
 
-when defined(posix): 
+when defined(posix) and not defined(JS):
   type
     TTimeImpl {.importc: "time_t", header: "<sys/time.h>".} = int
     TTime* = distinct TTimeImpl ## distinct type that represents a time
@@ -62,45 +62,44 @@ elif defined(windows):
 elif defined(JS):
   type
     TTime* {.final, importc.} = object
-      getDay: proc (): int
-      getFullYear: proc (): int
-      getHours: proc (): int
-      getMilliseconds: proc (): int
-      getMinutes: proc (): int
-      getMonth: proc (): int
-      getSeconds: proc (): int
-      getTime: proc (): int
-      getTimezoneOffset: proc (): int
-      getDate: proc (): int
-      getUTCDate: proc (): int
-      getUTCFullYear: proc (): int
-      getUTCHours: proc (): int
-      getUTCMilliseconds: proc (): int
-      getUTCMinutes: proc (): int
-      getUTCMonth: proc (): int
-      getUTCSeconds: proc (): int
-      getUTCDay: proc (): int
-      getYear: proc (): int
-      parse: proc (s: cstring): TTime
-      setDate: proc (x: int)
-      setFullYear: proc (x: int)
-      setHours: proc (x: int)
-      setMilliseconds: proc (x: int)
-      setMinutes: proc (x: int)
-      setMonth: proc (x: int)
-      setSeconds: proc (x: int)
-      setTime: proc (x: int)
-      setUTCDate: proc (x: int)
-      setUTCFullYear: proc (x: int)
-      setUTCHours: proc (x: int)
-      setUTCMilliseconds: proc (x: int)
-      setUTCMinutes: proc (x: int)
-      setUTCMonth: proc (x: int)
-      setUTCSeconds: proc (x: int)
-      setYear: proc (x: int)
-      toGMTString: proc (): cstring
-      toLocaleString: proc (): cstring
-      UTC: proc (): int
+      getDay: proc (): int {.tags: [].}
+      getFullYear: proc (): int {.tags: [].}
+      getHours: proc (): int {.tags: [].}
+      getMilliseconds: proc (): int {.tags: [].}
+      getMinutes: proc (): int {.tags: [].}
+      getMonth: proc (): int {.tags: [].}
+      getSeconds: proc (): int {.tags: [].}
+      getTime: proc (): int {.tags: [].}
+      getTimezoneOffset: proc (): int {.tags: [].}
+      getDate: proc (): int {.tags: [].}
+      getUTCDate: proc (): int {.tags: [].}
+      getUTCFullYear: proc (): int {.tags: [].}
+      getUTCHours: proc (): int {.tags: [].}
+      getUTCMilliseconds: proc (): int {.tags: [].}
+      getUTCMinutes: proc (): int {.tags: [].}
+      getUTCMonth: proc (): int {.tags: [].}
+      getUTCSeconds: proc (): int {.tags: [].}
+      getUTCDay: proc (): int {.tags: [].}
+      getYear: proc (): int {.tags: [].}
+      parse: proc (s: cstring): TTime {.tags: [].}
+      setDate: proc (x: int) {.tags: [].}
+      setFullYear: proc (x: int) {.tags: [].}
+      setHours: proc (x: int) {.tags: [].}
+      setMilliseconds: proc (x: int) {.tags: [].}
+      setMinutes: proc (x: int) {.tags: [].}
+      setMonth: proc (x: int) {.tags: [].}
+      setSeconds: proc (x: int) {.tags: [].}
+      setTime: proc (x: int) {.tags: [].}
+      setUTCDate: proc (x: int) {.tags: [].}
+      setUTCFullYear: proc (x: int) {.tags: [].}
+      setUTCHours: proc (x: int) {.tags: [].}
+      setUTCMilliseconds: proc (x: int) {.tags: [].}
+      setUTCMinutes: proc (x: int) {.tags: [].}
+      setUTCMonth: proc (x: int) {.tags: [].}
+      setUTCSeconds: proc (x: int) {.tags: [].}
+      setYear: proc (x: int) {.tags: [].}
+      toGMTString: proc (): cstring {.tags: [].}
+      toLocaleString: proc (): cstring {.tags: [].}
 
 type
   TTimeInfo* = object of TObject ## represents a time in different parts
@@ -124,6 +123,9 @@ type
     timezone*: int            ## The offset of the (non-DST) timezone in seconds
                               ## west of UTC.
 
+  ## I make some assumptions about the data in here. Either
+  ## everything should be positive or everything negative. Zero is
+  ## fine too. Mixed signs will lead to unexpected results.
   TTimeInterval* {.pure.} = object ## a time interval
     miliseconds*: int ## The number of miliseconds
     seconds*: int     ## The number of seconds
@@ -150,6 +152,17 @@ proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime
   ## contents of the structure members `weekday` and `yearday` and recomputes
   ## them from the other information in the broken-down time structure.
 
+proc fromSeconds*(since1970: float): TTime
+  ## Takes a float which contains the number of seconds since 1970 and
+  ## returns a time object.
+
+proc fromSeconds*(since1970: int|int64): TTime = fromSeconds(float(since1970))
+  ## Takes an in which contains the number of seconds since 1970 and
+  ## returns a time object.
+
+proc toSeconds*(time: TTime): float
+  ## Returns the time in seconds since 1970.
+
 proc `$` *(timeInfo: TTimeInfo): string
   ## converts a `TTimeInfo` object to a string representation.
 proc `$` *(time: TTime): string
@@ -173,9 +186,10 @@ proc `==`*(a, b: TTime): bool {.rtl, extern: "ntEqTime".} =
   ## returns true if ``a == b``, that is if both times represent the same value
   result = a - b == 0
 
-proc getTzname*(): tuple[nonDST, DST: string] {.tags: [FTime].}
-  ## returns the local timezone; ``nonDST`` is the name of the local non-DST
-  ## timezone, ``DST`` is the name of the local DST timezone.
+when not defined(JS):
+  proc getTzname*(): tuple[nonDST, DST: string] {.tags: [FTime].}
+    ## returns the local timezone; ``nonDST`` is the name of the local non-DST
+    ## timezone, ``DST`` is the name of the local DST timezone.
 
 proc getTimezone*(): int {.tags: [FTime].}
   ## returns the offset of the local (non-DST) timezone in seconds west of UTC.
@@ -212,10 +226,18 @@ proc getDaysInMonth(month: TMonth, year: int): int =
   of mApr, mJun, mSep, mNov: result = 30
   else: result = 31
 
-proc calculateSeconds(a: TTimeInfo, interval: TTimeInterval): float =
+proc `-`*(interval: TTimeInterval): TTimeInterval =
+  for a, b in fields(result, interval):
+    a = -b
+
+proc toSeconds*(a: TTimeInfo, interval: TTimeInterval): float =
+  ## Returns the time the interval will be at that point in time. This
+  ## needs a time as well, because e.g. a month is not always the same
+  ## length.
+
   var anew = a
   var newinterv = interval
-  result = 0.0
+  result = 0
   
   newinterv.months += interval.years * 12
   var curMonth = anew.month
@@ -228,32 +250,30 @@ proc calculateSeconds(a: TTimeInfo, interval: TTimeInterval): float =
       curMonth.inc()
   result += float(newinterv.days * 24 * 60 * 60)
   result += float(newinterv.minutes * 60 * 60)
-  result += newinterv.seconds.float
+  result += float(newinterv.seconds)
   result += newinterv.miliseconds / 1000
 
+proc toSeconds*(a: TTime, interval: TTimeInterval): float =
+  result = toSeconds(getGMTime(a), interval)
+
 proc `+`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
   ## adds ``interval`` time.
   ##
   ## **Note:** This has been only briefly tested and it may not be
   ## very accurate.
-  let t = timeInfoToTime(a)
-  let secs = calculateSeconds(a, interval)
+  let t = toSeconds(TimeInfoToTime(a))
+  let secs = toSeconds(a, interval)
   if a.tzname == "UTC":
-    result = getGMTime(TTime(float(t) + secs))
+    result = getGMTime(fromSeconds(t + secs))
   else:
-    result = getLocalTime(TTime(float(t) + secs))
+    result = getLocalTime(fromSeconds(t + secs))
 
 proc `-`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
   ## subtracts ``interval`` time.
   ##
   ## **Note:** This has been only briefly tested, it is inaccurate especially
   ## when you subtract so much that you reach the Julian calendar.
-  let t = timeInfoToTime(a)
-  let secs = calculateSeconds(a, interval)
-  if a.tzname == "UTC":
-    result = getGMTime(TTime(float(t) - secs))
-  else:
-    result = getLocalTime(TTime(float(t) - secs))
+  result = a + -interval
 
 when not defined(JS):  
   proc epochTime*(): float {.rtl, extern: "nt$1", tags: [FTime].}
@@ -274,8 +294,7 @@ when not defined(JS):
     ##   doWork()
     ##   echo "CPU time [s] ", cpuTime() - t0
 
-when not defined(JS):
-  
+when not defined(JS) and defined(POSIX):
   # C wrapper:
   type
     structTM {.importc: "struct tm", final.} = object
@@ -416,7 +435,11 @@ when not defined(JS):
   
   proc getTimezone(): int =
     return timezone
-  
+
+  proc fromSeconds(since1970: float): TTime = TTime(since1970)
+
+  proc toSeconds(time: TTime): float = float(time)
+
   when not defined(useNimRtl):
     proc epochTime(): float = 
       when defined(posix):
@@ -437,8 +460,12 @@ when not defined(JS):
       result = toFloat(int(clock())) / toFloat(clocksPerSec)
     
 elif defined(JS):
-  proc newDate(): TTime {.importc: "new Date", nodecl.}
-  proc getTime(): TTime = return newDate()
+  proc newDate(): TTime {.importc: "new Date".}
+  proc newDate(value: float): TTime {.importc: "new Date".}
+  proc newDate(value: string): TTime {.importc: "new Date".}
+  proc getTime(): TTime =
+    # Warning: This is something different in JS.
+    return newDate()
 
   const
     weekDays: array [0..6, TWeekDay] = [
@@ -486,6 +513,13 @@ elif defined(JS):
     ## get the miliseconds from the start of the program
     return int(getTime() - startMilsecs)
 
+  proc valueOf(time: TTime): float {.importcpp: "getTime", tags:[]}
+
+  proc fromSeconds(since1970: float): TTime = result = newDate(since1970)
+
+  proc toSeconds(time: TTime): float = result = time.valueOf() / 1000
+
+  proc getTimezone(): int = result = newDate().getTimezoneOffset()
 
 proc getDateStr*(): string {.rtl, extern: "nt$1", tags: [FTime].} =
   ## gets the current date as a string of the format ``YYYY-MM-DD``.
@@ -680,7 +714,7 @@ when isMainModule:
   # $ date --date='@2147483647'
   # Tue 19 Jan 03:14:07 GMT 2038
 
-  var t = getGMTime(TTime(2147483647))
+  var t = getGMTime(fromSeconds(2147483647))
   echo t.format("ddd dd MMM hh:mm:ss ZZZ yyyy")
   assert t.format("ddd dd MMM hh:mm:ss ZZZ yyyy") == "Tue 19 Jan 03:14:07 UTC 2038"
   
@@ -688,19 +722,19 @@ when isMainModule:
     " ss t tt y yy yyy yyyy yyyyy z zz zzz ZZZ") == 
     "19 19 Tue Tuesday 3 03 3 03 14 14 1 01 Jan January 7 07 A AM 8 38 038 2038 02038 0 00 00:00 UTC"
   
-  var t2 = getGMTime(TTime(160070789)) # Mon 27 Jan 16:06:29 GMT 1975
+  var t2 = getGMTime(fromSeconds(160070789)) # Mon 27 Jan 16:06:29 GMT 1975
   assert t2.format("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 ZZZ") ==
     "27 27 Mon Monday 4 04 16 16 6 06 1 01 Jan January 29 29 P PM 5 75 975 1975 01975 0 00 00:00 UTC"
   
-  when sizeof(TTime) == 8:
-    var t3 = getGMTime(TTime(889067643645)) # Fri  7 Jun 19:20:45 BST 30143
+  when not defined(JS) and sizeof(TTime) == 8:
+    var t3 = getGMTime(fromSeconds(889067643645)) # Fri  7 Jun 19:20:45 BST 30143
     assert t3.format("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 ZZZ") == 
       "7 07 Fri Friday 6 06 18 18 20 20 6 06 Jun June 45 45 P PM 3 43 143 0143 30143 0 00 00:00 UTC"
     assert t3.format(":,[]()-/") == ":,[]()-/" 
   
-  var t4 = getGMTime(TTime(876124714)) # Mon  6 Oct 08:58:34 BST 1997
+  var t4 = getGMTime(fromSeconds(876124714)) # Mon  6 Oct 08:58:34 BST 1997
   assert t4.format("M MM MMM MMMM") == "10 10 Oct October"