Просмотр исходного кода

Sample code for timezone handling (#1853)

Philip Gladstone 7 лет назад
Родитель
Сommit
c0848ec66f

+ 56 - 0
lua_examples/timezone/README.md

@@ -0,0 +1,56 @@
+# tz module
+
+This is a simple module that parses timezone files as found on unix systems. It is oriented around converting the current time. It can convert other times, but it is
+rather less efficient as it maintains only a single cached entry in memory.
+
+On my linux system, these files can be found in `/usr/share/zoneinfo`. 
+
+
+## tz.setzone()
+
+This sets the timezone to be used in subsequent conversions
+
+#### Syntax
+`tz.setzone(timezone)`
+
+#### Parameters
+- `timezone` this is the timezone string. It must correspond to a file in the file system which is named timezone.zone.
+
+#### Returns
+true if the zone exists in the file system.
+
+## tz.getoffset()
+
+This gets the offset (in seconds) of the time passed as the argument.
+
+#### Syntax
+`tz.getoffset(time)`
+
+#### Parameters
+- `time` the number of seconds since the epoch. This is the same value as used by the `sntp` module.
+
+#### Returns
+
+- The number of seconds of offset. West of Greenwich is negative.
+- The start time (in epoch seconds) of this offset.
+- The end time (in epoch seconds) of this offset.
+
+#### Example
+```
+tz = require('tz')
+tz.setzone('eastern')
+sntp.sync(nil, function(now)
+  local tm = rtctime.epoch2cal(now + tz.getoffset(now))
+  print(string.format("%04d/%02d/%02d %02d:%02d:%02d", tm["year"], tm["mon"], tm["day"], tm["hour"], tm["min"], tm["sec"]))
+end)
+```
+
+## tz.getzones()
+
+This returns a list of the available timezones in the file system.
+
+#### Syntax
+`tz.getzones()`
+
+#### Returns
+A list of timezones.

BIN
lua_examples/timezone/alaska.zone


BIN
lua_examples/timezone/central.zone


BIN
lua_examples/timezone/eastern.zone


BIN
lua_examples/timezone/mountain.zone


BIN
lua_examples/timezone/pacific.zone


+ 81 - 0
lua_examples/timezone/tz.lua

@@ -0,0 +1,81 @@
+-- tz -- A simple timezone module for interpreting zone files
+
+local M = {}
+
+local tstart = 0
+local tend = 0
+local toffset = 0
+local thezone = "eastern"
+
+function M.setzone(zone)
+  thezone = zone
+  return M.exists(thezone)
+end
+
+function M.exists(zone)
+  return file.exists(zone .. ".zone")
+end
+
+function M.getzones()
+  local result = {}
+  for fn, _ in pairs(file.list()) do
+    local _, _, prefix = string.find(fn, "(.*).zone")
+    if prefix then
+      table.insert(result, prefix)
+    end
+  end
+  return result
+end
+
+function load(t)
+  local z = file.open(thezone .. ".zone", "r")
+
+  local hdr = z:read(20)
+  local magic = struct.unpack("c4 B", hdr)
+
+  if magic == "TZif" then
+      local lens = z:read(24)
+      local ttisgmt_count, ttisdstcnt, leapcnt, timecnt, typecnt, charcnt = struct.unpack("> LLLLLL", lens)
+    
+      local times = z:read(4 * timecnt)
+      local typeindex = z:read(timecnt)
+      local ttinfos = z:read(6 * typecnt)
+    
+      z:close()
+      
+      local offset = 1
+      local tt
+      for i = 1, timecnt do
+        tt = struct.unpack(">l", times, (i - 1) * 4 + 1)
+        if t < tt then
+          offset = (i - 2)
+          tend = tt
+          break
+        end
+        tstart = tt
+      end
+      
+      local tindex = struct.unpack("B", typeindex, offset + 1)
+      toffset = struct.unpack(">l", ttinfos, tindex * 6 + 1)
+  else
+      tend = 0x7fffffff
+      tstart = 0
+  end
+end
+
+
+function M.getoffset(t)
+  if t < tstart or t >= tend then
+    -- Ignore errors
+    local ok, msg = pcall(function ()
+        load(t)
+    end)
+    if not ok then
+      print (msg)
+    end
+  end
+
+  return toffset, tstart, tend
+end
+
+return M