HTML5

If you’re lucky enough to be able to switch to HTML5, you’ll be able to use the new built-in date picker controls.

<input type="date" id="mydate" value="2014-03-14" />

If you’re viewing this page with an HTML5 capable browser, the value will render as follows:

No special jQuery plugins or custom calendar controls necessary! With HTML5, there are a total of three different date and date/time picker controls:

  • date – The date (no timezone).
  • datetime – The date/time (with time zone).
  • datetime-local – The date/time (no timezone).

JavaScript Date/Time Parsing

If you’ve ever worked clientside with JavaScript, you’ll know that any new Date() function call will return a Date object that is localized based on the timezone set for the computer. You can also create a new date from an existing date or by parsing the string as follows:

  var date = new Date("Tue Mar 04 2014 16:00:00 GMT-0800");
  console.log(date);

With the above example, assuming you are located in CST (or a different timezone than PST), you’ll find the following output:

Tue Mar 04 2014 18:00:00 GMT-0600 (Central Standard Time)

Notice that the time has automatically corrected itself to the local timezone. OK, that’s good to know, but how does that affect me?

Try the following time:

  var date = new Date("Tue Mar 04 2014 00:00:00 GMT-0000");
  console.log(date);

Assuming you’re in the western hemisphere and you don’t live near the prime meridian, you should see something like the following:

Mon Mar 03 2014 18:00:00 GMT-0600 (Central Standard Time)

Did you catch that? The date has moved back to March 03 instead of March 04 because of the timezone conversion. OK, you get it, enough with the geography and math lessons… why should you care?

HTML5 Date Input

When using the <input type=”date” /> control, the value that is posted and returned from the input control is formatted as: YYYY-MM-DD. Since we have a date, we can assume that we can just let the JavaScript Date object parse it for us.

  var date = new Date('2014-03-04');
  // Mon Mar 03 2014 18:00:00 GMT-0600 (Central Standard Time)

What?!?! Why is it March 03 again? Lets try playing around with the Date object a little bit and see what happens.

  var date = new Date(2014, 2, 4); // Recall that month is 0 based, where 0=January
  // Tue Mar 04 2014 00:00:00 GMT-0600 (Central Standard Time)
  var date = new Date('03/04/2014');
  // Tue Mar 04 2014 00:00:00 GMT-0600 (Central Standard Time)

OK. Now that is what I’m expecting!!! So basically if we provide the string as YYYY-MM-DD, the Date object will parse that date automatically as a GMT time and then localize. However, if we pass it in as MM/DD/YYYY it will already be localized.

So how do we handle this for our HTML5 input control to get the date we expect? The following naive JavaScript will attempt to parse the input received and create a localized Date object. It will also attempt to parse a standard date in the MM/DD/YYYY format if HTML5 isn’t supported.

/**
 * Parses the date from the string input.
 * @param {Number|Date|string} date Teh value to be parsed.
 * @param {Function|Date} [defaultValue] The default value to use if the date cannot be parsed.
 * @returns {Date} The parsed date value. If the date is invalid or can't be parsed, then the defaultValue is returned.
 */
function parseDate(date, defaultValue) {
  if (! date) return(getDefaultValue());
  if (typeof(date) === 'date') return(date);
  if (typeof(date) === 'number') return(new Date(date));

  /**
   * Gets the default value.
   * @returns {Date}
   */
  function getDefaultValue() {
    return((typeof(defaultValue) === 'function') ? defaultValue(name) : defaultValue);
  }

  var results;
  // YYYY-MM-DD
  if ((results = /(\d{4})[-\/\\](\d{1,2})[-\/\\](\d{1,2})/.exec(date))) {
    return(new Date(results[1], parseInt(results[2], 10)-1, results[3]) || new Date(date) || getDefaultValue());
  }
  // MM/DD/YYYY
  if ((results = /(\d{1,2})[-\/\\](\d{1,2})[-\/\\](\d{4})/.exec(date))) {
    date = new Date(results[3], parseInt(results[1], 10)-1, results[2]) || new Date(date) || getDefaultValue();
  }
  return(new Date(date) || getDefaultValue());
}

So the next time you find yourself struggling with dates and times in JavaScript, be wary of the input parsing or the format of your input and / or timezone.