Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Date accept negative values?

Tags:

javascript

As per MDN

"Date objects are based on a time value that is the number of milliseconds since 1 January, 1970 UTC."

Then why does it accept negative values ?

Even if it did shouldn't negative value mean values before Jan 1, 1970 ?

new Date('0000', '00', '-1');   // "1899-12-30T05:00:00.000Z"
new Date('0000', '00', '00');   // "1899-12-31T05:00:00.000Z"
new Date('-9999', '99', '99');  // "-009991-07-08T04:00:00.000Z"

What is happening ?

Update

For some positive values , the year begins from 1900

new Date(100);                  // "1970-01-01T00:00:00.100Z"   // it says 100Z
new Date(0100);                 // "1970-01-01T00:00:00.064Z"   // it says 64Z
new Date("0006","06","06");     // "1906-07-06T04:00:00.000Z"

Also note that, in the last one, the date is shown as 4 which is wrong.

I suspect this is some sort of Y2K bug ?!!

like image 848
Flying Gambit Avatar asked Dec 27 '16 07:12

Flying Gambit


People also ask

Can Long accept negative values?

Does long long not support negative values ? Yes it does support negative values as long as it is not appended after unsigned .

Can datediff return a negative value?

Yes the datediff is returning a negative number. A minimal reproducible example is a great start when asking SQL questions.

What are negatives values?

A real quantity having a value less than zero ( < 0 ) is said to be negative. Negative numbers are denoted with a minus sign preceding the corresponding positive number, i.e., -2, -100.


2 Answers

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.

like image 145
Sheepy Avatar answered Oct 07 '22 15:10

Sheepy


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.

like image 21
darryn.ten Avatar answered Oct 07 '22 16:10

darryn.ten