ref: d6883b7f794b12741cb0246142daa5355e9ea279
parent: 264e4e6588d35226e110e08a92eae75295e962b9
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Aug 28 15:32:16 EDT 2014
Add preliminary support for time zones.
--- a/lib/date/Makefile
+++ b/lib/date/Makefile
@@ -1,6 +1,7 @@
MYRLIB=date
MYRSRC= \
date.myr \
+ types.myr \
zoneinfo.myr \
MYRFLAG=-I .
--- a/lib/date/date.myr
+++ b/lib/date/date.myr
@@ -1,21 +1,8 @@
use std
+use "types.use"
+use "zoneinfo.use"
pkg date =
- type date = struct
- actual : std.time /* epoch time in microseconds */
- tzoff : diff /* timezone offset in microseconds */
- year : int /* year, starting at 0 (ie, 1 BCE) */
- mon : int /* month, [1..12] */
- day : int /* day, [1..31] */
- wday : int /* weekday, [0..6] */
- h : int /* hour: [0..23] */
- m : int /* minute: [0..59] */
- s : int /* second: [0..59] */
- us : int /* microsecond: [0..999,999] */
- ;;
-
- type diff = std.time
-
/* date i/o */
const parse : (d : byte[:] -> date)
const parsefmt : (fmt : byte[:], d : byte[:] -> date)
@@ -25,7 +12,7 @@
/* useful constructors */
const mkdate : (tm : std.time, tz : diff -> date)
- const now : (-> date)
+ const now : (tz : byte[:] -> date)
const utcnow : (-> date)
const localoff : (-> diff)
const tzoff : (tzname : byte[:] -> diff)
@@ -39,16 +26,16 @@
const Days400y = 365*400 + 4*25 - 3
const Days4y = 365*4 + 1
-const now = {
- -> utcnow()
-}
-
-const utcnow = {
+const now = {tz : byte[:]
var tm
tm = std.now()
- std.put("tm = %l\n", tm)
- -> mkdate(tm, 0)
+ std.put("%l\n", _zoneinfo.findtzoff(tz, tm))
+ -> mkdate(tm, _zoneinfo.findtzoff(tz, tm))
+}
+
+const utcnow = {
+ -> mkdate(std.now(), 0)
}
const mkdate = {tm, off
--- /dev/null
+++ b/lib/date/types.myr
@@ -1,0 +1,18 @@
+use std
+
+pkg date =
+ type date = struct
+ actual : std.time /* epoch time in microseconds */
+ tzoff : diff /* timezone offset in microseconds */
+ year : int /* year, starting at 0 (ie, 1 BCE) */
+ mon : int /* month, [1..12] */
+ day : int /* day, [1..31] */
+ wday : int /* weekday, [0..6] */
+ h : int /* hour: [0..23] */
+ m : int /* minute: [0..59] */
+ s : int /* second: [0..59] */
+ us : int /* microsecond: [0..999,999] */
+ ;;
+
+ type diff = std.time
+;;
--- a/lib/date/zoneinfo.myr
+++ b/lib/date/zoneinfo.myr
@@ -1,8 +1,11 @@
use std
+use "types.use"
-pkg _timezone =
+pkg _zoneinfo =
type zifile
+ const findtzoff : (tz : byte[:], tm : std.time -> date.diff)
const load : (file : byte[:] -> zifile#)
+ const free : (f : zifile# -> void)
;;
type zifile = struct
@@ -21,26 +24,45 @@
abbrind : byte
;;
-const load = {file
- var nisgmt
- var nisstd
- var nleap
- var ntime
- var ntype
- var nchar
+const findtzoff = {tz, tm
+ var path
+ var zone
+ var cur
+ var ds
var i
- var f
- var p
+ /* load zone */
+ match std.getenv("ZI")
+ | `std.Some zi: path = zi
+ | `std.None: path = "/etc/localtime"
+ ;;
+ zone = load(path)
+
+ /* find applicable gmt offset */
+ cur = (tm / 1_000_000) castto(int32)
+ if zone.time.len == 0
+ -> 0
+ ;;
+ for i = 0; i < zone.time.len && cur < zone.time[i]; i++
+ /* nothing */
+ ;;
+ ds = zone.ttinfo[zone.timetype[i]].gmtoff
+ free(zone)
+ -> (ds castto(date.diff)) * 1_000_000
+}
+
+const load = {file
+ var nisgmt, nisstd, nleap, ntime, ntype, nchar
+ var i, f, p
+
/* check magic */
match std.slurp(file)
| `std.Ok d: p = d
| `std.Fail m:
- std.put("unable to load zone: %s\n", m)
-> std.zalloc()
;;
- if !std.sleq(p[:4], "TZif")
+ if !std.sleq(p[:4], "TZif\0")
std.put("%s is not a zone info file\n", file)
-> std.zalloc()
;;
@@ -92,8 +114,18 @@
(f.isgmt[i], p) = fetchbe8(p)
;;
-
-> f
+}
+
+const free = {zi
+ std.slfree(zi.time)
+ std.slfree(zi.timetype)
+ std.slfree(zi.ttinfo)
+ std.slfree(zi.abbrev)
+ std.slfree(zi.leap)
+ std.slfree(zi.isstd)
+ std.slfree(zi.isgmt)
+ std.free(zi)
}
const fetchbe32 = {sl