tzinfoex
v0.8.0
Published
parse tzinfo files
Downloads
14
Readme
tzinfoex
Functions to parse /usr/share/zoneinfo timezone info files. Parses both v1 and v2 format zoneinfo files.
What is tzinfo
tzinfo is a collection of files holding records of past and future timestamps with changes of timezone offsets to universal time at those timestamps. All timestamps in the database are in seconds from the epoch.
Generally speaking a timezone is represented by info_t
record with fields:
ttimes
- a array of numbers holding the timestampstypes
- a array of numbers, the same size asttimes
- the number of offset type valid after the correspondingttimes
timestamp; a index intotzinfo
tzinfo
- a object of typetzinfo_change_t
describing a offset from the universal time
With that information available you can say at (almost) any given universal time what is the current offset for the zone and when the next offset (DST) is about to happen.
API
function locateZoneinfoDirectory( ):string;
Detects system's zone info directory between /usr/share/zoneinfo
and /usr/lib/zoneinfo
, This is used at module load time for auto configuration. All directory related setup should be automagical.
function getZoneinfoDirectory( )
Return the auto-detected/currently set directory containing the system zoneinfo files.
function setZoneinfoDirectory(dir:string);
Override the auto-detected directory containing the system zoneinfo files
function listZoneinfoFiles( dirname:string|undefined, strip_prefix:boolean=false ):string[];
List all the zoneinfo files contained in the dirname
directory. Recursively
walks the directory and tests each file found. This is a blocking operation, so call
only on program load. The results are small and can be easily cached.
- The
dirname
can be set toundefined
to use the auto-detected directory - The
strip_prefix
has default value offalse
and indicates whether entries in the list will contain azoneinfoDirectory
prefix or look more like time zone names. - Called with no parameters the function will return filenames from the auto-detected directory
precacheZones
function does almost the same amount of work, asynchronously, usually completes under one second and can register all zone names while enabling speedy, case insensitive lookups via getCachedZoneInfo
.
export function readZoneinfoFile( tzname:string ):Promise<Buffer> ;
export function readZoneinfoFile( tzname:string, cb:(err: NodeJS.ErrnoException | null, data: Buffer) => void ):void ;
Read the zoneinfo file corresponding to the named timezone.
if the cb
is provided it should take two parameters: err
and data
. If err is falsy data
holds the timezone file content that need to be further parsed via parseZoneinfo
if no cb
is provided a promise that resolves to Buffer
is returned
function readZoneinfoFileSync( tzname:string ):Buffer;
Read the zoneinfo file corresponding to the named timezone. Returns a Buffer
containing the file contents, or throws an Error
.
function parseZoneinfo( buf:Buffer ):info_t|false;
Parse the zoneinfo file contained in buf
and return it as an object of type info_t
. If buf
contains invalid data a false
is returned
Returned object format:
export interface info_t {
magic: string; // 'TZif'
version: string; // '\0' or '2'
ttisgmtcnt: number, // num gmt/local indicators stored in `ttisgmt`
ttisstdcnt: number, // num standard/wall indicators stored in `ttisstd`
leapcnt: number, // num leap seconds for which data is stored in `leaps`
timecnt: number, // num transition types stored in `types'
typecnt: number, // num time transition structs stored in `tzinfo`
charcnt: number, // total num chars to store the tz name abbreviations
ttimes: number[], // transition time timestamps (timecnt)
types: number[], // tzinfo index of each time transitioned to (timecnt)
tzinfo: tzinfo_change_t[], // tzinfo structs (typecnt)
abbrevs: string, // concatenated tz name abbreviations (asciiz strings totaling charcnt bytes)
leaps: unknown[], // leap second descriptors (leapcnt)
ttisstd: unknown[], // transitions of tzinfo were std or wallclock times (ttisstdcnt)
ttisgmt: unknown[], // transitions of tzinfo were UTC or local time (ttisgmtcnt)
_v1end: number,
_v2end: number,
}
function findTzinfo( info:info_t, date:number|Date|string, firstIfTooOld:boolean ) : false|tzinfo_change_ex_t;
Searches for the date
in info
for the corresponding tzinfo_change_t
struct and return it extended with the corresponding ttime
timestamp as start
and the used index in ttime
. If date
is a number it is considered as time in miliseconds since the epoch. On error false
is returned like when the date
is before the earliest
time transition on record or if date
is not valid. If date
precedes the first known
time transition but firstIfTooOld
is truthy, it returns the oldest tzinfo struct.
If there are no time transitions defined but there is a tzinfo struct, it returns the
tzinfo struct (to always succeed for GMT and UTC).
tzinfo_change_t is defined as
interface tzinfo_change_ex_t extends tzinfo_change_t {
startat:number; //miliseconds since epoch or 0 if unknown (better use ttimes_index for unknown indicator)
ttimes_index:number; //index to ttimes/types arrays or -1 if unknown
}
To find the POSIX-style timezone environment variable attributes associated with this tzinfo
,
look at zoneinfo.ttisstd[tzinfo.idx]
and zoneinfo.ttisgmt[tzinfo.idx]
.
function nextTzinfo(info: info_t, current: tzinfo_change_ex_t): false | tzinfo_change_ex_t
Finds the next change after current
. Returns false if no more changes are expected
function getCachedZoneInfo(zonename:string):Promise<info_t>;
Combines readZoneinfoFile
, parseZoneinfo
and caches the result
function precacheZones(capture_canonical_names?:string[]):Promise<true>;
Asynchronously precache all zone info data. Post completion getCachedZoneInfo
is just map lookup. getCachedZoneInfo
does not depend on precacheZones
but it will benefit significantly from the precache in expense of sub 10MB of RAM. Beside speed improvements zone name lookup becomes case insensitive as all zones are now known and such lookup can be done easily. If you want to capture the list of canonical zone names e.g. Europe/Paris etc, you need to pass an empty array as capture_canonical_names
parameter. Zone names will be pushed there before a lowercase version is stored in internal map. With a SSD disk and i5 circa 2011 the precaching of recent zone info database takes about 600ms. Heap usage goes up by 9MB while the database is calculated as 5MB ondisk.
function getPreCachedZoneInfo(zonename:string):info_t|false {
Do a lookup the precached maps and return the zone info if found. If precacheZones
has not yet completed (usually under a second) the function will return false
. false
is also returned if unknown zonename is requested.
Example
import { getCachedZoneInfo, findTzinfo, nextTzinfo } from "tzinfo";
getCachedZoneInfo('Europe/Sofia').then(zi=>{
if (!zi) process.exit(-1);
let now=findTzinfo(zi, Date.now(),true);
if (now==false) {
console.error("The database seems broken?");
process.exit(-1);
}
console.log("current offset in this tz is "+now.tt_gmtoff+" seconds or "+now.tt_gmtoff/3600+' hours in effect sice '+new Date(now.startat)+' idx:'+now.ttimes_index);
let next=nextTzinfo(zi,now);
if (next==false) {
console.log("no shifts in offset are planned!");
} else {
console.log("next change in offset will happen at "+new Date(next.startat-1)+' new offset will be '+next.tt_gmtoff+" seconds or "+next.tt_gmtoff/3600+' hours');
}
}).catch(err=>{
console.error(err);
process.exit(-1);
})
Change Log
- 0.8.0 - getPreCachedZoneInfo no-promises lookup of precached data
- 0.7.0 - precacheZones, case insensitive zone name lookup
- 0.6.0 - Port to TS, add getCachedZoneInfo, remove zoneinfoDir export, documentation changes
- 0.5.1 - always find GMT zoneinfo
- 0.5.0 - findTzinfo option to return the oldest known tzinfo struct for very old dates
- 0.4.2 - more tests, make
readStringZ
stop on unterminated strings - 0.4.1 - npm tag
- 0.4.0 -
listZoneinfoFiles()
,getZoneinfoDirectory()
- 0.3.0 -
readZoneinfoFile
andreadZoneinfoFileSync
,findTzinfo
- 0.2.0 - first published release, with
parseZoneinfo
Related Work
- zoneinfo
tzfile(5)
,zdump(8)
,zic(8)
- unix zoneinfo manpages