diff options
author | Ori Bernstein <ori@eigenstate.org> | 2015-09-21 22:18:08 -0700 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2015-09-22 09:43:57 -0700 |
commit | f7228d204a9cbe40f7b6286ba8987ef65691bfbd (patch) | |
tree | 07ad9b15a06191661e5a02e157d3e002d32ed48a /lib/date | |
parent | 19e038b0670828810453c284589469c6520aa7d9 (diff) | |
download | mc-f7228d204a9cbe40f7b6286ba8987ef65691bfbd.tar.gz |
Add period addition/subtraction.
Diffstat (limited to 'lib/date')
-rw-r--r-- | lib/date/date.myr | 75 | ||||
-rw-r--r-- | lib/date/test/fmt.myr | 33 | ||||
-rw-r--r-- | lib/date/types.myr | 8 | ||||
-rw-r--r-- | lib/date/zoneinfo.myr | 4 |
4 files changed, 99 insertions, 21 deletions
diff --git a/lib/date/date.myr b/lib/date/date.myr index c5589ce..0b0ebdb 100644 --- a/lib/date/date.myr +++ b/lib/date/date.myr @@ -9,18 +9,17 @@ pkg date = const tozone : (d : instant, zone : byte[:] -> instant) const mkinstant : (tm : std.time, zone : byte[:] -> instant) - const localoff : (tm : std.time -> delta) - const tzoff : (tzname : byte[:], tm : std.time -> delta) + const localoff : (tm : std.time -> duration) + const tzoff : (tzname : byte[:], tm : std.time -> duration) const isleap : (d : instant -> bool) /* date differences */ - const add : (d : instant, dt : delta -> instant) - const sub : (d : instant, dt : delta -> instant) - const delta : (a : instant, b : instant -> delta) - /* - const duradd : (d : instant, dt : period -> instant) - const dursub : (d : instant, dt : period -> instant) - */ + const add : (d : instant, dt : duration -> instant) + const sub : (d : instant, dt : duration -> instant) + const addperiod : (d : instant, dt : period -> instant) + const subperiod : (d : instant, dt : period -> instant) + + const duration : (a : instant, b : instant -> duration) ;; const Days400y = 365*400 + 4*25 - 3 @@ -71,13 +70,10 @@ const mkinstant = {tm, tz inst.us = (t % 1_000_000) castto(int) t /= 1_000_000 inst.s = (t % 60) castto(int) - std.assert(inst.s >= 0, "inst.s negative??\n") t /= 60 inst.m = (t % 60) castto(int) - std.assert(inst.m >= 0, "inst.m negative??\n") t /= 60 inst.h = t castto(int) - std.assert(inst.h >= 0, "inst.h negative??\n") /* weekday */ inst.wday = ((e + 4) % 7) castto(int) /* the world started on Thursday */ @@ -152,7 +148,58 @@ const sub = {d, dt -> mkinstant(d.actual - (dt castto(std.time)), d.tzname) } -const delta = {a, b - -> (b.actual - a.actual) castto(delta) +const addperiod = {inst, p + match p + | `Year y: inst.year += y + | `Month m: inst.mon += m + | `Day d: inst.day += d + | `Hour h: inst.h += h + | `Minute m: inst.m += m + | `Second s: inst.s += s + ;; + -> mkinstant(recalc(inst), inst.tzname) +} + +const subperiod = {inst, p + match p + | `Year y: inst.year -= y + | `Month m: inst.mon -= m + | `Day d: inst.day -= d + | `Hour h: inst.h -= h + | `Minute m: inst.m -= m + | `Second s: inst.s -= s + ;; + -> mkinstant(recalc(inst), inst.tzname) +} + +const duration = {a, b + -> (b.actual - a.actual) castto(duration) } +const recalc = {inst + var c, ya, j, tm + var year, mon, day + var h, m, s, us + + year = inst.year castto(std.time) + mon = inst.mon castto(std.time) + day = inst.day castto(std.time) + h = inst.h castto(std.time) + m = inst.m castto(std.time) + s = inst.s castto(std.time) + us = inst.us castto(std.time) + + if m > 2 + mon -= 3 + else + mon += 9 + year -= 1 + ;; + c = year / 100 + ya = year - 100 * c + j = (c*Days400y/4 + Days4y*ya/4 + (153*mon+2)/5 + day) + j -= 719469 + tm = j * DayUsec + tm += (3600*h + 60*m + s)*1_000_000 + us + -> tm +} diff --git a/lib/date/test/fmt.myr b/lib/date/test/fmt.myr index 4160315..369e32f 100644 --- a/lib/date/test/fmt.myr +++ b/lib/date/test/fmt.myr @@ -3,11 +3,13 @@ use date const main = { var buf : byte[1024] - var d + var d, s /* epoch */ d = date.mkinstant(0, "") eq("1970-1-01 00:00:00 +0000", std.bfmt(buf[:], "{D}", d)) + d = date.mkinstant(24*3600*1_000_000, "") + eq("1970-1-02 00:00:00 +0000", std.bfmt(buf[:], "{D}", d)) /* epoch + 12 hours */ d = date.mkinstant(12*3600*1_000_000, "") @@ -32,6 +34,35 @@ const main = { /* date in the bc */ d = date.mkinstant(-70000000000*1_000_000, "") eq("-249-11-19 19:33:20 +0000", std.bfmt(buf[:], "{D}", d)) + + /* test addition and subtraction of dates */ + d = date.mkinstant(-1, "") + d = date.addperiod(d, `date.Hour 1) + eq("1970-1-01 00:59:59 +0000", std.bfmt(buf[:], "{D}", d)) + + d = date.mkinstant(0, "") + d = date.addperiod(d, `date.Hour 24) + eq("1970-1-02 00:00:00 +0000", std.bfmt(buf[:], "{D}", d)) + + d = date.mkinstant(0, "") + d = date.addperiod(d, `date.Day 1) + eq("1970-1-02 00:00:00 +0000", std.bfmt(buf[:], "{D}", d)) + + d = date.subperiod(d, `date.Day 1) + eq("1970-1-01 00:00:00 +0000", std.bfmt(buf[:], "{D}", d)) + + d = date.subperiod(d, `date.Year 1) + eq("1969-1-01 00:00:00 +0000", std.bfmt(buf[:], "{D}", d)) + + d = date.mkinstant(12*3601*1_000_000, "") + for var i = 0; i < 50; i++ + d = date.addperiod(d, `date.Day 1) + d = date.addperiod(d, `date.Second 1) + s = std.fmt("1970-{}-{p=0,w=2} 12:{p=0,w=2}:{p=0,w=2} +0000", \ + (i+1)/31 + 1, (i+1)%31+1, (i+13)/60, (i+13)%60) + eq(s, std.bfmt(buf[:], "{D}", d)) + std.slfree(s) + ;; } const eq = {expected, actual diff --git a/lib/date/types.myr b/lib/date/types.myr index 6fbb0d0..e042e7e 100644 --- a/lib/date/types.myr +++ b/lib/date/types.myr @@ -3,7 +3,7 @@ use std pkg date = type instant = struct actual : std.time /* epoch time in microseconds */ - tzoff : delta /* timezone offset in microseconds */ + tzoff : duration /* timezone offset in microseconds */ year : int /* year, starting at 0 (ie, 1 BCE) */ mon : int /* month, [1..12] */ day : int /* day, [1..31] */ @@ -16,12 +16,12 @@ pkg date = _tzbuf : byte[32] /* current time zone name storage */ ;; - type delta = std.time + type duration = std.time type period = union - `Day int - `Month int `Year int + `Month int + `Day int `Hour int `Minute int `Second int diff --git a/lib/date/zoneinfo.myr b/lib/date/zoneinfo.myr index 9320519..88e6f06 100644 --- a/lib/date/zoneinfo.myr +++ b/lib/date/zoneinfo.myr @@ -5,7 +5,7 @@ use "types.use" pkg _zoneinfo = type zifile - const findtzoff : (tz : byte[:], tm : std.time -> date.delta) + const findtzoff : (tz : byte[:], tm : std.time -> date.duration) const load : (file : byte[:] -> zifile#) const free : (f : zifile# -> void) ;; @@ -70,7 +70,7 @@ const findtzoff = {tz, tm ;; ds = zone.ttinfo[zone.timetype[i]].gmtoff free(zone) - -> (ds castto(date.delta)) * 1_000_000 + -> (ds castto(date.duration)) * 1_000_000 } const load = {file |