Last active
June 25, 2017 00:45
-
-
Save mattjohnsonpint/f6aa5e8b8aa040f65ae1 to your computer and use it in GitHub Desktop.
JS replacement functions for timestamp <==> date parts without using the Date object
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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()]; | |
| } |
Author
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.
Author
Updated to fix floating point math errors, and errors with flooring negative values.
Author
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
I'm also thinking about this with regard to moment.js