Calculating a future date

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Claus Mygind
    Contributor
    • Mar 2008
    • 571

    Calculating a future date

    I want to take a date value from an input field and calculate a future date (90 days from the input date).

    I get inconsistent results.

    if I use "1/1/11" I get "4/5/11" or 94 days answer should be "4/1/11".

    if I use "3/1/11" I get "6/4/11" or 64 days where the answer should be "6/30/11"

    Here is my function:
    Code:
    	g.inspDate = document.getElementById('inspDate'); 
    	g.inspDate.addEventListener("change", function(){
    			if (g.process.isDate(this)) 
    			{
    				wkDay = new Date(this.value);
    				nextD = wkDay.getDate() +90 ;
    				wkDay.setDate( nextD );
    				document.getElementById("followDate").value = (wkDay.getMonth()+1)+'/'+wkDay.getDay()+'/'+wkDay.getFullYear();
    			}
    		
    		}, false);
    The g.process.isDat e merely allows me to enter either a date with / or - and use either 2 or 4 digit year. The returned result is always a string value "mm/dd/yyyy". This then serves as the input for the function above.

    Here is that function but it seems to work just fine. I only include it to show all work used to compute the future date.

    Code:
    	this.isDate = function (fld) {
    		var mo, day, yr;
    		var entry = fld.value;
    		var reLong = /\b\d{1,2}[\/-]\d{1,2}[\/-]\d{4}\b/;
    		var reShort = /\b\d{1,2}[\/-]\d{1,2}[\/-]\d{2}\b/;
    		var valid = (reLong.test(entry)) || (reShort.test(entry));
    		if (valid) {
    			var delimChar = (entry.indexOf("/") != -1) ? "/" : "-";
    			var delim1 = entry.indexOf(delimChar);
    			var delim2 = entry.lastIndexOf(delimChar);
    			mo = parseInt(entry.substring(0, delim1), 10);
    			day = parseInt(entry.substring(delim1+1, delim2), 10);
    			yr = parseInt(entry.substring(delim2+1), 10);
    			// handle two-digit year
    			if (yr < 100) {
    				var today = new Date();
    				// get current century floor (e.g., 2000)
    				var currCent = parseInt(today.getFullYear() / 100) * 100;
    				// two digits up to this year + 15 expands to current century
    				var threshold = (today.getFullYear() + 15) - currCent;
    				if (yr > threshold) {
    				    yr += currCent - 100;
    				} else {
    				    yr += currCent;
    				}
    			}
    			var testDate = new Date(yr, mo-1, day);
    			if (testDate.getDate() == day) {
    				if (testDate.getMonth() + 1 == mo) {
    					if (testDate.getFullYear() == yr) {
    					    // fill field with database-friendly format
    					    fld.value = mo + "/" + day + "/" + yr;
    					    return true;
    					} else {
    						alert("There is a problem with the year entry.");
    					}
    				} else {
    					alert("There is a problem with the month entry.");
    				}
    			} else {
    				alert("There is a problem with the date entry.");
    			}
    		} else {
    			alert("Incorrect date format. Enter as mm/dd/yyyy.");
    		}
    		return false;
    		
    	};
  • Claus Mygind
    Contributor
    • Mar 2008
    • 571

    #2
    Ok I have narrowed the problem down to this code.

    document.getEle mentById("outpu t").value = (wkDay.getMonth ()+1)+'/'+wkDay.getDay( )+'/'+wkDay.getFull Year();

    Here is a simple app which will calculate the future date using milliseconds. That calculation is correct, but when I extract the date information, it returns an incorrect date. This code gives me two different dates 4/1 and 4/5 when tested from 1/1/2011. What am I doing incorrectly?

    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
     <head>
    <script type="text/javascript">
     <!--
    	function doMath()
    	{
    	var input = document.getElementById("input").value
    	var today = new Date(input);
    	var wkDay = new Date(today.getTime() + 1000 * 60 * 60 * 24 * 90);
    	document.getElementById("output").value = (wkDay.getMonth()+1)+'/'+wkDay.getDay()+'/'+wkDay.getFullYear();
    	document.getElementById("output2").value = wkDay;
    	}
    
     //-->
     </script> </head>
    
     <body>
     Enter date:<input type="text" id="input" value="1/1/2011"/><input type="button" value="Calc 90 days from date" onclick="doMath();" /><br />
     mm/dd/yyyy output <input type="text" id="output" /><br />
     Correct Date output <input type="text" id="output2" size='50'/>
     </body>
    </html>
    I am running the code on XP with FireFox 6.0

    Comment

    • Claus Mygind
      Contributor
      • Mar 2008
      • 571

      #3
      It is sad to see that javaScript has not evolved to include a better date handler. But I finally came up with a solution I found on the web


      To bad you have to resort to regExp for simple date handling, but passing the future date calculated using milliseconds as described in my previous reply and passing that date through this at least yields the correct date. ie: dateFormat(<cal cDate>,"mm/dd/yyyy");

      Code:
      	/*
       * Date Format 1.2.3
       * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
       * MIT license
       *
       * Includes enhancements by Scott Trenda <scott.trenda.net>
       * and Kris Kowal <cixar.com/~kris.kowal/>
       *
       * Accepts a date, a mask, or a date and a mask.
       * Returns a formatted version of the given date.
       * The date defaults to the current date/time.
       * The mask defaults to dateFormat.masks.default.
       */
      
      var dateFormat = function () {
      	var	token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
      		timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
      		timezoneClip = /[^-+\dA-Z]/g,
      		pad = function (val, len) {
      			val = String(val);
      			len = len || 2;
      			while (val.length < len) val = "0" + val;
      			return val;
      		};
      
      	// Regexes and supporting functions are cached through closure
      	return function (date, mask, utc) {
      		var dF = dateFormat;
      
      		// You can't provide utc if you skip other args (use the "UTC:" mask prefix)
      		if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
      			mask = date;
      			date = undefined;
      		}
      
      		// Passing date through Date applies Date.parse, if necessary
      		date = date ? new Date(date) : new Date;
      		if (isNaN(date)) throw SyntaxError("invalid date");
      
      		mask = String(dF.masks[mask] || mask || dF.masks["default"]);
      
      		// Allow setting the utc argument via the mask
      		if (mask.slice(0, 4) == "UTC:") {
      			mask = mask.slice(4);
      			utc = true;
      		}
      
      		var	_ = utc ? "getUTC" : "get",
      			d = date[_ + "Date"](),
      			D = date[_ + "Day"](),
      			m = date[_ + "Month"](),
      			y = date[_ + "FullYear"](),
      			H = date[_ + "Hours"](),
      			M = date[_ + "Minutes"](),
      			s = date[_ + "Seconds"](),
      			L = date[_ + "Milliseconds"](),
      			o = utc ? 0 : date.getTimezoneOffset(),
      			flags = {
      				d:    d,
      				dd:   pad(d),
      				ddd:  dF.i18n.dayNames[D],
      				dddd: dF.i18n.dayNames[D + 7],
      				m:    m + 1,
      				mm:   pad(m + 1),
      				mmm:  dF.i18n.monthNames[m],
      				mmmm: dF.i18n.monthNames[m + 12],
      				yy:   String(y).slice(2),
      				yyyy: y,
      				h:    H % 12 || 12,
      				hh:   pad(H % 12 || 12),
      				H:    H,
      				HH:   pad(H),
      				M:    M,
      				MM:   pad(M),
      				s:    s,
      				ss:   pad(s),
      				l:    pad(L, 3),
      				L:    pad(L > 99 ? Math.round(L / 10) : L),
      				t:    H < 12 ? "a"  : "p",
      				tt:   H < 12 ? "am" : "pm",
      				T:    H < 12 ? "A"  : "P",
      				TT:   H < 12 ? "AM" : "PM",
      				Z:    utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
      				o:    (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
      				S:    ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
      			};
      
      		return mask.replace(token, function ($0) {
      			return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
      		});
      	};
      }();
      
      // Some common format strings
      dateFormat.masks = {
      	"default":      "ddd mmm dd yyyy HH:MM:ss",
      	shortDate:      "m/d/yy",
      	mediumDate:     "mmm d, yyyy",
      	longDate:       "mmmm d, yyyy",
      	fullDate:       "dddd, mmmm d, yyyy",
      	shortTime:      "h:MM TT",
      	mediumTime:     "h:MM:ss TT",
      	longTime:       "h:MM:ss TT Z",
      	isoDate:        "yyyy-mm-dd",
      	isoTime:        "HH:MM:ss",
      	isoDateTime:    "yyyy-mm-dd'T'HH:MM:ss",
      	isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
      };
      
      // Internationalization strings
      dateFormat.i18n = {
      	dayNames: [
      		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
      		"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
      	],
      	monthNames: [
      		"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
      		"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
      	]
      };
      
      // For convenience...
      Date.prototype.format = function (mask, utc) {
      	return dateFormat(this, mask, utc);
      };

      Comment

      Working...