added toSeconds and fromSeconds to times. fixes #334
This commit is contained in:
parent
45185f84df
commit
4deaae9830
1 changed files with 100 additions and 66 deletions
|
|
@ -29,7 +29,7 @@ var
|
||||||
timezone {.importc, header: "<time.h>".}: int
|
timezone {.importc, header: "<time.h>".}: int
|
||||||
tzname {.importc, header: "<time.h>" .}: array[0..1, cstring]
|
tzname {.importc, header: "<time.h>" .}: array[0..1, cstring]
|
||||||
|
|
||||||
when defined(posix):
|
when defined(posix) and not defined(JS):
|
||||||
type
|
type
|
||||||
TTimeImpl {.importc: "time_t", header: "<sys/time.h>".} = int
|
TTimeImpl {.importc: "time_t", header: "<sys/time.h>".} = int
|
||||||
TTime* = distinct TTimeImpl ## distinct type that represents a time
|
TTime* = distinct TTimeImpl ## distinct type that represents a time
|
||||||
|
|
@ -62,45 +62,44 @@ elif defined(windows):
|
||||||
elif defined(JS):
|
elif defined(JS):
|
||||||
type
|
type
|
||||||
TTime* {.final, importc.} = object
|
TTime* {.final, importc.} = object
|
||||||
getDay: proc (): int
|
getDay: proc (): int {.tags: [].}
|
||||||
getFullYear: proc (): int
|
getFullYear: proc (): int {.tags: [].}
|
||||||
getHours: proc (): int
|
getHours: proc (): int {.tags: [].}
|
||||||
getMilliseconds: proc (): int
|
getMilliseconds: proc (): int {.tags: [].}
|
||||||
getMinutes: proc (): int
|
getMinutes: proc (): int {.tags: [].}
|
||||||
getMonth: proc (): int
|
getMonth: proc (): int {.tags: [].}
|
||||||
getSeconds: proc (): int
|
getSeconds: proc (): int {.tags: [].}
|
||||||
getTime: proc (): int
|
getTime: proc (): int {.tags: [].}
|
||||||
getTimezoneOffset: proc (): int
|
getTimezoneOffset: proc (): int {.tags: [].}
|
||||||
getDate: proc (): int
|
getDate: proc (): int {.tags: [].}
|
||||||
getUTCDate: proc (): int
|
getUTCDate: proc (): int {.tags: [].}
|
||||||
getUTCFullYear: proc (): int
|
getUTCFullYear: proc (): int {.tags: [].}
|
||||||
getUTCHours: proc (): int
|
getUTCHours: proc (): int {.tags: [].}
|
||||||
getUTCMilliseconds: proc (): int
|
getUTCMilliseconds: proc (): int {.tags: [].}
|
||||||
getUTCMinutes: proc (): int
|
getUTCMinutes: proc (): int {.tags: [].}
|
||||||
getUTCMonth: proc (): int
|
getUTCMonth: proc (): int {.tags: [].}
|
||||||
getUTCSeconds: proc (): int
|
getUTCSeconds: proc (): int {.tags: [].}
|
||||||
getUTCDay: proc (): int
|
getUTCDay: proc (): int {.tags: [].}
|
||||||
getYear: proc (): int
|
getYear: proc (): int {.tags: [].}
|
||||||
parse: proc (s: cstring): TTime
|
parse: proc (s: cstring): TTime {.tags: [].}
|
||||||
setDate: proc (x: int)
|
setDate: proc (x: int) {.tags: [].}
|
||||||
setFullYear: proc (x: int)
|
setFullYear: proc (x: int) {.tags: [].}
|
||||||
setHours: proc (x: int)
|
setHours: proc (x: int) {.tags: [].}
|
||||||
setMilliseconds: proc (x: int)
|
setMilliseconds: proc (x: int) {.tags: [].}
|
||||||
setMinutes: proc (x: int)
|
setMinutes: proc (x: int) {.tags: [].}
|
||||||
setMonth: proc (x: int)
|
setMonth: proc (x: int) {.tags: [].}
|
||||||
setSeconds: proc (x: int)
|
setSeconds: proc (x: int) {.tags: [].}
|
||||||
setTime: proc (x: int)
|
setTime: proc (x: int) {.tags: [].}
|
||||||
setUTCDate: proc (x: int)
|
setUTCDate: proc (x: int) {.tags: [].}
|
||||||
setUTCFullYear: proc (x: int)
|
setUTCFullYear: proc (x: int) {.tags: [].}
|
||||||
setUTCHours: proc (x: int)
|
setUTCHours: proc (x: int) {.tags: [].}
|
||||||
setUTCMilliseconds: proc (x: int)
|
setUTCMilliseconds: proc (x: int) {.tags: [].}
|
||||||
setUTCMinutes: proc (x: int)
|
setUTCMinutes: proc (x: int) {.tags: [].}
|
||||||
setUTCMonth: proc (x: int)
|
setUTCMonth: proc (x: int) {.tags: [].}
|
||||||
setUTCSeconds: proc (x: int)
|
setUTCSeconds: proc (x: int) {.tags: [].}
|
||||||
setYear: proc (x: int)
|
setYear: proc (x: int) {.tags: [].}
|
||||||
toGMTString: proc (): cstring
|
toGMTString: proc (): cstring {.tags: [].}
|
||||||
toLocaleString: proc (): cstring
|
toLocaleString: proc (): cstring {.tags: [].}
|
||||||
UTC: proc (): int
|
|
||||||
|
|
||||||
type
|
type
|
||||||
TTimeInfo* = object of TObject ## represents a time in different parts
|
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
|
timezone*: int ## The offset of the (non-DST) timezone in seconds
|
||||||
## west of UTC.
|
## 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
|
TTimeInterval* {.pure.} = object ## a time interval
|
||||||
miliseconds*: int ## The number of miliseconds
|
miliseconds*: int ## The number of miliseconds
|
||||||
seconds*: int ## The number of seconds
|
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
|
## contents of the structure members `weekday` and `yearday` and recomputes
|
||||||
## them from the other information in the broken-down time structure.
|
## 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
|
proc `$` *(timeInfo: TTimeInfo): string
|
||||||
## converts a `TTimeInfo` object to a string representation.
|
## converts a `TTimeInfo` object to a string representation.
|
||||||
proc `$` *(time: TTime): string
|
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
|
## returns true if ``a == b``, that is if both times represent the same value
|
||||||
result = a - b == 0
|
result = a - b == 0
|
||||||
|
|
||||||
proc getTzname*(): tuple[nonDST, DST: string] {.tags: [FTime].}
|
when not defined(JS):
|
||||||
## returns the local timezone; ``nonDST`` is the name of the local non-DST
|
proc getTzname*(): tuple[nonDST, DST: string] {.tags: [FTime].}
|
||||||
## timezone, ``DST`` is the name of the local DST timezone.
|
## 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].}
|
proc getTimezone*(): int {.tags: [FTime].}
|
||||||
## returns the offset of the local (non-DST) timezone in seconds west of UTC.
|
## 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
|
of mApr, mJun, mSep, mNov: result = 30
|
||||||
else: result = 31
|
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 anew = a
|
||||||
var newinterv = interval
|
var newinterv = interval
|
||||||
result = 0.0
|
result = 0
|
||||||
|
|
||||||
newinterv.months += interval.years * 12
|
newinterv.months += interval.years * 12
|
||||||
var curMonth = anew.month
|
var curMonth = anew.month
|
||||||
|
|
@ -228,32 +250,30 @@ proc calculateSeconds(a: TTimeInfo, interval: TTimeInterval): float =
|
||||||
curMonth.inc()
|
curMonth.inc()
|
||||||
result += float(newinterv.days * 24 * 60 * 60)
|
result += float(newinterv.days * 24 * 60 * 60)
|
||||||
result += float(newinterv.minutes * 60 * 60)
|
result += float(newinterv.minutes * 60 * 60)
|
||||||
result += newinterv.seconds.float
|
result += float(newinterv.seconds)
|
||||||
result += newinterv.miliseconds / 1000
|
result += newinterv.miliseconds / 1000
|
||||||
|
|
||||||
|
proc toSeconds*(a: TTime, interval: TTimeInterval): float =
|
||||||
|
result = toSeconds(getGMTime(a), interval)
|
||||||
|
|
||||||
proc `+`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
|
proc `+`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
|
||||||
## adds ``interval`` time.
|
## adds ``interval`` time.
|
||||||
##
|
##
|
||||||
## **Note:** This has been only briefly tested and it may not be
|
## **Note:** This has been only briefly tested and it may not be
|
||||||
## very accurate.
|
## very accurate.
|
||||||
let t = timeInfoToTime(a)
|
let t = toSeconds(TimeInfoToTime(a))
|
||||||
let secs = calculateSeconds(a, interval)
|
let secs = toSeconds(a, interval)
|
||||||
if a.tzname == "UTC":
|
if a.tzname == "UTC":
|
||||||
result = getGMTime(TTime(float(t) + secs))
|
result = getGMTime(fromSeconds(t + secs))
|
||||||
else:
|
else:
|
||||||
result = getLocalTime(TTime(float(t) + secs))
|
result = getLocalTime(fromSeconds(t + secs))
|
||||||
|
|
||||||
proc `-`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
|
proc `-`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
|
||||||
## subtracts ``interval`` time.
|
## subtracts ``interval`` time.
|
||||||
##
|
##
|
||||||
## **Note:** This has been only briefly tested, it is inaccurate especially
|
## **Note:** This has been only briefly tested, it is inaccurate especially
|
||||||
## when you subtract so much that you reach the Julian calendar.
|
## when you subtract so much that you reach the Julian calendar.
|
||||||
let t = timeInfoToTime(a)
|
result = a + -interval
|
||||||
let secs = calculateSeconds(a, interval)
|
|
||||||
if a.tzname == "UTC":
|
|
||||||
result = getGMTime(TTime(float(t) - secs))
|
|
||||||
else:
|
|
||||||
result = getLocalTime(TTime(float(t) - secs))
|
|
||||||
|
|
||||||
when not defined(JS):
|
when not defined(JS):
|
||||||
proc epochTime*(): float {.rtl, extern: "nt$1", tags: [FTime].}
|
proc epochTime*(): float {.rtl, extern: "nt$1", tags: [FTime].}
|
||||||
|
|
@ -274,8 +294,7 @@ when not defined(JS):
|
||||||
## doWork()
|
## doWork()
|
||||||
## echo "CPU time [s] ", cpuTime() - t0
|
## echo "CPU time [s] ", cpuTime() - t0
|
||||||
|
|
||||||
when not defined(JS):
|
when not defined(JS) and defined(POSIX):
|
||||||
|
|
||||||
# C wrapper:
|
# C wrapper:
|
||||||
type
|
type
|
||||||
structTM {.importc: "struct tm", final.} = object
|
structTM {.importc: "struct tm", final.} = object
|
||||||
|
|
@ -416,7 +435,11 @@ when not defined(JS):
|
||||||
|
|
||||||
proc getTimezone(): int =
|
proc getTimezone(): int =
|
||||||
return timezone
|
return timezone
|
||||||
|
|
||||||
|
proc fromSeconds(since1970: float): TTime = TTime(since1970)
|
||||||
|
|
||||||
|
proc toSeconds(time: TTime): float = float(time)
|
||||||
|
|
||||||
when not defined(useNimRtl):
|
when not defined(useNimRtl):
|
||||||
proc epochTime(): float =
|
proc epochTime(): float =
|
||||||
when defined(posix):
|
when defined(posix):
|
||||||
|
|
@ -437,8 +460,12 @@ when not defined(JS):
|
||||||
result = toFloat(int(clock())) / toFloat(clocksPerSec)
|
result = toFloat(int(clock())) / toFloat(clocksPerSec)
|
||||||
|
|
||||||
elif defined(JS):
|
elif defined(JS):
|
||||||
proc newDate(): TTime {.importc: "new Date", nodecl.}
|
proc newDate(): TTime {.importc: "new Date".}
|
||||||
proc getTime(): TTime = return newDate()
|
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
|
const
|
||||||
weekDays: array [0..6, TWeekDay] = [
|
weekDays: array [0..6, TWeekDay] = [
|
||||||
|
|
@ -486,6 +513,13 @@ elif defined(JS):
|
||||||
## get the miliseconds from the start of the program
|
## get the miliseconds from the start of the program
|
||||||
return int(getTime() - startMilsecs)
|
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].} =
|
proc getDateStr*(): string {.rtl, extern: "nt$1", tags: [FTime].} =
|
||||||
## gets the current date as a string of the format ``YYYY-MM-DD``.
|
## gets the current date as a string of the format ``YYYY-MM-DD``.
|
||||||
|
|
@ -680,7 +714,7 @@ when isMainModule:
|
||||||
# $ date --date='@2147483647'
|
# $ date --date='@2147483647'
|
||||||
# Tue 19 Jan 03:14:07 GMT 2038
|
# 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")
|
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"
|
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") ==
|
" 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"
|
"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" &
|
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") ==
|
" 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"
|
"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:
|
when not defined(JS) and sizeof(TTime) == 8:
|
||||||
var t3 = getGMTime(TTime(889067643645)) # Fri 7 Jun 19:20:45 BST 30143
|
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" &
|
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") ==
|
" 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"
|
"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(":,[]()-/") == ":,[]()-/"
|
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"
|
assert t4.format("M MM MMM MMMM") == "10 10 Oct October"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue