shithub: mc

Download patch

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