Skip to content

Instantly share code, notes, and snippets.

@puppybits
Last active December 17, 2015 05:59
Show Gist options
  • Save puppybits/5561723 to your computer and use it in GitHub Desktop.
Save puppybits/5561723 to your computer and use it in GitHub Desktop.
Create a date that iterates on either multiple dates of the month or every X number of days
/*
// EXAMPLES:
var payday = new SeriesDate('DAILY', [14], '1/15/2010')
var gas = new SeriesDate('MONTHLY', [1,15], '1/15/2010')
var electricity = new SeriesDate('MONTHLY', [20], '1/15/2010')
payday.next(); // move to next payday
payday.prev(); // move to previous payday
// TODO: fix bad hack to subclass Date (http://www.2ality.com/2013/03/subclassing-builtins-es6.html)
// only tested in chrome
*/
function SeriesDate( seriesType, series, start )
{
var _this = new Date(start);
_this.__proto__ = SeriesDate.prototype;
for(var i in series){ if (series[i]>28)series[i]=28}
var _seriesType = seriesType,
_series = series.sort(),
_start = new Date(start.toString()),
setLastDate = function(d)
{
nextMonth(d);
d.setDate(0); /* set date 0 will subtract one day */
},
nextMonth = function(d)
{
if (d.getMonth() < 11)
{
d.setMonth( (d.getMonth()+1) );
}
else
{
d.setMonth(0);
d.setFullYear(d.getFullYear()+1);
}
return d;
},
nextDate = function(d, date)
{
if (d.getDate() < date)
{
(date < 28) ? d.setDate(date) : setLastDate(d);
}
else
{
if (date < 28)
{
d.setDate(1)
nextMonth(d);
d.setDate(date);
}
else
{
setLastDate(d);
}
}
return d;
},
previousMonth = function(d)
{
if (d.getMonth() > 0)
{
d.setMonth(d.getMonth()-1);
}
else
{
d.setMonth(11);
d.setFullYear(d.getFullYear()-1);
}
return d;
},
previousDate = function(d, date)
{
if (d.getDate() > date)
{
(date < 28) ? d.setDate(date) : d.setDate(0);
}
else
{
if (date < 28)
{
previousMonth(d);
d.setDate(date);
}
else
{
d.setDate(1);
previousMonth(d);
setLastDate(d);
}
}
return d;
},
nextMonthlyDate = function(date, monthSeries, start)
{
var isBeforeStartDate = (start.getTime() > date.getTime()),
d = [date.getFullYear(), date.getMonth(), date.getDate()];
if (isBeforeStartDate)
return new Date(start.toString());
for (var i in monthSeries)
{
if (monthSeries[i] > d[2])
return nextDate(date, monthSeries[i])
}
return nextDate(date, monthSeries[0])
},
previousMonthlyDate = function(date, monthSeries, start)
{
var isBeforeStartDate = (start.getTime() > date.getTime()),
d = [date.getFullYear(), date.getMonth(), Math.min(date.getDate(), 28)];
if (isBeforeStartDate)
return new Date(start.toString());
for (var i=monthSeries.length-1; i>=0; i--)
{
if (monthSeries[i] < d[2])
return previousDate(date, monthSeries[i])
}
return previousDate(date, monthSeries[monthSeries.length-1])
},
nextDailyDate = function(date, day, start)
{
var isBeforeStartDate = (start.getTime() > date.getTime());
if (isBeforeStartDate)
return new Date(start.toString());
day *= 86400000;
date.setTime(date.getTime() + day)
return date;
},
previousDailyDate = function(date, day, start)
{
var isBeforeStartDate = (start.getTime() > date.getTime());
if (isBeforeStartDate)
return new Date(start.toString());
day *= 86400000;
date.setTime(date.getTime() - day)
return date;
};
if (seriesType ==='MONTHLY')
{
_this.next = function(){
return nextMonthlyDate(this, _series, _start);
};
_this.prev = function(){
return previousMonthlyDate(this, _series, _start);
};
}
else
{
_this.next = function(){
return nextDailyDate(this, _series, _start);
};
_this.prev = function(){
return previousDailyDate(this, _series, _start);
};
}
/* move to first future date */
var now = new Date().getTime();
while (now > _this.getTime() )
{
_this.next()
}
return _this;
}
SeriesDate.prototype = Object.create(Date.prototype);
// TODO: upload unit tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment