diff options
author | Simon Hafner <hafnersimon@gmail.com> | 2013-04-13 13:57:06 -0500 |
---|---|---|
committer | Simon Hafner <hafnersimon@gmail.com> | 2013-04-13 13:57:06 -0500 |
commit | 4deaae98306effd887703f8b7493b0d9c91efbc9 (patch) | |
tree | 7dd618e643899d2930a520eee5f9f907f29a6829 /lib | |
parent | 45185f84dfcb8f4f16734fcd22f91834621c60e7 (diff) | |
download | Nim-4deaae98306effd887703f8b7493b0d9c91efbc9.tar.gz |
added toSeconds and fromSeconds to times. fixes #334
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/times.nim | 166 |
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" |