Skip to content

Instantly share code, notes, and snippets.

@blangenfeld
Created October 1, 2013 14:58
Show Gist options
  • Save blangenfeld/6779807 to your computer and use it in GitHub Desktop.
Save blangenfeld/6779807 to your computer and use it in GitHub Desktop.
An AngularJS filter for turning a date pair into an array containing all intervening dates.
angular.module('kf.filters', []).
/*
* Because ngScope $watchCollection uses === to evaluate whether a collection has changed, we
* need a way to return the same Date objects -- in the identity (not equality) sense -- to avoid
* a $digest death spiral.
*/
factory('DateCache', ['$cacheFactory', function($cacheFactory) {
return $cacheFactory('dateCache');
}]).
/**
* @ngdoc filter
* @name kf.filters:expandDateRange
* @function
*
* @description
* Passed a pair of Dates, returns a chronologically-ordered array containing all Dates between
* them (inclusive).
*
* Uses DateCache to avoid a $digest death spiral.
*/
filter('expandDateRange', ['DateCache', function(DateCache) {
/**
* Simply truncates the given date to midnight.
*/
var truncate = function(date) {
var d = new Date(date);
return new Date(
d.getFullYear(),
d.getMonth(),
d.getDate()
);
};
return function(input) {
var out = [],
first = truncate(new Date(input[0])).getTime(),
last = truncate(new Date(input[1])).getTime(),
msPerDay = 24 * 60 * 60 * 1000,
date;
for(var ms = first; ms <= last; ms += msPerDay) {
date = DateCache.get(ms) || DateCache.put(ms, new Date(ms));
out.push(date);
}
return out;
};
}]);
@blangenfeld
Copy link
Author

The challenge in implementing this filter was the fact that every new Date(...) creates a new object, which causes $watchCollection to detect a change and force a $digest. I solved this problem by using $cacheFactory to re-use date objects.

Filter demo fiddle: http://jsfiddle.net/blangenfeld/CqFvg/

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