Reply to comment
Day Range Indexer
Submitted by bingomanatee on 6 March, 2010 - 14:12I wanted to create a way to rapidly compare and get date ranges (in days) between two dates. So I created a class that indexes all dates within a range of years and retuns an integral value for any given date, i.e., in years from year zero. This was done for the purpose of creating a Gantt table with date pagination.
The entire library is pretty short so I'm just pasting it here:
(function($){
$.fn.date_index = function(start, end){
start = new Number(start);
end = new Number(end);
this.start_year = start;
this.end_year = end;
this.first_date = new Date(start, 0, 1);
this.end_date = new Date(end + 1, 0, 1);
this.end_date.setDate(this.end_date.getDate() - 1);
this.init();
}
$.fn.date_index.prototype.date_diff = function(d1, d2){
var d1_day_index = this.index_of_date(d1, d1.getFullYear() == d2.getFullYear());
var d2_day_index = this.index_of_date(d2, d1.getFullYear() == d2.getFullYear());
return d2_day_index - d1_day_index;
}
$.fn.date_index.prototype.index_of_date = function(d1, day_only){
var day_offset = this._index[d1.getFullYear()].index[d1.getMonth()][d1.getDate()];
if (day_only){
return day_offset;
}
var year_offset = this._year_offset(d1.getFullYear());
return day_offset + year_offset;
}
$.fn.date_index.prototype._year_offset = function(year){
var days_before = 0;
for (var y = this.start_year; y < year; ++y){
days_before += this._index[y].year_length;
}
return days_before;
}
$.fn.date_index.prototype.init = function(){
this._index = [];
for (year = this.start_year; year <= this.end_year; ++year){
this._index[year] = this._year_index(year);
}
}
$.fn.date_index.prototype._year_index = function(year){
var list = new Array(12);
var d = new Date(year, 0, 1);
var offset = 0;
while (d.getFullYear() == year){
if (!list[d.getMonth()]){
list[d.getMonth()] = new Array(28);
}
list[d.getMonth()][d.getDate()] = offset;
++offset;
d.setDate(d.getDate() + 1);
}
return {
year: year,
year_length: offset, // usually 365 except on leap years
index: list
};
}
})(jQuery);
The operative methods are
- date_diff(d1:Date, d2:Date), indicating a range of days between the two dates (can be negative)
- index_of_date(d) which returns the number of days from "Year zero" to the given date
So the operation would be as such:
var my_date_index = new $.fn.date_index(2000, 2015); var today = new Date(); var halloween = new Date(2010, 10, 31); var days_til_halloween = my_date_index.date_diff(today, halloween);
Note -- this method creates a value for EVERY DAY betwen the indicated years -- that is, a nested array [year][day] of integers -- upon instantiation, before even a single comparison or check is made. This means that for just checking single dates it might not be the most efficient way to go. Its is best suited for situations in which a LOT of dates need to be compared (As in the Gantt example). However because there are no real computations happening after init(), just array checking, this is probably the fastest way to accomplish date comparisons, on an individual comparison basis.
Because there is a lot of year clumping in the gantt this works fine for my purpose. However, if you wanted to extend this for a wider, sparser year range you could dynamically generate the daily data as needed and just compute the days in the year in init().
