summary refs log tree commit diff stats
path: root/lib/pure/times.nim
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2009-06-08 08:06:25 +0200
committerAndreas Rumpf <rumpf_a@web.de>2009-06-08 08:06:25 +0200
commit4d4b3b1c04d41868ebb58bd9ccba7b303007e900 (patch)
tree909ed0aad0b145733521f4ac2bfb938dd4b43785 /lib/pure/times.nim
parentce88dc3e67436939b03f97e624c11ca6058fedce (diff)
downloadNim-4d4b3b1c04d41868ebb58bd9ccba7b303007e900.tar.gz
version0.7.10
Diffstat (limited to 'lib/pure/times.nim')
-rw-r--r--lib/pure/times.nim307
1 files changed, 307 insertions, 0 deletions
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
new file mode 100644
index 000000000..793b55ead
--- /dev/null
+++ b/lib/pure/times.nim
@@ -0,0 +1,307 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2009 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+
+## This module contains routines and types for dealing with time.
+## This module is available for the ECMAScript target.
+
+{.push debugger:off .} # the user does not want to trace a part
+                       # of the standard library!
+
+import
+  strutils
+
+type
+  TMonth* = enum ## represents a month
+    mJan, mFeb, mMar, mApr, mMay, mJun, mJul, mAug, mSep, mOct, mNov, mDec
+  TWeekDay* = enum ## represents a weekday
+    dMon, dTue, dWed, dThu, dFri, dSat, dSun
+    
+when defined(posix): 
+  type
+    TTime* = abstract int ## abstract type that represents a time
+elif defined(windows):
+  when defined(vcc):
+    # newest version of Visual C++ defines time_t to be of 64 bits
+    type TTime* = abstract int64
+  else:
+    type TTime* = abstract int32
+elif defined(ECMAScript):
+  type
+    TTime* {.final.} = 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
+      getUTCDate: proc (): int
+      getUTCFullYear: proc (): int
+      getUTCHours: proc (): int
+      getUTCMilliseconds: proc (): int
+      getUTCMinutes: proc (): int
+      getUTCMonth: proc (): int
+      getUTCSeconds: 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
+
+type
+  TTimeInfo* = object of TObject ## represents a time in different parts
+    second*: range[0..61]     ## The number of seconds after the minute,
+                              ## normally in the range 0 to 59, but can
+                              ## be up to 61 to allow for leap seconds.
+    minute*: range[0..59]     ## The number of minutes after the hour,
+                              ## in the range 0 to 59.
+    hour*: range[0..23]       ## The number of hours past midnight,
+                              ## in the range 0 to 23.
+    monthday*: range[1..31]   ## The day of the month, in the range 1 to 31.
+    month*: TMonth            ## The current month.
+    year*: int                ## The current year.
+    weekday*: TWeekDay        ## The current day of the week.
+    yearday*: range[0..365]   ## The number of days since January 1,
+                              ## in the range 0 to 365.
+                              ## Always 0 if the target is ECMAScript.
+
+proc getTime*(): TTime ## gets the current calendar time
+proc getLocalTime*(t: TTime): TTimeInfo
+  ## converts the calendar time `t` to broken-time representation,
+  ## expressed relative to the user's specified time zone.
+proc getGMTime*(t: TTime): TTimeInfo
+  ## converts the calendar time `t` to broken-down time representation,
+  ## expressed in Coordinated Universal Time (UTC).
+
+proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime
+  ## converts a broken-down time structure, expressed as local time, to
+  ## calendar time representation. The function ignores the specified
+  ## contents of the structure members `weekday` and `yearday` and recomputes
+  ## them from the other information in the broken-down time structure.
+
+proc `$` *(timeInfo: TTimeInfo): string
+  ## converts a `TTimeInfo` object to a string representation.
+proc `$` *(time: TTime): string
+  ## converts a calendar time to a string representation.
+
+proc getDateStr*(): string
+  ## gets the current date as a string of the format
+  ## ``YYYY-MM-DD``.
+proc getClockStr*(): string
+  ## gets the current clock time as a string of the format ``HH:MM:SS``.
+
+proc `-` *(a, b: TTime): int64
+  ## computes the difference of two calendar times. Result is in seconds.
+
+proc `<` * (a, b: TTime): bool = 
+  ## returns true iff ``a < b``, that is iff a happened before b.
+  result = a - b < 0
+  
+proc `<=` * (a, b: TTime): bool = 
+  ## returns true iff ``a <= b``.
+  result = a - b <= 0
+
+proc getStartMilsecs*(): int
+  ## get the miliseconds from the start of the program
+
+
+when not defined(ECMAScript):  
+  # C wrapper:
+  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
+  
+    PTimeInfo = ptr structTM
+    PTime = ptr TTime
+  
+    TClock {.importc: "clock_t".} = range[low(int)..high(int)]
+  
+  proc localtime(timer: PTime): PTimeInfo {.
+    importc: "localtime", header: "<time.h>".}
+  proc gmtime(timer: PTime): PTimeInfo {.importc: "gmtime", header: "<time.h>".}
+  proc timec(timer: PTime): TTime      {.importc: "time", header: "<time.h>".}
+  proc mktime(t: structTM): TTime      {.importc: "mktime", header: "<time.h>".}
+  proc asctime(tblock: structTM): CString {.
+    importc: "asctime", header: "<time.h>".}
+  proc ctime(time: PTime): CString     {.importc: "ctime", header: "<time.h>".}
+  #  strftime(s: CString, maxsize: int, fmt: CString, t: tm): int {.
+  #    importc: "strftime", header: "<time.h>".}
+  proc clock(): TClock {.importc: "clock", header: "<time.h>".}
+  proc difftime(a, b: TTime): float {.importc: "difftime", header: "<time.h>".}
+  
+  var
+    clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int
+  
+  
+  # our own procs on top of that:
+  proc tmToTimeInfo(tm: structTM): TTimeInfo =
+    const
+      weekDays: array [0..6, TWeekDay] = [
+        dSun, dMon, dTue, dWed, dThu, dFri, dSat]
+    result.second = int(tm.second)
+    result.minute = int(tm.minute)
+    result.hour = int(tm.hour)
+    result.monthday = int(tm.monthday)
+    result.month = TMonth(tm.month)
+    result.year = tm.year + 1900'i32
+    result.weekday = weekDays[int(tm.weekDay)]
+    result.yearday = int(tm.yearday)
+  
+  proc timeInfoToTM(t: TTimeInfo): structTM =
+    const
+      weekDays: array [TWeekDay, int] = [1, 2, 3, 4, 5, 6, 0]
+    result.second = t.second
+    result.minute = t.minute
+    result.hour = t.hour
+    result.monthday = t.monthday
+    result.month = ord(t.month)
+    result.year = t.year - 1900
+    result.weekday = weekDays[t.weekDay]
+    result.yearday = t.yearday
+    result.isdst = -1
+  
+  proc `-` (a, b: TTime): int64 =
+    return toBiggestInt(difftime(a, b))
+  
+  proc getStartMilsecs(): int = return clock() div (clocksPerSec div 1000)
+  proc getTime(): TTime = return timec(nil)
+  proc getLocalTime(t: TTime): TTimeInfo =
+    var a = t
+    result = tmToTimeInfo(localtime(addr(a))^)
+    # copying is needed anyway to provide reentrancity; thus
+    # the convertion is not expensive
+  
+  proc getGMTime(t: TTime): TTimeInfo =
+    var a = t
+    result = tmToTimeInfo(gmtime(addr(a))^)
+    # copying is needed anyway to provide reentrancity; thus
+    # the convertion is not expensive
+  
+  proc TimeInfoToTime(timeInfo: TTimeInfo): TTime =
+    var cTimeInfo = timeInfo # for C++ we have to make a copy,
+    # because the header of mktime is broken in my version of libc
+    return mktime(timeInfoToTM(cTimeInfo))
+    
+  proc toStringTillNL(p: cstring): string = 
+    result = ""
+    var i = 0
+    while p[i] != '\0' and p[i] != '\10' and p[i] != '\13': 
+      add(result, p[i])
+      inc(i)
+    return result
+    
+  proc `$`(timeInfo: TTimeInfo): string =
+    # BUGFIX: asctime returns a newline at the end!
+    var p = asctime(timeInfoToTM(timeInfo))
+    result = toStringTillNL(p)
+  
+  proc `$`(time: TTime): string =
+    # BUGFIX: ctime returns a newline at the end!
+    var a = time
+    return toStringTillNL(ctime(addr(a)))
+
+  const
+    epochDiff = 116444736000000000'i64
+    rateDiff = 10000000'i64 # 100 nsecs
+
+  proc unixTimeToWinTime*(t: TTime): int64 = 
+    ## converts a UNIX `TTime` (``time_t``) to a Windows file time
+    result = int64(t) * rateDiff + epochDiff
+    
+  proc winTimeToUnixTime*(t: int64): TTime = 
+    ## converts a Windows time to a UNIX `TTime` (``time_t``)
+    result = TTime((t - epochDiff) div rateDiff)
+
+else:
+  proc getTime(): TTime {.importc: "new Date", nodecl.}
+
+  const
+    weekDays: array [0..6, TWeekDay] = [
+      dSun, dMon, dTue, dWed, dThu, dFri, dSat]
+  
+  proc getLocalTime(t: TTime): TTimeInfo =
+    result.second = t.getSeconds()
+    result.minute = t.getMinutes()
+    result.hour = t.getHours()
+    result.monthday = t.getDate()
+    result.month = TMonth(t.getMonth())
+    result.year = t.getFullYear()
+    result.weekday = weekDays[t.getDay()]
+    result.yearday = 0
+
+  proc getGMTime(t: TTime): TTimeInfo =
+    result.second = t.getUTCSeconds()
+    result.minute = t.getUTCMinutes()
+    result.hour = t.getUTCHours()
+    result.monthday = t.getUTCDate()
+    result.month = TMonth(t.getUTCMonth())
+    result.year = t.getUTCFullYear()
+    result.weekday = weekDays[t.getDay()]
+    result.yearday = 0
+  
+  proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime =
+    result = getTime()
+    result.setSeconds(timeInfo.second)
+    result.setMinutes(timeInfo.minute)
+    result.setHours(timeInfo.hour)
+    result.setMonth(ord(timeInfo.month))
+    result.setFullYear(timeInfo.year)
+    result.setDate(timeInfo.monthday)
+  
+  proc `$`(timeInfo: TTimeInfo): string = return $(TimeInfoToTIme(timeInfo))
+  proc `$`(time: TTime): string = $time.toLocaleString()
+    
+  proc `-` (a, b: TTime): int64 = 
+    return a.getTime() - b.getTime()
+  
+  var
+    startMilsecs = getTime()
+  
+  proc getStartMilsecs(): int =
+    ## get the miliseconds from the start of the program
+    return int(getTime() - startMilsecs)
+
+proc getDateStr(): string =
+  var ti = getLocalTime(getTime())
+  result = $ti.year & '-' & intToStr(ord(ti.month)+1, 2) &
+    '-' & intToStr(ti.monthDay, 2)
+
+proc getClockStr(): string =
+  var ti = getLocalTime(getTime())
+  result = intToStr(ti.hour, 2) & ':' & intToStr(ti.minute, 2) &
+    ':' & intToStr(ti.second, 2)
+
+{.pop.}