Sample code for timezone handling (#1853)

This commit is contained in:
Philip Gladstone 2017-03-10 16:09:36 -05:00 committed by Marcel Stör
parent f562ef8fc1
commit c0848ec66f
7 changed files with 137 additions and 0 deletions

View File

@ -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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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