summaryrefslogtreecommitdiff
path: root/lib/date
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-09-21 22:18:08 -0700
committerOri Bernstein <ori@eigenstate.org>2015-09-22 09:43:57 -0700
commitf7228d204a9cbe40f7b6286ba8987ef65691bfbd (patch)
tree07ad9b15a06191661e5a02e157d3e002d32ed48a /lib/date
parent19e038b0670828810453c284589469c6520aa7d9 (diff)
downloadmc-f7228d204a9cbe40f7b6286ba8987ef65691bfbd.tar.gz
Add period addition/subtraction.
Diffstat (limited to 'lib/date')
-rw-r--r--lib/date/date.myr75
-rw-r--r--lib/date/test/fmt.myr33
-rw-r--r--lib/date/types.myr8
-rw-r--r--lib/date/zoneinfo.myr4
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