Skip to content

Minimalist timezones for Node.js and the browser, inspired by moment-timezone

License

Notifications You must be signed in to change notification settings

bkon-connect/zt

Repository files navigation

zt

Minimalist timezones for Node.js and the browser, inspired by moment-timezone

Note: WIP

import zt from 'zt'
import assert from 'assert'

// `zt` operates on UTC timestamps (milliseconds since 1 Jan, 1970 UTC)

let ts = Date.UTC(2016, 2, 13, 7) // 13 Mar, 2016 07:00 UTC
assert.equal(ts, 1457852400000)

// It converts UTC timestamps to local time timestamps
// (milliseconds since 1 Jan, 1970 UTC, plus or minus whatever
// local adjustments are in effect *at the given time*,
// i.e. Daylight Savings Time)

ts = zt(ts, 'America/Chicago')    // 13 Mar, 2016 01:00 CST
assert.equal(ts, 1457830800000)

ts = Date.UTC(2016, 2, 13, 8)     // 13 Mar, 2016 08:00 UTC
assert.equal(ts, 1457856000000)   // one hour later in UTC time...

ts = zt(ts, 'America/Chicago')    // 13 Mar, 2016 03:00 CDT
assert.equal(ts, 1457838000000)   // ...is 2 hours later in local time,
                                  // because Daylight Savings Time 
                                  // went into effect

// Date objects can be used instead of timestamps...

let d = new Date(Date.UTC(2016, 2, 13, 7, 2, 3))

// ...and you'll get back a Date object in return...

d = zt(d, 'America/Chicago')

// ...which is convenient for formatted display in local time:

const pad = n => (n < 10 ? '0' : '') + n
const fmt = f => pad(d['getUTC' + f]())
const time = [fmt('Hours'), fmt('Minutes'), fmt('Seconds')].join(':')
assert.equal(time, '01:02:03')

// The local offset (in minutes) can be retrieved for a timestamp:

import {offset} from 'zt'

ts = Date.UTC(2016, 2, 13, 7)
let dm = offset(ts, 'America/Chicago')
assert.equal(dm, -360) // UTC - 6 hours (in minutes)

ts = Date.UTC(2016, 2, 13, 8)
dm = offset(ts, 'America/Chicago')
assert.equal(dm, -300) // UTC - 5 hours (in minutes)

// Apply an offset to a timestamp by converting to milliseconds...

ts += dm * 6e4 // (60000 milliseconds in an hour)

// ...which is all `zt()` really does:

ts = Date.UTC(2016, 2, 13, 8)
dm = offset(ts, 'America/Chicago')
assert.equal(zt(ts, 'America/Chicago'), ts + dm * 6e4)

// It can also convert local timestamps to UTC timestamps:

ts = Date.UTC(2016, 2, 13, 8)
ts = zt(ts, 'America/Chicago')        // UTC to local
ts = zt(ts, 'America/Chicago', true)  // local to UTC
assert.equal(ts, Date.UTC(2016, 2, 13, 8))

// Offsets can also be retrieved for local to UTC conversions...

ts = Date.UTC(2016, 2, 13, 8)
ts = zt(ts, 'America/Chicago')
dm = offset(ts, 'America/Chicago', true)
assert.equal(dm, 300)

// ...and are applied to local timestamps in the same way:

ts += dm * 6e4
assert.equal(ts, Date.UTC(2016, 2, 13, 8))

// Some local timestamps can't be directly converted to UTC,
// since the local time may be ambiguous (it happened more than
// once locally) or invalid (it never happened locally).

// For ambiguous conversions, the default is to use the *earliest*
// possible UTC time:

ts = Date.UTC(2016, 10, 6, 7)               // 6 Nov, 2016 07:00 UTC
ts = zt(ts, 'America/Chicago')              // 6 Nov, 2016 01:00 CST
ts = zt(ts, 'America/Chicago', true)        // 6 Nov, 2016 06:00 UTC
assert.equal(ts, Date.UTC(2016, 10, 6, 6))

// You can pass the `moveAmbiguousForward` option to use the *latest*
// possible UTC time instead:
let opts = {moveAmbiguousForward: true}
ts = Date.UTC(2016, 10, 6, 6)               // 6 Nov, 2016 06:00 UTC
ts = zt(ts, 'America/Chicago')              // 6 Nov, 2016 01:00 CDT
ts = zt(ts, 'America/Chicago', true, opts)  // 6 Nov, 2016 07:00 UTC
assert.equal(ts, Date.UTC(2016, 10, 6, 7))

// For invalid conversions, the default is to use the *earliest*
// valid UTC time:

ts = Date.UTC(2016, 2, 13, 8)               // 13 Mar, 2016 08:00 UTC
ts = zt(ts, 'America/Chicago')              // 13 Mar, 2016 03:00 CDT
ts -= 60 * 6e4                              // 13 Mar, 2016 02:00 CDT (invalid)
ts = zt(ts, 'America/Chicago', true)        // 13 Mar, 2016 07:00 UTC
assert.equal(ts, Date.UTC(2016, 2, 13, 7))

// You can pass the `moveInvalidForward` option to use the *latest*
// valid UTC time instead:

opts = {moveInvalidForward: true}
ts = Date.UTC(2016, 2, 13, 8)               // 13 Mar, 2016 08:00 UTC
ts = zt(ts, 'America/Chicago')              // 13 Mar, 2016 03:00 CDT
ts -= 60 * 6e4                              // 13 Mar, 2016 02:00 CDT (invalid)
ts = zt(ts, 'America/Chicago', true, opts)  // 13 Mar, 2016 08:00 UTC
assert.equal(ts, Date.UTC(2016, 2, 13, 8))

// The timezone abbreviation (which may change over time) can
// be retrieved for a given timestamp:

import {abbr} from 'zt'

ts = Date.UTC(2016, 2, 13, 7)
assert.equal(abbr(ts, 'America/Chicago'), 'CST')

ts = Date.UTC(2016, 2, 13, 8)
assert.equal(abbr(ts, 'America/Chicago'), 'CDT')

// Whether or not a given timestamp falls during Daylight Savings Time
// can be retrieved as well:

import {dst} from 'zt'

ts = Date.UTC(2016, 2, 13, 7)
assert.ok(!dst(ts, 'America/Chicago'))

ts = Date.UTC(2016, 2, 13, 8)
assert.ok(dst(ts, 'America/Chicago'))

Timezone Data

Timezone data is sourced from the moment-timezone project and uses a slightly modified version of the totally excellent moment-timezone packed format.

About

Minimalist timezones for Node.js and the browser, inspired by moment-timezone

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published