walltime-js
Version:
A javascript library for easily translating a UTC time to a "Wall Time" for a particular time zone and back.
561 lines (399 loc) • 21.6 kB
text/coffeescript
should = require "should"
helpers = require "../lib/olson/helpers"
OlsonReader = require "../lib/olson/reader"
OlsonCommon = require "../lib/olson/common"
WallTime = require "../lib/walltime"
TimeZoneTime = require "../lib/olson/timezonetime"
OlsonZone = OlsonCommon.Zone
OlsonZoneSet = OlsonCommon.ZoneSet
describe "walltime-js", ->
rules = {}
zones = {}
noSave =
hours: 0
mins: 0
dstSave =
hours: 1
mins: 0
readTimezoneFile = (file = "./test/rsrc/full/northamerica", next) ->
reader = new OlsonReader
reader.singleFile file, (result) ->
should.exist result?.zones, "should have zones in result"
should.exist result?.rules, "should have rules in result"
rules = JSON.parse(JSON.stringify(result.rules))
zones[zoneName] = zoneVal.zones for own zoneName, zoneVal of result.zones
do next
beforeEach ->
WallTime.rules = undefined
WallTime.zones = undefined
WallTime.doneInit = false
describe "init", ->
before (next) ->
readTimezoneFile "./test/rsrc/full/northamerica", next
it "requires an init call to load the rules and zones", ->
should.exist WallTime.init
WallTime.init rules, zones
should.exist WallTime.rules["US"], "rule"
should.exist WallTime.zones["America/Chicago"], "zone"
it "throws an error if you fail to init with rules and zones before setting the time zone", ->
setTimeZoneWithNoInit = -> WallTime.setTimeZone "America/Chicago"
setTimeZoneWithNoInit.should.throw()
describe "setTimeZone", ->
before (next) ->
readTimezoneFile "./test/rsrc/full/northamerica", next
it "allows you to set the time zone", ->
should.exist WallTime.setTimeZone
WallTime.init rules, zones
WallTime.setTimeZone "America/Chicago"
WallTime.zoneSet.name.should.equal "America/Chicago"
it "throws an error if the time zone is not found", ->
WallTime.init rules, zones
emptyName = -> WallTime.setTimeZone ""
emptyName.should.throw()
###
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule US 1918 1919 - Mar lastSun 2:00 1:00 D
Rule US 1918 1919 - Oct lastSun 2:00 0 S
Rule US 1942 only - Feb 9 2:00 1:00 W # War
Rule US 1945 only - Aug 14 23:00u 1:00 P # Peace
Rule US 1945 only - Sep 30 2:00 0 S
Rule US 1967 2006 - Oct lastSun 2:00 0 S
Rule US 1967 1973 - Apr lastSun 2:00 1:00 D
Rule US 1974 only - Jan 6 2:00 1:00 D
Rule US 1975 only - Feb 23 2:00 1:00 D
Rule US 1976 1986 - Apr lastSun 2:00 1:00 D
Rule US 1987 2006 - Apr Sun>=1 2:00 1:00 D
Rule US 2007 max - Mar Sun>=8 2:00 1:00 D
Rule US 2007 max - Nov Sun>=1 2:00 0 S
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
Rule Chicago 1920 only - Jun 13 2:00 1:00 D
Rule Chicago 1920 1921 - Oct lastSun 2:00 0 S
Rule Chicago 1921 only - Mar lastSun 2:00 1:00 D
Rule Chicago 1922 1966 - Apr lastSun 2:00 1:00 D
Rule Chicago 1922 1954 - Sep lastSun 2:00 0 S
Rule Chicago 1955 1966 - Oct lastSun 2:00 0 S
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Chicago -5:50:36 - LMT 1883 Nov 18 12:09:24
-6:00 US C%sT 1920
-6:00 Chicago C%sT 1936 Mar 1 2:00
-5:00 - EST 1936 Nov 15 2:00
-6:00 Chicago C%sT 1942
-6:00 US C%sT 1946
-6:00 Chicago C%sT 1967
-6:00 US C%sT
###
firstOffset =
negative: true
hours: 5
mins: 50
secs: 36
sixOffset =
negative: true
hours: 6
mins: 0
secs: 0
fiveOffset =
negative: true
hours: 5
mins: 0
secs: 0
commonWallTimeTest = (point, zoneName, expectSave, expectWallTime) ->
WallTime.init rules, zones
WallTime.setTimeZone zoneName
result = WallTime.UTCToWallTime point
result.save.hours.should.equal expectSave.hours
result.save.mins.should.equal expectSave.mins
result.utc.should.equal point, "UTC time"
result.wallTime.getTime().should.equal expectWallTime.wallTime.getTime(), "WallTimes: #{result.wallTime.toUTCString()} :: #{expectWallTime.wallTime.toUTCString()}"
describe "UTCToWallTime", ->
it "can be called before setTimeZone as long as zone is passed", ->
WallTime.init rules, zones
currTime = new Date().getTime()
result = WallTime.UTCToWallTime currTime, "America/Chicago"
should.exist result
it "throws an error when you don't setTimeZone and don't pass a zone", ->
WallTime.init rules, zones
currTime = new Date().getTime()
result = null
callFunc = ->
result = WallTime.UTCToWallTime currTime
callFunc.should.throw()
should.not.exist result
describe "UTCToWallTime (America/Chicago)", ->
before (next) ->
readTimezoneFile "./test/rsrc/full/northamerica", next
it "can convert Jul 26 2013, 6:50 AM", ->
WallTime.init rules, zones
chicagoTime = WallTime.UTCToWallTime(1374839400000, "America/Chicago")
chicagoTime.getFullYear().should.equal(2013)
chicagoTime.getMonth().should.equal(6)
chicagoTime.getDate().should.equal(26)
chicagoTime.getHours().should.equal(6)
chicagoTime.getMinutes().should.equal(50)
it "can translate a UTC Time to Chicago Wall Time for times before the first zone line", ->
# Before any zones
point = helpers.Time.MakeDateFromParts 1880, 0, 1
expect = new TimeZoneTime point, { offset: firstOffset }, noSave
commonWallTimeTest point, "America/Chicago", noSave, expect
it "can translate a UTC Time to Chicago Wall Time for times at the end of first zone line", ->
# Right at the end of the first zone line
point = helpers.Time.MakeDateFromParts 1883, 10, 18, 12, 9, 23
point = helpers.Time.ApplyOffset point, firstOffset
expect = new TimeZoneTime point, { offset: firstOffset }, noSave
commonWallTimeTest point, "America/Chicago", noSave, expect
it "can translate a UTC Time to Chicago Wall Time for times after the first zone line with -6:00 offset", ->
# Right after the end of the first zone line
point = helpers.Time.MakeDateFromParts 1883, 10, 18, 12, 9, 24
# We use the first offset here because we want it to match the end of the first rule
point = helpers.Time.ApplyOffset point, firstOffset
expect = new TimeZoneTime point, { offset: sixOffset }, noSave
commonWallTimeTest point, "America/Chicago", noSave, expect
it "can apply daylight savings for the first US Rule zone line", ->
# Right after the end of the first zone line
point = helpers.Time.MakeDateFromParts 1918, 2, 31, 2, 0, 1
point = helpers.Time.ApplyOffset point, sixOffset
expect = new TimeZoneTime point, { offset: sixOffset }, dstSave
commonWallTimeTest point, "America/Chicago", dstSave, expect
it "can go back to standard time for the first US Rule zone line", ->
# Right after the end of the first zone line
point = helpers.Time.MakeDateFromParts 1918, 9, 31, 2, 0, 1
point = helpers.Time.ApplyOffset point, sixOffset
# Apply the save because we would be in daylight savings from the previous move
point = helpers.Time.ApplySave point, dstSave
expect = new TimeZoneTime point, { offset: sixOffset }, noSave
commonWallTimeTest point, "America/Chicago", noSave, expect
it "can translate this years rule before DST", ->
# Right before the time zone switch
point = helpers.Time.StandardTimeToUTC sixOffset, 2012, 2, 11, 1, 59
#console.log point.toUTCString()
#console.log point.toUTCString()
point.getUTCHours().should.equal 7
expect = new TimeZoneTime point, { offset: sixOffset }, noSave
commonWallTimeTest point, "America/Chicago", noSave, expect
it "can translate this years rule after DST on 3/11 at 2:00 AM", ->
# Right after the time zone switch
point = helpers.Time.MakeDateFromParts 2012, 2, 11, 2, 0
point = helpers.Time.ApplyOffset point, sixOffset
expect = new TimeZoneTime point, { offset: sixOffset }, dstSave
commonWallTimeTest point, "America/Chicago", dstSave, expect
it "can translate this years rule during the middle of DST", ->
# Middle of DST
point = helpers.Time.MakeDateFromParts 2012, 4, 11, 2, 0
point = helpers.Time.ApplyOffset point, sixOffset
# Apply a DST because we would have had one applied.
point = helpers.Time.ApplySave point, dstSave
expect = new TimeZoneTime point, { offset: sixOffset }, dstSave
commonWallTimeTest point, "America/Chicago", dstSave, expect
it "can translate this years rule before the switch back to DST", ->
# End of DST
point = helpers.Time.WallTimeToUTC sixOffset, dstSave, 2012, 10, 4, 1, 59
expect = new TimeZoneTime point, { offset: sixOffset }, dstSave
commonWallTimeTest point, "America/Chicago", dstSave, expect
it "can translate this years rule after the switch back to DST on 11/4 at 2:00 AM", ->
# After DST
point = helpers.Time.MakeDateFromParts 2012, 10, 4, 2, 0
point = helpers.Time.ApplyOffset point, sixOffset
# Apply a DST because we would have had one applied.
point = helpers.Time.ApplySave point, dstSave
expect = new TimeZoneTime point, { offset: sixOffset }, noSave
commonWallTimeTest point, "America/Chicago", noSave, expect
describe "WallTimeToUTC (America/Chicago)", ->
before (next) ->
readTimezoneFile "./test/rsrc/full/northamerica", next
commonUTCTimeTest = (point, expect, zoneName = "America/Chicago") ->
WallTime.init rules, zones
WallTime.setTimeZone zoneName
#console.log point.toUTCString()
#console.log "\n"+expect.toUTCString()
result = WallTime.WallTimeToUTC zoneName, point
#console.log result.toUTCString()
result.should.equal expect
it "can translate wall time before the first zone line to UTC", ->
expect = helpers.Time.MakeDateFromParts 1880, 0, 1
point = helpers.Time.UTCToStandardTime expect, firstOffset
commonUTCTimeTest point, expect
it "can translate wall time at the end of the first zone line", ->
expect = helpers.Time.StandardTimeToUTC firstOffset, 1883, 10, 18, 12, 9, 23
point = helpers.Time.UTCToStandardTime expect, firstOffset
commonUTCTimeTest point, expect
it "can translate wall time after the end of the first zone line", ->
# We are preparing the "point" by using the firstOffset and just adding 2 seconds after the end of the first zone line.
expect = helpers.Time.StandardTimeToUTC firstOffset, 1883, 10, 18, 12, 9, 25
point = helpers.Time.UTCToStandardTime expect, firstOffset
# What we actually are expecting should have the sixOffset value
expect = helpers.Time.StandardTimeToUTC sixOffset, 1883, 10, 18, 12, 9, 25
commonUTCTimeTest point, expect
it "can translate wall time after the first zone line", ->
expect = helpers.Time.MakeDateFromParts 1900, 0, 1
point = helpers.Time.UTCToStandardTime expect, sixOffset
commonUTCTimeTest point, expect
it "can translate this years wall time before DST", ->
expect = helpers.Time.StandardTimeToUTC sixOffset, 2012, 2, 11, 1, 59, 59
point = helpers.Time.UTCToStandardTime expect, sixOffset
commonUTCTimeTest point, expect
it "can translate this years wall time after DST", ->
# Priming without dst save
expect = helpers.Time.StandardTimeToUTC sixOffset, 2012, 2, 11, 2
point = helpers.Time.UTCToStandardTime expect, sixOffset
# What we are expecting should have a dstSave applied.
expect = helpers.Time.WallTimeToUTC sixOffset, dstSave, 2012, 2, 11, 2
commonUTCTimeTest point, expect
it "can translate this years wall time during DST", ->
# Priming without dst save
expect = helpers.Time.StandardTimeToUTC fiveOffset, 2012, 7, 28, 12
point = helpers.Time.UTCToStandardTime expect, fiveOffset
commonUTCTimeTest point, expect
describe "IsAmbiguous (America/Chicago)", ->
before (next) ->
readTimezoneFile "./test/rsrc/full/northamerica", next
beforeEach ->
WallTime.init rules, zones
WallTime.setTimeZone "America/Chicago"
it "reports false for before DST", ->
result = WallTime.IsAmbiguous "America/Chicago", 2012, 0, 1
result.should.equal false
it "reports true for DST transition (2:00 AM, Mar 11, 2012)", ->
result = WallTime.IsAmbiguous "America/Chicago", 2012, 2, 11, 2, 0
result.should.equal true
it "reports false for before DST reset", ->
result = WallTime.IsAmbiguous "America/Chicago", 2012, 5, 1
result.should.equal false
it "reports true for DST reset transtion (1:00 AM, Nov 4, 2012)", ->
result = WallTime.IsAmbiguous "America/Chicago", 2012, 10, 4, 1
result.should.equal true
describe "UTCToWallTime (Australia/Adelaide)", ->
###
Daylight savings in Australia/Adelaide is generally opposite of the united states.
GMT Offset is +9:30.
Enter Daylight savings (Spring Forward) on October 7, 2012 3:00 AM -> 2:00 AM
Leave Daylights savings (Fall Back) on April 1, 2012 2:00 AM -> 3:00 AM
###
Mar28_8AM_2012 = 1332883800000
Apr3_8AM_2012 = 1333405800000
Sep28_8AM_2012 = 1348785000000
Oct10_8AM_2012 = 1349818200000
Jan4_8AM_2013 = 1357248600000
testTimestamp = (ts, yr, month, day, hr, min) ->
result = WallTime.UTCToWallTime ts
result.getFullYear().should.equal yr, "Year"
result.getMonth().should.equal month, "Month"
result.getDate().should.equal day, "Day"
result.getHours().should.equal hr, "Hour"
result.getMinutes().should.equal min, "Minute"
before (next) ->
readTimezoneFile "./test/rsrc/full/australasia", next
beforeEach ->
WallTime.init rules, zones
WallTime.setTimeZone "Australia/Adelaide"
# Before the DST Transition
it "can translate March 28 2012, 8:00 AM correctly", ->
testTimestamp Mar28_8AM_2012, 2012, 2, 28, 8, 0
# After the DST Transition
it "can translate April 3 2012, 8:00 AM correctly", ->
testTimestamp Apr3_8AM_2012, 2012, 3, 3, 8, 0
# During the DST Transition
it "can translate September 28 2012, 8:00 AM correctly", ->
testTimestamp Sep28_8AM_2012, 2012, 8, 28, 8, 0
# After the DST Regression
it "can translate October 10 2012, 8:00 AM correctly", ->
testTimestamp Oct10_8AM_2012, 2012, 9, 10, 8, 0
# After the DST Regression beginning of year
it "can translate January 4 2013, 8:00 AM correctly", ->
testTimestamp Jan4_8AM_2013, 2013, 0, 4, 8, 0
describe "WallTimeToUTC (Australia/Adelaide)", ->
###
Daylight savings in Australia/Adelaide is generally opposite of the united states.
GMT Offset is +9:30.
Enter Daylight savings (Spring Forward) on October 7, 2012 3:00 AM -> 2:00 AM
Leave Daylights savings (Fall Back) on April 1, 2012 2:00 AM -> 3:00 AM
###
Mar28_8AM_2012 = 1332883800000
Apr3_8AM_2012 = 1333405800000
Sep28_8AM_2012 = 1348785000000
Oct10_8AM_2012 = 1349818200000
Jan4_8AM_2013 = 1357248600000
testTimestamp = (ts, yr, month, day, hr, min) ->
result = WallTime.WallTimeToUTC "Australia/Adelaide", yr, month, day, hr, min
result.getTime().should.equal ts, "Timestamp"
before (next) ->
readTimezoneFile "./test/rsrc/full/australasia", next
beforeEach ->
WallTime.init rules, zones
WallTime.setTimeZone "Australia/Adelaide"
# Before the DST Transition
it "can translate March 28 2012, 8:00 AM correctly", ->
testTimestamp Mar28_8AM_2012, 2012, 2, 28, 8, 0
# After the DST Transition
it "can translate April 3 2012, 8:00 AM correctly", ->
testTimestamp Apr3_8AM_2012, 2012, 3, 3, 8, 0
# During the DST Transition
it "can translate September 28 2012, 8:00 AM correctly", ->
testTimestamp Sep28_8AM_2012, 2012, 8, 28, 8, 0
# After the DST Regression
it "can translate October 10 2012, 8:00 AM correctly", ->
testTimestamp Oct10_8AM_2012, 2012, 9, 10, 8, 0
# After the DST Regression beginning of year
it "can translate January 4 2013, 8:00 AM correctly", ->
testTimestamp Jan4_8AM_2013, 2013, 0, 4, 8, 0
describe "UTCToWallTime (America/Chihuahua)", ->
Mar28_8AM_2012 = 1332946800000
Apr3_8AM_2012 = 1333461600000
Sep28_8AM_2012 = 1348840800000
Oct10_8AM_2012 = 1349877600000
Jan4_8AM_2013 = 1357311600000
testTimestamp = (ts, yr, month, day, hr, min) ->
result = WallTime.UTCToWallTime ts
result.getFullYear().should.equal yr, "Year"
result.getMonth().should.equal month, "Month"
result.getDate().should.equal day, "Day"
result.getHours().should.equal hr, "Hour"
result.getMinutes().should.equal min, "Minute"
before (next) ->
readTimezoneFile "./test/rsrc/full/northamerica", next
beforeEach ->
WallTime.init rules, zones
WallTime.setTimeZone "America/Chihuahua"
it "can set timezone to America/Chihuahua", ->
WallTime.timeZoneName.should.equal "America/Chihuahua"
# Before the DST Transition
it "can translate March 28 2012, 8:00 AM correctly", ->
testTimestamp Mar28_8AM_2012, 2012, 2, 28, 8, 0
# After the DST Transition
it "can translate April 3 2012, 8:00 AM correctly", ->
testTimestamp Apr3_8AM_2012, 2012, 3, 3, 8, 0
# During the DST Transition
it "can translate September 28 2012, 8:00 AM correctly", ->
testTimestamp Sep28_8AM_2012, 2012, 8, 28, 8, 0
# After the DST Regression
it "can translate October 10 2012, 8:00 AM correctly", ->
testTimestamp Oct10_8AM_2012, 2012, 9, 10, 8, 0
# After the DST Regression beginning of year
it "can translate January 4 2013, 8:00 AM correctly", ->
testTimestamp Jan4_8AM_2013, 2013, 0, 4, 8, 0
describe "UTCToWallTime (America/Regina)", ->
sixOffset =
negative: true
hours: 6
mins: 0
secs: 0
Mar28_8AM_2012 = helpers.Time.MakeDateFromParts 2012, 2, 28, 8
Mar28_8AM_2012 = helpers.Time.ApplyOffset Mar28_8AM_2012, sixOffset
testTimestamp = (ts, yr, month, day, hr, min) ->
result = WallTime.UTCToWallTime ts
result.getFullYear().should.equal yr, "Year"
result.getMonth().should.equal month, "Month"
result.getDate().should.equal day, "Day"
result.getHours().should.equal hr, "Hour"
result.getMinutes().should.equal min, "Minute"
before (next) ->
readTimezoneFile "./test/rsrc/full/northamerica", next
beforeEach ->
WallTime.init rules, zones
WallTime.setTimeZone "America/Regina"
it "can set timezone to America/Regina", ->
WallTime.timeZoneName.should.equal "America/Regina"
local = WallTime.UTCToWallTime new Date(), "America/Regina"
local.zone.name.should.equal("America/Regina")
# Before the DST Transition
it "can translate March 28 2012, 8:00 AM correctly", ->
testTimestamp Mar28_8AM_2012, 2012, 2, 28, 8, 0