© J R Stockton, ≥ 2012-04-18

JavaScript Date and Time 4 :
Validation
.

Links within this site :-

See "About This JavaScript Site" in JavaScript Index and Introduction.

See "General Date/Time Introduction" in JavaScript Date and Time Introduction.

My JavaScript RegExps and Validation deals with data validation in general, and indicates an efficient way of coding it.

Time and Date Validation

To check string patterns, it seems most effective to use a RegExp, which is core JavaScript 1.2, needing therefore MSIE4+, NS4+, or equivalent. It's probably reasonable for most authors to expect RegExp to be available. However, using split() may suffice, though it can allow strange forms.

String method match can be used to avoid the RegExp.$n construct, used as in :-

Match = S.match(/^(\d{4})\D(\d\d)\D(\d\d)$/)
if (!Match) { alert("Error") ; return false }
Y = + Match[1] ; ...

Choice of method may depend on whether the date or time is to be used only as a string, or is to be processed further. In the latter case, it is useful if the validation also prepares for the further use, by splitting fields or creating a result.

If it is necessary to validate a date-time combination, it may be easiest to split them and validate separately - remember, though, Summer Time, which invalidates an hour per year in many locations.

If a date/time string is used as the argument of new Date() at least some out-of-range values will be accepted in at least some browsers, and converted to equivalents.

See the code used on this site for other uses of the properties of Date Objects : e.g. determination of month length, incrementing the week, ... . It seems that, in Netscape 4.7, the zero in "new Date(Y, M, 0)" is taken as a 1, although in MSIE 4 that gave the last day of the previous month; hence the code change here of 2000-09-01. I believe that MSIE is ECMA-compliant in this (and that Java behaves in the same way).

Date Validating

Will the date to be validated be supplied as numbers; or as a string, and if so in what format?

Is "29/02/00" valid? Will it be valid in 100 years' time? Is "02/29/00" valid? Is "Sat, 9 Aug 2000" valid? Is "Wed, 9 Aug 2000" valid? Is "25.XII.2000" valid? Is "25.12.00"? Is "Easter Sunday, 2001" valid? Is "YYYY-MM-00" a permissible way of representing the day before "YYYY-MM-01"?

Accepting 2-digit years on the Net is risky; the chance of someone putting the fields in the wrong order is too great. So, for most purposes, change a \d+ to a \d{4} in examples and code.

A 4-digit year field could start with a zero, in which case it could be taken as octal; or with two or more, in which case it might also be taken as in the 1900s. Consider 0052/02/29.

Even if a Date Object is required subsequently, it seems faster to validate the numbers arithmetically then create the Object, rather than to create the Object and then use it in the validation. But the combined method is simpler.

Using only a Regular Expression

This is fairly unreasonable, except as an intellectual exercise. I have found Date validation in Javascript in the archives of news:comp.lang.javascript. It is a validator for the years 1900 to 2000, DMY order. I have verified its RegExp. I have also written and tested a RegExp to validate all dates YYYY-MM-DD, where the letters represent any decimal digit. See page js-dvreg.htm.

Numeric Input (Year, Month, Day) using a Date Object

To validate a numeric Gregorian date, one can set it into a date object with new Date(FullYr, Mo, Dy) (if the date is a string, use a RegExp to check the format and decompose it, and remember that the fields may be in the wrong order). Then see whether the object yields the three values set. This approach is elegant, terse, but not the fastest.

I believe that it is both necessary and sufficient to check just two fields, if the inputs are integer. Examples: if 2000-13-31 is given, 2001-01-31 will be found; if 2000-03-00 is given, 2000-02-29 will be found; if 2001-07-370 is given, 2002-07-05 should be found (note that if the year is not explicitly checked, 00..99 can be used for 1900-1999, but with error for 00-02-29).

Preference among the above needs consideration; my choice has been ValidDate as in Include Files :-


P4 3GHz XP sp2 IE6 : ~ 3.5 s

But if the date is selected by Y M D drop-downs, it is only necessary to check M or D :-

