Skip to content

Instantly share code, notes, and snippets.

@mattjohnsonpint
Last active June 25, 2017 00:45
Show Gist options
  • Select an option

  • Save mattjohnsonpint/f6aa5e8b8aa040f65ae1 to your computer and use it in GitHub Desktop.

Select an option

Save mattjohnsonpint/f6aa5e8b8aa040f65ae1 to your computer and use it in GitHub Desktop.
JS replacement functions for timestamp <==> date parts without using the Date object
var d365 = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 ];
var d366 = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 ];
function parts2ts(year, month, day, hour, minute, second, millisecond) {
if (month < 0 || month > 11) {
return NaN;
}
var leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
var days = leap ? d366 : d365;
if (day < 1 || day > days[month + 1] - days[month]) {
return NaN;
}
var f = Math.floor;
var y = year - 1;
var daysSinceEpoch = y * 365 + f(y / 4) - f(y / 100) + f(y / 400) + days[month] + day - 719163;
return (daysSinceEpoch * 8640 * 10000) + (hour * 3600 * 1000) + (minute * 60000) + (second * 1000) + millisecond;
}
function ts2parts(ts) {
var f = Math.floor;
var n = f(ts / 864e5) + 719162;
var y400 = f(n / 146097);
n -= y400 * 146097;
var y100 = f(n / 36524);
if (y100 == 4) y100 = 3;
n -= y100 * 36524;
var y4 = f(n / 1461);
n -= y4 * 1461;
var y1 = f(n / 365);
if (y1 == 4) y1 = 3;
n -= y1 * 365;
var year = y400 * 400 + y100 * 100 + y4 * 4 + y1 + 1;
var leap = y1 == 3 && (y4 != 24 || y100 == 3);
var days = leap ? d366 : d365;
var month = n >> 5;
while (n >= days[month + 1])
month++;
var day = n - days[month] + 1;
var hour = (Math.floor((ts % 864e5) / 36e5) + 24) % 24;
var minute = (Math.floor((ts % 36e5) / 6e4) + 60) % 60;
var second = (Math.floor((ts % 6e4) / 1e3) + 60) % 60;
var millisecond = ((ts % 1e3) + 1e3) % 1e3;
return [year, month, day, hour, minute, second, millisecond];
}
function parts2ts_native(year, month, day, hour, minute, second, millisecond) {
return Date.UTC(year, month, day, hour, minute, second, millisecond);
}
function ts2parts_native(ts) {
var dt = new Date(ts);
return [dt.getUTCFullYear(), dt.getUTCMonth(), dt.getUTCDate(), dt.getUTCHours(), dt.getUTCMinutes(), dt.getUTCSeconds(), dt.getUTCMilliseconds()];
}
@mattjohnsonpint
Copy link
Copy Markdown
Author

I'm also thinking about this with regard to moment.js

@mattjohnsonpint
Copy link
Copy Markdown
Author

The "why is this faster" may be in part that I'm not handling underflow/overflow scenarios, and that I'm computing the values all at once in a single pass, rather than one part at a time.

@mattjohnsonpint
Copy link
Copy Markdown
Author

Updated to fix floating point math errors, and errors with flooring negative values.

@mattjohnsonpint
Copy link
Copy Markdown
Author

mattjohnsonpint commented Jun 25, 2017

Updated again, apparently I botched the time parts of ts2parts. oops!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment