diff options
author | Ori Bernstein <ori@eigenstate.org> | 2014-08-29 21:59:25 -0400 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2014-08-29 21:59:25 -0400 |
commit | a68cb156d015fcebef274f372d2061496acc90c5 (patch) | |
tree | 84092fdc689985193f1601e675ef3af28255dc95 /lib/date | |
parent | 33f429bcdd5beeed24a8650320e9d3a83ce2d6f5 (diff) | |
download | mc-a68cb156d015fcebef274f372d2061496acc90c5.tar.gz |
Add preliminary, untested parsing.
Diffstat (limited to 'lib/date')
-rw-r--r-- | lib/date/Makefile | 2 | ||||
-rw-r--r-- | lib/date/date.myr | 2 | ||||
-rw-r--r-- | lib/date/fmt.myr | 17 | ||||
-rw-r--r-- | lib/date/parse.myr | 204 |
4 files changed, 211 insertions, 14 deletions
diff --git a/lib/date/Makefile b/lib/date/Makefile index 9467a12..4a0088b 100644 --- a/lib/date/Makefile +++ b/lib/date/Makefile @@ -2,6 +2,8 @@ MYRLIB=date MYRSRC= \ date.myr \ fmt.myr \ + names.myr \ + parse.myr \ types.myr \ zoneinfo.myr \ diff --git a/lib/date/date.myr b/lib/date/date.myr index fe75a58..fc2bcc3 100644 --- a/lib/date/date.myr +++ b/lib/date/date.myr @@ -124,6 +124,8 @@ const sub = {d, dt -> mkdate(d.actual - (dt castto(std.time)), d.tzname) } + + const diff = {a, b -> (b.actual - a.actual) castto(diff) } diff --git a/lib/date/fmt.myr b/lib/date/fmt.myr index 722280c..3ba50c1 100644 --- a/lib/date/fmt.myr +++ b/lib/date/fmt.myr @@ -1,5 +1,7 @@ use std + use "types.use" +use "names.use" pkg date = const fmt : (d : instant, time : bool -> byte[:]) @@ -37,11 +39,6 @@ const ftime = {f, d -> buf[:sz] } -const abbrevday = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] -const fullday = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] -const abbrevmon = ["NONE", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] -const fullmon = ["NONE", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] - const bftime = {buf, f, d var c var o @@ -52,10 +49,10 @@ const bftime = {buf, f, d if c == '%' (c, f) = std.striter(f) match c - | 'a': o += std.bfmt(buf[o:], "%s", abbrevday[d.day]) - | 'A': o += std.bfmt(buf[o:], "%s", fullday[d.day]) - | 'b': o += std.bfmt(buf[o:], "%s", abbrevmon[d.mon]) - | 'B': o += std.bfmt(buf[o:], "%s", fullmon[d.mon]) + | 'a': o += std.bfmt(buf[o:], "%s", _names.abbrevday[d.day]) + | 'A': o += std.bfmt(buf[o:], "%s", _names.fullday[d.day]) + | 'b': o += std.bfmt(buf[o:], "%s", _names.abbrevmon[d.mon]) + | 'B': o += std.bfmt(buf[o:], "%s", _names.fullmon[d.mon]) | 'c': o += bftime(buf[o:], "%Y-%m-%d", d) | 'C': o += std.bfmt(buf[o:], "%02i", d.year % 100) | 'd': o += std.bfmt(buf[o:], "%02i", d.day) @@ -66,7 +63,7 @@ const bftime = {buf, f, d | 'G': o += std.bfmt(buf[o:], ...? | 'g': */ - | 'h': o += std.bfmt(buf[o:], "%s", abbrevmon[d.mon]) + | 'h': o += std.bfmt(buf[o:], "%s", _names.abbrevmon[d.mon]) | 'H': o += std.bfmt(buf[o:], "%02i", d.h) | 'I': o += std.bfmt(buf[o:], "%02i", d.h % 12) | 'j': o += std.bfmt(buf[o:], "year day... unimplemented.") diff --git a/lib/date/parse.myr b/lib/date/parse.myr index e989719..4911e7b 100644 --- a/lib/date/parse.myr +++ b/lib/date/parse.myr @@ -1,11 +1,207 @@ use std -use "date.use" + +use "types.use" +use "names.use" pkg date = /* date i/o */ - const parse : (d : byte[:] -> instant) - const parsefmt : (fmt : byte[:], d : byte[:] -> instant) - const parsez : (d : byte[:], tz : byte[:] -> instant) + const parse : (s : byte[:] -> std.option(instant)) + const parsez : (s : byte[:], tz : byte[:] -> std.option(instant)) + const parsefmt : (f : byte[:], s: byte[:] -> std.option(instant)) + const parsefmtz : (f : byte[:], s: byte[:], tz : byte[:] -> std.option(instant)) ;; +const Default = "%Y-%m-%d" + +const parse = {s; -> parsefmtz(Default, s, "")} +const parsez = {s, tz; -> parsefmtz(Default, s, tz)} +const parsefmt = {f, s; -> parsefmtz(f, s, "")} +const parsefmtz = {f, s, tz + var d + var err + + err = false + s = filldate(&d, f, s, tz, &err) + if err || s.len > 0 + -> `std.None + ;; + -> `std.Some d +} + +generic intval = {s : byte[:], min : @a::(numeric,integral), max : @a::(numeric,integral), err : bool#-> (@a::(numeric,integral), byte[:]) + var i + var c + var num + + num = s + for i = 0; i < min; i++ + (c, s) = std.striter(s) + if !std.isdigit(c) + err# = true + -> (0, s) + ;; + ;; + for i = min ; i < max; i++ + (c, s) = std.striter(s) + if !std.isdigit(c) + break + ;; + ;; + num = num[:i] + match std.intparse(num) + | `std.Some v: -> (v, s) + | `std.None: + err# = true + -> (0, s) + ;; +} + + +const filldate = {d, f, s, tz, err -> byte[:] + var fc, sc + var d + + while f.len != 0 + (fc, f) = std.striter(f) + if fc == '%' + (fc, f) = std.striter(f) + match fc + /* named things */ + | 'a': (d.day, s) = indexof(s, _names.abbrevday, err) + | 'A': (d.day, s) = indexof(s, _names.fullday, err) + | 'b': (d.day, s) = indexof(s, _names.abbrevmon, err) + | 'B': (d.day, s) = indexof(s, _names.fullmon, err) + | 'c': s = filldate(d, "%Y-%m-%d", s, tz, err) + | 'C': + (d.year, s) = intval(s, 2, 2, err) + d.year += 1900 + | 'd': (d.day, s) = intval(s, 2, 2, err) + | 'D': s = filldate(d, "%m/%d/%y", s, tz, err) + | 'e': (d.day, s) = intval(s, 1, 2, err) + | 'F': s = filldate(d, "%y-%m-%d", s, tz, err) + /* + | 'G': o += std.bfmt(buf[o:], ...? + | 'g': + */ + | 'h': (d.day, s) = indexof(s, _names.abbrevmon, err) + | 'H': (d.h, s) = intval(s, 2, 2, err) + | 'I': (d.h, s) = intval(s, 2, 2, err) + | 'j': std.fatal(1, "year day... unimplemented.") + | 'k': (d.h, s) = intval(s, 1, 2, err) + | 'l': (d.h, s) = intval(s, 1, 2, err) + | 'm': (d.mon, s) = intval(s, 1, 2, err) + | 'M': (d.m, s) = intval(s, 1, 2, err) + | 'n': s = matchstr(s, "\n", err) + | 'O': std.fatal(1, "unsupported %O") + | 'p': s = matchampm(d, s, err) + | 'P': s = matchampm(d, s, err) + | 'r': s = filldate(d, "%H:%M:%S %P", s, tz, err) + | 'R': s = filldate(d, "%H:%M %P", s, tz, err) + | 's': (d.actual, s) = intval(s, 1, 64, err) + | 'S': (d.s, s) = intval(s, 1, 2, err) + | 't': s = eatspace(s) + | 'u': (d.wday, s) = intval(s, 1, 1, err) + | 'U': std.fatal(1, "week number... unimplemented.") + /* + | 'x': o += bftime(buf[o:], Datefmt, d) + | 'X': o += bftime(buf[o:], Timefmt, d) + */ + | 'y': (d.year, s) = intval(s, 1, 2, err) + d.year += 1900 + | 'Y': (d.year, s) = intval(s, 1, 4, err) + /* + | 'z': o += timezone(buf[o:], d.tzoff) + | 'Z': o += std.bfmt(buf[o:], "%s", d.tzname) + */ + | '%': s = matchstr(s, "%", err) + ;; + else + (sc, s) = std.striter(s) + if std.isspace(sc) + s = eatspace(s) + elif (sc != fc) + err# = true + -> s + ;; + ;; + if err# + -> s + ;; + ;; + -> s +} + +const eatspace = {s + var c + + while std.isspace(std.decode(s)) + (c, s) = std.striter(s) + ;; + -> s +} + +const indexof = {s, set, err + var i + for i = 0; i < set.len; i++ + if s.len >= set[i].len && std.streq(s, set[i]) + -> (i, s[set[i].len:]) + ;; + ;; + err# = true + -> (0, s) +} + +const matchstr = {s, str, err + if s.len <= str.len || !std.sleq(s[:str.len], str) + err# = true + -> "" + ;; + -> s[str.len:] +} + +const matchampm = {d, s, err + if s.len < 2 + err# = true + -> s + ;; + if std.sleq(s[:2], "am") || std.sleq(s[:2], "AM") + -> s[2:] + elif std.sleq(s[:2], "pm") || std.sleq(s[:2], "PM") + d.h += 12 + -> s[2:] + else + err# = true + -> s + ;; +} + +/* +const time = {date + var t + var c, y, ya, m, u + + t = 0 + + if date.mon > 2 + m = (date.mon - 3) castto(std.time) + else + m = (date.mon + 9) castto(std.time) + y = (date.year - 1) castto(std.time) + ;; + + c = y / 100 + ya = y - 100 * c + u = (146097 * c) / 4 + \ + (1461 * ya) / 4 + \ + (153 * m + 2) / 5 + \ + (date.day castto(std.time)) + \ + UnixJulianDiff + t += (u * 24*60*60*1_000_000) + t += (date.h castto(std.time)) * 60*60*1_000_000 + t += (date.m castto(std.time)) * 60*1_000_000 + t += (date.s castto(std.time)) * 1_000_000 + t += date.us castto(std.time) + -> t +} +*/ |