Likewise if the Month and Year fields are already known to have one or two decimal digits only.

See also function ifXisOK in JavaScript : Object DATE2.

Numeric Input (Year, Month, Day) using Arithmetic

The following validation function DateOK (2004-04-18 ff.) is significantly faster and not much longer; there is no need to evaluate Leap Year until Feb 29th is noted, and if a 29th has failed a month-length test for a valid month then the month must be February.

Timing Comparisons

Functions DateOK2b DateOK3 are wondrous constructions by RC which my older technology cannot display effectively.

    P4 3GHz XP sp2 IE6 : 17 seconds
   

Note : currently only Feb 29th is timed.

Opera 9.21 to 9.25 used to fail in FullTest at 2038; Opera Summer Time refers.

I got, with PII/300 IE4, about 390, 110, 80, 23, 15, 22, 195 microseconds; and with P4 3GHz XP sp2 IE6, about 35, 19, 11, 5, 3, 7, 9 microseconds. Comparing first and last, arithmetic checking is faster even if a Date Object must be created. The UTC method is faster than the local one.

String Input (e.g. YYYY-MM-DD)

Before using the previous sections, check the character pattern and extract the numbers. Here, ISO 8601 YYYY-MM-DD is used, though the order and separator can easily be changed.

Choices :-

Merged Input and Validation

N.B. As Days is known by RegExp to be in 0..99, it seems only necessary to test the Month of the Date Object.

Testing

JavaScript ISO 8601 Date String Parser/Validator Demo

a date in ISO 8601 format; range (AD) 100-01-01 to 275760-09-13;
      A, B, E return Number < 0 for an error, else array of Yr, Mo, Dy;
A   B   give valid [Y, M, D] or error message
C   D   give valid object or undefined
E   As A, B

See also below.

Verifying a Hotel Booking

This checks that the dates are valid dates, that date of arrival is later than today, and date of departure is later than date of arrival. It ignores Time Zone effects, but allows for Summer Time.

Arr :   Dep :    

Using Double Conversion

If one has an output method which gives a date in a string format which new Date will accept, or nearly so, for example ISOlocaldateStr, one can test a string S in that format by double conversion :-

ISO format uses '-' for separators; new Date() accepts '/' instead. The output method must tolerate NaN.

Input :     OK :

Time Validating

Note that not all civil times of day are valid every day; when Summer Time starts, that day has some time missing (and when it stops, some is repeated). In the UK, this affects the "interval" 01:00 - 02:00 civil time.

On the last day of the half-year, 23:59:60 UTC can be a valid time; JavaScript does not know this.

Either validate as for dates, checking read-back on hours, minutes, and seconds; or test each field for range. Also consider special treatment for leap seconds and TZ offset changes.

In some cases, it may be necessary to accept 24:00 or higher.

Avoid a.m. and p.m.; one cannot be sure that the user will get them right, especially for 12:00 ≤ time < 1:00 . Using the 24-hour clock is much safer. But see below.

Testing for String Use

The following should accept a one- or two- digit hour, optionally followed by two-digit minutes.

JavaScript ISO 8601 Time String Validator Demo



RegExp /^(24):(00)|([01][0-9]|2[0-3]):([0-5][0-9])$/ may also serve, for a less flexible format requiring 4 digits but allowing 24:00.

Testing and Evaluating

JavaScript ISO 8601 Time String Parser/Validator Demo


    returns Number < 0 for an error, else Array of Hr, Mn, Sc;
  if Hr<0 then Error Message else Hr,Mn,Sc as an array of strings.

First check for hh:mm:ss with a RegExp such as /^(\d\d):(\d\d):(\d\d)$/ , validate.

AM/PM Times

For conversion without validation, see 9: Output Formatting.

It seems that a datetime that is valid with any form of am/pm must be valid, although different, without it; so one can add hour-amending code to an existing validator, and, if the new field exists, amend the Hours by converting 12 to 0 and adding 12 for p.m. - if I understand 12 a.m. & 12 p.m. correctly. It is necessary to check for the 'm', since a single letter can denote a "military" time zone.

