summaryrefslogtreecommitdiff
path: root/lib/date
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2017-11-19 19:13:00 -0800
committerOri Bernstein <ori@eigenstate.org>2017-11-20 21:54:54 -0800
commit2da5de43f610bfd33116a06631a4eaa85deb811d (patch)
tree1a343c079d5575c8652cb4ded7520fc599614953 /lib/date
parentf637a3c144fe69410d7134cfe57b95258bfabe1f (diff)
downloadmc-2da5de43f610bfd33116a06631a4eaa85deb811d.tar.gz
Cache timezone info.
Loading and parsing zoneinfo files every time we print a date? eugh.
Diffstat (limited to 'lib/date')
-rw-r--r--lib/date/zoneinfo+posixy.myr54
1 files changed, 32 insertions, 22 deletions
diff --git a/lib/date/zoneinfo+posixy.myr b/lib/date/zoneinfo+posixy.myr
index 69b2e85..33edd03 100644
--- a/lib/date/zoneinfo+posixy.myr
+++ b/lib/date/zoneinfo+posixy.myr
@@ -32,6 +32,11 @@ const zonepath = [
"/etc/zoneinfo"
]
+var zonecache : std.htab(byte[:], zifile#)#
+const __init__ = {
+ zonecache = std.mkht()
+}
+
const findtzoff = {tz, tm -> std.option(date.duration)
var path
var zone
@@ -40,26 +45,32 @@ const findtzoff = {tz, tm -> std.option(date.duration)
var ds
var i
- /* load zone */
- if std.sleq(tz, "") || std.sleq(tz, "UTC")
- -> `std.Some 0
- elif std.sleq(tz, "local")
- path = std.sldup("/etc/localtime")
- else
- path = ""
- for z : zonepath
- path = std.pathcat(z, tz)
- if sys.stat(path, &sb) == 0
- goto found
+ match std.htget(zonecache, tz)
+ | `std.Some z:
+ zone = z
+ | `std.None:
+ /* load zone */
+ if std.sleq(tz, "") || std.sleq(tz, "UTC")
+ -> `std.Some 0
+ elif std.sleq(tz, "local")
+ path = std.sldup("/etc/localtime")
+ else
+ path = ""
+ for z : zonepath
+ path = std.pathcat(z, tz)
+ if sys.stat(path, &sb) == 0
+ goto found
+ ;;
+ std.slfree(path)
;;
std.slfree(path)
+ -> `std.None
;;
+ :found
+ zone = load(path)
std.slfree(path)
- -> `std.None
+ std.htput(zonecache, std.sldup(tz), zone)
;;
-:found
- zone = load(path)
- std.slfree(path)
/* find applicable gmt offset */
cur = (tm / 1_000_000 : int32)
@@ -70,28 +81,26 @@ const findtzoff = {tz, tm -> std.option(date.duration)
/* nothing */
;;
ds = zone.ttinfo[zone.timetype[i]].gmtoff
- free(zone)
-> `std.Some ((ds : date.duration) * 1_000_000)
}
const load = {file
var nisgmt, nisstd, nleap, ntime, ntype, nchar
- var i, f, p
+ var i, f, p, data
/* check magic */
match std.slurp(file)
- | `std.Ok d: p = d
- | `std.Err m:
- -> std.zalloc()
+ | `std.Ok d: data = d
+ | `std.Err m: -> std.zalloc()
;;
- if !std.sleq(p[:4], "TZif")
+ if !std.eq(data[:4], "TZif")
std.put("{} is not a zone info file\n", file)
-> std.zalloc()
;;
/* skip to data */
- p = p[20:]
+ p = data[20:]
(nisgmt, p) = fetchbe32(p)
(nisstd, p) = fetchbe32(p)
(nleap, p) = fetchbe32(p)
@@ -136,6 +145,7 @@ const load = {file
for i = 0; i < nisgmt; i++
(f.isgmt[i], p) = fetchbe8(p)
;;
+ std.slfree(data)
-> f
}