Skip to content

Instantly share code, notes, and snippets.

@PitBeast
Created October 14, 2015 17:30
Show Gist options
  • Save PitBeast/2451b610f9dbf9681b33 to your computer and use it in GitHub Desktop.
Save PitBeast/2451b610f9dbf9681b33 to your computer and use it in GitHub Desktop.
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