In-lining ValidTime would ease returning of a Date Object. For a.m./p.m, the dots are optional and case is ignored.

JavaScript US Time String Parser/Validator Demo


      returns Number < 0 for an error, else array of Hr, Mn;
  =
if Hr<0 then Error Message else Hr,Mn as an array of numbers.

As is, allows hours 00-12; easily changed to reject 00. Addition of a seconds field is straightforward.

I have read that the Japanese use 0 AM & 0 PM for midnight & noon.

Validated Input Demonstrations

For Time, or Date-and-Time, one can use the same basic methods, omitting what is irrelevant and adjusting where needed.

General Free-form Date Input with Validation

One could use three separate input windows, but it would not shorten the code.

Script version ≥ #10



  Some are invalid. Also input your own. Omit Day-of-Week.

The function "DatVal" returns, in an array, a boolean for validity, and, if valid, a Date object.

An English (German) month name, in sufficient letters, will first be converted to a number, in situ; as will a month in Roman numerals. Suffixes st nd rd th (te ste) will be removed. A year less than 100 will be converted to 1960-2059, by optional code readily adaptable for other 100-year ranges. The minimum date is 0100-01-01, the maximum is 275760-09-13. Arbitrary field separators, represented here by _, work.

  D5+ expects    Y+MMDD   e.g. 20030215          030215
  ISO expects  Y+_M+_D+   e.g. 2003-2-15    2003 Feb 15
  EU  expects  D+_M+_Y+   e.g. 15 Okt, 2003    15.02.03
  NA  expects  M+_D+_Y+   e.g. Feb 15th, 2003   2/15/03

Individual sections for language, Roman months, alphabetic months, suffixes, two-digit year, and the buttons can easily be removed; the basic conversion and validation function takes no more than ten lines. See "DatVal", via View Source. Suffixes are not checked (but must be in the current language); a month-name is converted to a number regardless of position. Users offering non-English should check language ...

The above does not, or does not yet, allow auto-recognition of [YYYY, month-in- letters, day cardinal or ordinal] in any order, but that should not be too difficult.

The Y-M-D combination is validated as above.

Field Sorting

For an all-numeric Gregorian date to be intrinsically unambiguous, it must generally be of the form /\d{3,}\D+\d+\D+\d+/ for which the field order is known (Y M D).

But, whatever order the fields are in, if the month is given in letters (in full, as a TLA, or as Roman numerals), and the language is known, then the date is unambiguous (apart from guess-the-century error) if the value of the year field is greater than the greatest possible day field value - in which case the year value is greater than the actual day value. Even "Mar 2006 15" can only have one meaning, likewise "27 Feb 29".

ISTM that this function will in all cases above put the fields into an array in a known order (M D Y), which is good enough for subsequent processing (it also strips day suffix as in 9th) :-

  Order M D Y
  DatVal test

Input is a String with month in letters and year & date as ordinary numbers, in any order; output is an Array of month, day, year in that order. Needs checking.

ISO Date Input with Validation

This is as above, simplified; it requires exactly YYYY-MM-DD as input. Simply re-ordering V[1] V[2] V[3] and adjusting the separators in the RegExp would adapt it for EU or NA conventions.

Script version ≥ #1 :-

   

The function "ISODateValue" returns, in an array, a boolean for validity, and either NaN or a Date Object.

The Y-M-D combination is validated as above. See also above.

Drop-Down/Pick Date Input

Some prefer to use drop-down boxes rather than typing for entering a date, although that seems slower. The varying month-length can cause difficulty; solutions allowing only valid entry, for YMD and YWD, are now in 6: Date/Time Choosers.

That page also has a Picker, showing a month's calendar.

JavaScript Date and Time Index
Home Page
Mail: no HTML
© Dr J R Stockton, near London, UK.
All Rights Reserved.
These pages are tested mainly with Firefox and W3's Tidy.
This site, , is maintained by me.
Head.