Created
October 14, 2015 17:30
-
-
Save PitBeast/2451b610f9dbf9681b33 to your computer and use it in GitHub Desktop.
This file contains 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
function fastDateFactory() { | |
var DAYS_IN_YEAR = 365; | |
var DAYS_IN_LEAP_YEAR = 366; | |
var DAYS_IN_4_YEARS = DAYS_IN_LEAP_YEAR + DAYS_IN_YEAR * 3; | |
var DAYS_IN_OTHER_FIRST_4_YEARS = DAYS_IN_YEAR * 4; | |
var DAYS_IN_FIRST_100_YEARS = DAYS_IN_4_YEARS * 25; | |
var DAYS_IN_NEXT_100_YEARS = DAYS_IN_OTHER_FIRST_4_YEARS + DAYS_IN_4_YEARS * 24; | |
var DAYS_IN_400_YEARS = DAYS_IN_FIRST_100_YEARS + DAYS_IN_NEXT_100_YEARS * 3; | |
var MONTH_DAYS_AGGREGATED_LEAP = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]; | |
var MONTH_DAYS_AGGREGATED = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365]; | |
var FastDate; | |
function stringToYMD(stringDate) { | |
var dateParts; | |
if (!(dateParts = /^(\d{4})-(\d{2})-(\d{2})$/.exec(stringDate))) { | |
throw new Error('Date format invalid'); | |
} | |
return { | |
year: parseInt(dateParts[1], 10), | |
month: parseInt(dateParts[2], 10), | |
day: parseInt(dateParts[3], 10) | |
}; | |
} | |
function daysFromZeroPoint(ymd) { | |
var yearRest = (ymd.year) % 400; | |
/*jshint bitwise: false*/ | |
var leapYears = ((ymd.year - yearRest) / 400) * 97 + | |
((yearRest + 3) >> 2) - (yearRest > 300 ? 3 : yearRest > 200 ? 2 : yearRest > 100 ? 1 : 0); | |
/*jshint bitwise: true*/ | |
return leapYears * DAYS_IN_LEAP_YEAR + (ymd.year - leapYears) * DAYS_IN_YEAR + | |
(isLeap(ymd.year) ? MONTH_DAYS_AGGREGATED_LEAP[ymd.month - 1] : MONTH_DAYS_AGGREGATED[ymd.month - 1]) + | |
ymd.day - 1; | |
} | |
function isLeap(year) { | |
return (year % 4 === 0) && (year % 100 !== 0) || (year % 400 === 0); | |
} | |
FastDate = function(startDate) { | |
if (this instanceof FastDate) { | |
this.offsetFromZeroPoint = daysFromZeroPoint(stringToYMD(startDate)); | |
} else { | |
return new FastDate(startDate); | |
} | |
}; | |
_.extend( | |
FastDate.prototype, | |
{ | |
stringToYMD: function(stringDate) { | |
return stringToYMD(stringDate); | |
}, | |
stringToFastDate: function(stringDate) { | |
return daysFromZeroPoint(this.stringToYMD(stringDate)) - this.offsetFromZeroPoint; | |
}, | |
fastDateToYMD: function(index) { | |
var offset = index + this.offsetFromZeroPoint; | |
var rest; | |
var year; | |
var month = 1; | |
var inFirst100 = false; | |
var inOtherFirst4 = false; | |
var monthDays; | |
rest = offset % DAYS_IN_400_YEARS; | |
year = (offset - rest) / DAYS_IN_400_YEARS * 400; | |
offset = rest; | |
if (rest) { | |
if (offset < DAYS_IN_FIRST_100_YEARS) { | |
inFirst100 = true; | |
} else { | |
rest = (offset - DAYS_IN_FIRST_100_YEARS) % DAYS_IN_NEXT_100_YEARS; | |
year += 100 + (offset - DAYS_IN_FIRST_100_YEARS - rest) / DAYS_IN_NEXT_100_YEARS * 100; | |
offset = rest; | |
} | |
if (rest) { | |
if (!inFirst100) { | |
if (offset < DAYS_IN_OTHER_FIRST_4_YEARS) { | |
inOtherFirst4 = true; | |
} else { | |
rest = (offset - DAYS_IN_OTHER_FIRST_4_YEARS) % DAYS_IN_4_YEARS; | |
year += 4 + (offset - DAYS_IN_OTHER_FIRST_4_YEARS - rest) / DAYS_IN_4_YEARS * 4; | |
offset = rest; | |
} | |
} else { | |
rest = offset % DAYS_IN_4_YEARS; | |
year += (offset - rest) / DAYS_IN_4_YEARS * 4; | |
offset = rest; | |
} | |
if (rest) { | |
if (!inOtherFirst4) { | |
if (offset >= DAYS_IN_LEAP_YEAR) { | |
rest = (offset - DAYS_IN_LEAP_YEAR) % DAYS_IN_YEAR; | |
year += 1 + (offset - DAYS_IN_LEAP_YEAR - rest) / DAYS_IN_YEAR; | |
} | |
} else { | |
rest = offset % DAYS_IN_YEAR; | |
year += (offset - rest) / DAYS_IN_YEAR; | |
} | |
} | |
} | |
} | |
monthDays = isLeap(year) ? MONTH_DAYS_AGGREGATED_LEAP : MONTH_DAYS_AGGREGATED; | |
while (rest > monthDays[month]) { | |
month++; | |
} | |
rest -= monthDays[month - 1] - 1; | |
return { | |
year: year, | |
month: month, | |
day: rest | |
}; | |
}, | |
fastDateToSting: function(index) { | |
var ymd = this.fastDateToYMD(index); | |
return ('000' + ymd.year).substr(-4) + '-' + ('0' + ymd.month).substr(-2) + '-' + ('0' + ymd.day).substr(-2); | |
}, | |
fastDateToDayOfWeek: function(index) { | |
return (index + this.offsetFromZeroPoint + 6) % 7; | |
}, | |
isFastDateWeekend: function(index) { | |
return (index + this.offsetFromZeroPoint) % 7 < 2; | |
} | |
} | |
); | |
return FastDate; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment