Why Does JavaScript Parse 'Route 66' as a Date? Understanding Date Constructor Behavior
Problem
When I used JavaScript’s Date constructor to validate user input, I found that random strings like “Route 66” were accepted as valid dates:
new Date("Route 66")// Sat Jan 01 1966 00:00:00 GMT-0500
new Date("Beverly Hills, 90210")// Mon Jan 01 90210 00:00:00 GMT-0500This caused a bug where addresses and business names in our app were being displayed as dates.
Environment
- Node.js v20.x
- Chrome 120+ (V8 engine)
- JavaScript ES2023
What happened?
We had a bug in our app. Addresses and business names were being converted to dates unexpectedly.
The root cause: we used the Date constructor as a fallback parser to catch unexpected date formats:
function isValidDate(str) { return !isNaN(new Date(str).getTime());}
isValidDate("2020-01-23") // true (expected)isValidDate("Route 66") // true! (returns year 1966)isValidDate("Beverly Hills, 90210") // true! (returns year 90,210)I thought the Date constructor would reject non-date strings. But it doesn’t. It tries to be helpful by extracting any numbers that could represent a date.
Here are more examples of this behavior:
// Expected behaviornew Date("2020-01-23")// Wed Jan 22 2020 19:00:00 GMT-0500 (ISO format, parsed as UTC)
// Unexpected behaviornew Date("Route 66")// Sat Jan 01 1966 00:00:00 GMT-0500 (interprets 66 as year 1966)
new Date("Beverly Hills, 90210")// Mon Jan 01 90210 00:00:00 GMT-0500 (year 90,210!)
new Date("Today is 2020-01-23")// Thu Jan 23 2020 00:00:00 GMT-0500 (extracts date from sentence)How to solve it?
I tried a few approaches.
Solution 1: Strict ISO 8601 Validation
The Date constructor only guarantees consistent parsing for ISO 8601 format (YYYY-MM-DD). For other formats, browsers behave differently.
function isValidISODate(str) { // Strict ISO 8601 regex const isoRegex = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{3})?Z?)?$/;
if (!isoRegex.test(str)) { return false; }
const date = new Date(str); const timestamp = date.getTime();
// Check for Invalid Date return !isNaN(timestamp);}
// UsageisValidISODate("2020-01-23") // trueisValidISODate("Route 66") // falseisValidISODate("Beverly Hills, 90210") // falseisValidISODate("2020-13-45") // false (invalid month/day)This works for ISO dates. But what about other formats?
Solution 2: Use date-fns
For production code, I recommend using a dedicated date library. date-fns provides parseISO and isValid functions:
import { parseISO, isValid } from 'date-fns';
function parseDateSafely(str) { try { const date = parseISO(str); return isValid(date) ? date : null; } catch { return null; }}
// UsageparseDateSafely("2020-01-23") // Valid Date objectparseDateSafely("Route 66") // nullFor non-ISO formats, date-fns has parse with explicit format strings:
import { parse, isValid } from 'date-fns';
function parseCustomFormat(dateString, format) { const referenceDate = new Date(); const date = parse(dateString, format, referenceDate); return isValid(date) ? date : null;}
// UsageparseCustomFormat("01/23/2020", "MM/dd/yyyy"); // Valid Date objectparseCustomFormat("Route 66", "MM/dd/yyyy"); // nullThe reason
Why does JavaScript behave this way?
1. Legacy Parser Design
The Date constructor uses a parser designed to be maximally helpful. It was created in the early days of the web when developers passed date strings in many formats. The parser tries to extract date-like patterns from almost any string.
2. Implementation-Defined Behavior
The ECMAScript spec only mandates parsing for ISO 8601 format. Everything else is “implementation-defined,” meaning each browser can parse however it wants:
ECMAScript Spec:┌─────────────────┐│ ISO 8601 Format │ → Spec-defined, consistent across browsers└─────────────────┘ ↓┌─────────────────┐│ Other Formats │ → Implementation-defined, varies by browser└─────────────────┘3. Backward Compatibility
This behavior cannot change. Too many websites rely on the current parsing behavior. Changing it would break the web.
4. V8, SpiderMonkey, JavaScriptCore
Each JavaScript engine has its own legacy parser:
- V8 (Chrome/Node.js)
- SpiderMonkey (Firefox)
- JavaScriptCore (Safari)
They may parse the same string differently.
Summary
In this post, I showed why JavaScript’s Date constructor accepts random strings as dates. The key point is: never use the Date constructor for validation. Use strict ISO 8601 validation with regex, or use a library like date-fns. For new projects, consider the Temporal API which provides cleaner date handling.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 MDN: Date.parse()
- 👨💻 Reddit Discussion: JavaScript Date Parse Random Strings
- 👨💻 TC39 Temporal Proposal
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments