walltime-js
Version:
A javascript library for easily translating a UTC time to a "Wall Time" for a particular time zone and back.
359 lines (350 loc) • 9.66 kB
JavaScript
/*
* WallTime 0.2.0
* Copyright (c) 2013 Sprout Social, Inc.
* Available under the MIT License (http://bit.ly/walltime-license)
*/
(function() {
var Days, Milliseconds, Months, Time, helpers, _base;
(_base = Array.prototype).indexOf || (_base.indexOf = function(item) {
var i, x, _i, _len;
for (i = _i = 0, _len = this.length; _i < _len; i = ++_i) {
x = this[i];
if (x === item) {
return i;
}
}
return -1;
});
Days = {
DayShortNames: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
DayIndex: function(name) {
return this.DayShortNames.indexOf(name);
},
DayNameFromIndex: function(dayIdx) {
return this.DayShortNames[dayIdx];
},
AddToDate: function(dt, days) {
return Time.MakeDateFromTimeStamp(dt.getTime() + (days * Milliseconds.inDay));
}
};
Months = {
MonthsShortNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
CompareRuleMatch: new RegExp("([a-zA-Z]*)([\\<\\>]?=)([0-9]*)"),
MonthIndex: function(shortName) {
return this.MonthsShortNames.indexOf(shortName.slice(0, 3));
},
IsDayOfMonthRule: function(str) {
return str.indexOf(">") > -1 || str.indexOf("<") > -1 || str.indexOf("=") > -1;
},
IsLastDayOfMonthRule: function(str) {
return str.slice(0, 4) === "last";
},
DayOfMonthByRule: function(str, year, month) {
var compareFunc, compares, dateIndex, dayIndex, dayName, ruleParse, testDate, testPart, _ref;
ruleParse = this.CompareRuleMatch.exec(str);
if (!ruleParse) {
throw new Error("Unable to parse the 'on' rule for " + str);
}
_ref = ruleParse.slice(1, 4), dayName = _ref[0], testPart = _ref[1], dateIndex = _ref[2];
dateIndex = parseInt(dateIndex, 10);
if (dateIndex === NaN) {
throw new Error("Unable to parse the dateIndex of the 'on' rule for " + str);
}
dayIndex = helpers.Days.DayIndex(dayName);
compares = {
">=": function(a, b) {
return a >= b;
},
"<=": function(a, b) {
return a <= b;
},
">": function(a, b) {
return a > b;
},
"<": function(a, b) {
return a < b;
},
"=": function(a, b) {
return a === b;
}
};
compareFunc = compares[testPart];
if (!compareFunc) {
throw new Error("Unable to parse the conditional for " + testPart);
}
testDate = helpers.Time.MakeDateFromParts(year, month);
while (!(dayIndex === testDate.getUTCDay() && compareFunc(testDate.getUTCDate(), dateIndex))) {
testDate = helpers.Days.AddToDate(testDate, 1);
}
return testDate.getUTCDate();
},
LastDayOfMonthRule: function(str, year, month) {
var dayIndex, dayName, lastDay;
dayName = str.slice(4);
dayIndex = helpers.Days.DayIndex(dayName);
if (month < 11) {
lastDay = helpers.Time.MakeDateFromParts(year, month + 1);
} else {
lastDay = helpers.Time.MakeDateFromParts(year + 1, 0);
}
lastDay = helpers.Days.AddToDate(lastDay, -1);
while (lastDay.getUTCDay() !== dayIndex) {
lastDay = helpers.Days.AddToDate(lastDay, -1);
}
return lastDay.getUTCDate();
}
};
Milliseconds = {
inDay: 86400000,
inHour: 3600000,
inMinute: 60000,
inSecond: 1000
};
Time = {
Add: function(dt, hours, mins, secs) {
var newTs;
if (hours == null) {
hours = 0;
}
if (mins == null) {
mins = 0;
}
if (secs == null) {
secs = 0;
}
newTs = dt.getTime() + (hours * Milliseconds.inHour) + (mins * Milliseconds.inMinute) + (secs * Milliseconds.inSecond);
return this.MakeDateFromTimeStamp(newTs);
},
ParseGMTOffset: function(str) {
var isNeg, match, matches, reg, result;
reg = new RegExp("(-)?([0-9]*):([0-9]*):?([0-9]*)?");
matches = reg.exec(str);
result = matches ? (function() {
var _i, _len, _ref, _results;
_ref = matches.slice(2);
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
match = _ref[_i];
_results.push(parseInt(match, 10));
}
return _results;
})() : [0, 0, 0];
isNeg = matches && matches[1] === "-";
result.splice(0, 0, isNeg);
return result;
},
ParseTime: function(str) {
var match, matches, qual, reg, timeParts;
reg = new RegExp("(\\d*)\\:(\\d*)([wsugz]?)");
matches = reg.exec(str);
if (!matches) {
return [0, 0, ''];
}
timeParts = (function() {
var _i, _len, _ref, _results;
_ref = matches.slice(1, 3);
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
match = _ref[_i];
_results.push(parseInt(match, 10));
}
return _results;
})();
qual = matches[3] ? matches[3] : '';
timeParts.push(qual);
return timeParts;
},
ApplyOffset: function(dt, offset, reverse) {
var offset_ms;
offset_ms = (Milliseconds.inHour * offset.hours) + (Milliseconds.inMinute * offset.mins) + (Milliseconds.inSecond * offset.secs);
if (!offset.negative) {
offset_ms = offset_ms * -1;
}
if (reverse) {
offset_ms = offset_ms * -1;
}
return this.MakeDateFromTimeStamp(dt.getTime() + offset_ms);
},
ApplySave: function(dt, save, reverse) {
if (reverse !== true) {
reverse = false;
}
return this.ApplyOffset(dt, {
negative: true,
hours: save.hours,
mins: save.mins,
secs: 0
}, reverse);
},
UTCToWallTime: function(dt, offset, save) {
var endTime;
endTime = this.UTCToStandardTime(dt, offset);
return this.ApplySave(endTime, save);
},
UTCToStandardTime: function(dt, offset) {
return this.ApplyOffset(dt, offset, true);
},
UTCToQualifiedTime: function(dt, qualifier, offset, getSave) {
var endTime;
endTime = dt;
switch (qualifier) {
case "w":
endTime = this.UTCToWallTime(endTime, offset, getSave());
break;
case "s":
endTime = this.UTCToStandardTime(endTime, offset);
break;
}
return endTime;
},
QualifiedTimeToUTC: function(dt, qualifier, offset, getSave) {
var endTime;
endTime = dt;
switch (qualifier) {
case "w":
endTime = this.WallTimeToUTC(offset, getSave(), endTime);
break;
case "s":
endTime = this.StandardTimeToUTC(offset, endTime);
break;
}
return endTime;
},
StandardTimeToUTC: function(offset, y, m, d, h, mi, s, ms) {
var dt;
if (m == null) {
m = 0;
}
if (d == null) {
d = 1;
}
if (h == null) {
h = 0;
}
if (mi == null) {
mi = 0;
}
if (s == null) {
s = 0;
}
if (ms == null) {
ms = 0;
}
dt = typeof y === "number" ? this.MakeDateFromParts(y, m, d, h, mi, s, ms) : y;
return this.ApplyOffset(dt, offset);
},
WallTimeToUTC: function(offset, save, y, m, d, h, mi, s, ms) {
var dt;
if (m == null) {
m = 0;
}
if (d == null) {
d = 1;
}
if (h == null) {
h = 0;
}
if (mi == null) {
mi = 0;
}
if (s == null) {
s = 0;
}
if (ms == null) {
ms = 0;
}
dt = this.StandardTimeToUTC(offset, y, m, d, h, mi, s, ms);
return this.ApplySave(dt, save, true);
},
MakeDateFromParts: function(y, m, d, h, mi, s, ms) {
var dt;
if (m == null) {
m = 0;
}
if (d == null) {
d = 1;
}
if (h == null) {
h = 0;
}
if (mi == null) {
mi = 0;
}
if (s == null) {
s = 0;
}
if (ms == null) {
ms = 0;
}
if (Date.UTC) {
return new Date(Date.UTC(y, m, d, h, mi, s, ms));
}
dt = new Date;
dt.setUTCFullYear(y);
dt.setUTCMonth(m);
dt.setUTCDate(d);
dt.setUTCHours(h);
dt.setUTCMinutes(mi);
dt.setUTCSeconds(s);
dt.setUTCMilliseconds(ms);
return dt;
},
LocalDate: function(offset, save, y, m, d, h, mi, s, ms) {
if (m == null) {
m = 0;
}
if (d == null) {
d = 1;
}
if (h == null) {
h = 0;
}
if (mi == null) {
mi = 0;
}
if (s == null) {
s = 0;
}
if (ms == null) {
ms = 0;
}
return this.WallTimeToUTC(offset, save, y, m, d, h, mi, s, ms);
},
MakeDateFromTimeStamp: function(ts) {
return new Date(ts);
},
MaxDate: function() {
return this.MakeDateFromTimeStamp(10000000 * 86400000);
},
MinDate: function() {
return this.MakeDateFromTimeStamp(-10000000 * 86400000);
}
};
helpers = {
Days: Days,
Months: Months,
Milliseconds: Milliseconds,
Time: Time,
noSave: {
hours: 0,
mins: 0
},
noZone: {
offset: {
negative: false,
hours: 0,
mins: 0,
secs: 0
},
name: "UTC"
}
};
if (typeof window === 'undefined') {
module.exports = helpers;
} else if (typeof define !== 'undefined') {
define(helpers);
} else {
this.WallTime || (this.WallTime = {});
this.WallTime.helpers = helpers;
}
}).call(this);