This update fixes a few bugs surrounding month calculation bugs, hours and leap years. Big props to Simen for the first version which was the foundation.
Also this version will allow for optional second param dateVal where you can pass a date to calculate from instead of using today's date.
function determineDate(dateAttr, dateVal) {
var date = dateVal === undefined ? new Date() : new Date(dateVal);
var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
var matches = pattern.exec(dateAttr);
var year = date.getFullYear();
var month = date.getMonth();
var day = date.getDate();
while (matches) {
switch (matches[2] || 'd') {
case 'd' : case 'D' :
day += parseInt(matches[1],10); break;
case 'w' : case 'W' :
day += parseInt(matches[1],10) * 7; break;
case 'm' : case 'M' :
month += parseInt(matches[1],10);
day = Math.min(day, getDaysInMonth(year, month));
break;
case 'y': case 'Y' :
year += parseInt(matches[1],10);
day = Math.min(day, getDaysInMonth(year, month));
break;
}
matches = pattern.exec(dateAttr);
}
var newdate = new Date(year, month, day);
newdate.setHours(0);
newdate.setMinutes(0);
newdate.setSeconds(0);
newdate.setMilliseconds(0);
return daylightSavingAdjust(newdate);
}
function daylightSavingAdjust(date){
if (!date){
return null;
}
date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
return date;
}
function getDaysInMonth(year, month){
return 32 - daylightSavingAdjust(new Date(year, month, 32)).getDate();
}