Why does Date accept negative values?

Well, firstly, you're passing in string instead of an integer, so that might have something to do with your issues here.

Check this out, it explains negative dates quite nicely, and there is an explanation for your exact example.


This is hard and inconsistent, yes. The JavaScript Date object was based on the one in Java 1.0, which is so bad that Java redesigned a whole new package. JavaScript is not so lucky.

  1. Date is "based on" unix epoch because of how it is defined. It's internal details.
  2. 1st Jan 1970 is the actual time of this baseline.
  3. since is the direction of the timestamp value: forward for +ve, backward for -ve.
  4. Externally, the Date constructor has several different usages, based on parameters:

Zero parameters = current time

new Date()   // Current datetime. Every tutorial should teach this.

The time is absolute, but 'displayed' timezone may be UTC or local.

For simplicity, this answer will use only UTC. Keep timezone in mind when you test.

One numeric parameter = timestamp @ 1970

new Date(0)    // 0ms from 1970-01-01T00:00:00Z.
new Date(100)  // 100ms from 1970 baseline.
new Date(-10)  // -10ms from 1970 baseline.

One string parameter = iso date string

new Date('000')        // Short years are invalid, need at least four digits.
new Date('0000')       // 0000-01-01.  Valid because there are four digits.
new Date('1900')       // 1900-01-01.
new Date('1900-01-01') // Same as above.
new Date('1900-01-01T00:00:00') // Same as above.
new Date('-000001')    // 2 BC, see below. Yes you need all those zeros.

Two or more parameters = year, month, and so on @ 1900 or 0000

new Date(0,0)      // 1900-01-01T00:00:00Z.
new Date(0,0,1)    // Same as above.  Date is 1 based.
new Date(0,0,0)    // 1 day before 1900 = 1899-12-31.
new Date(0,-1)     // 1 month before 1900 = 1899-12-01.
new Date(0,-1,0)   // 1 month and 1 day before 1900 = 1899-11-30.
new Date(0,-1,-1)  // 1 month and *2* days before 1900 = 1899-11-29.
new Date('0','1')  // 1900-02-01. Two+ params always cast to year and month.
new Date(100,0)    // 0100-01-01. Year > 99 use year 0 not 1900.
new Date(1900,0)   // 1900-01-01. Same as new Date(0,0). So intuitive!

Negative year = BC

new Date(-1,0)    // 1 year before 0000-01-01 = 1 year before 1 BC = 2 BC.
new Date(-1,0,-1) // 2 days before 2 BC.  Fun, yes?  I'll leave this as an exercise.

There is no 0 AC. There is 1 AC and the year before it is 1 BC. Year 0 is 1 BC by convention.

2 BC is displayed as year "-000001". The extra zeros are required because it is outside normal range (0000 to 9999). If you new Date(12345,0) you will get "+012345-01-01", too.

Of course, the Gregorian calendar, adopted as late as 1923 in Europe, will cease to be meaningful long before we reach BC. In fact, scholars accept that Jesus wasn't born in 1 BC. But with the stars and the land moving at this scale, calendar is the least of your worries.


The remaining given code are just variations of these cases. For example:

new Date(0100)          // One number = epoch. 0100 (octal) = 64ms since 1970
new Date('0100')        // One string = iso = 0100-01-01.
new Date(-9999, 99, 99) // 9999 years before BC 1 and then add 99 months and 98 days

Hope you had some fun time. Please don't forget to vote up. :)

To stay sane, keep all dates in ISO 8601 and use the string constructor.
And if you need to handle timezone, keep all datetimes in UTC.

Tags:

Javascript