Why does Date accept negative values?










6















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 ?!!










share|improve this question



















  • 1





    @mplungjan note the word since

    – TrojanByAccident
    Dec 27 '16 at 7:28











  • Note that new Date(0) is 1970 (with relevant TZ)

    – mplungjan
    Dec 27 '16 at 7:34











  • @mplungjan does this mean there is a way to represent a time in BC ?

    – Flying Gambit
    Dec 27 '16 at 7:35











  • @FlyingGambit Gregorian calendar can be "reverse extended" to BC dates, but it will cease to be historically accurate long before that. Jesus did not invent the Gregorian calendar.

    – Sheepy
    Dec 27 '16 at 10:44












  • @TrojanByAccident, this is the number of milliseconds that is calculated since the epoch. Here the term since give a direction in time. So positive will be after, negative will be before. (this is how I understand it)

    – AxelH
    Dec 27 '16 at 12:56
















6















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 ?!!










share|improve this question



















  • 1





    @mplungjan note the word since

    – TrojanByAccident
    Dec 27 '16 at 7:28











  • Note that new Date(0) is 1970 (with relevant TZ)

    – mplungjan
    Dec 27 '16 at 7:34











  • @mplungjan does this mean there is a way to represent a time in BC ?

    – Flying Gambit
    Dec 27 '16 at 7:35











  • @FlyingGambit Gregorian calendar can be "reverse extended" to BC dates, but it will cease to be historically accurate long before that. Jesus did not invent the Gregorian calendar.

    – Sheepy
    Dec 27 '16 at 10:44












  • @TrojanByAccident, this is the number of milliseconds that is calculated since the epoch. Here the term since give a direction in time. So positive will be after, negative will be before. (this is how I understand it)

    – AxelH
    Dec 27 '16 at 12:56














6












6








6


1






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 ?!!










share|improve this question
















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 ?!!







javascript






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 27 '16 at 8:02







Flying Gambit

















asked Dec 27 '16 at 7:24









Flying GambitFlying Gambit

738724




738724







  • 1





    @mplungjan note the word since

    – TrojanByAccident
    Dec 27 '16 at 7:28











  • Note that new Date(0) is 1970 (with relevant TZ)

    – mplungjan
    Dec 27 '16 at 7:34











  • @mplungjan does this mean there is a way to represent a time in BC ?

    – Flying Gambit
    Dec 27 '16 at 7:35











  • @FlyingGambit Gregorian calendar can be "reverse extended" to BC dates, but it will cease to be historically accurate long before that. Jesus did not invent the Gregorian calendar.

    – Sheepy
    Dec 27 '16 at 10:44












  • @TrojanByAccident, this is the number of milliseconds that is calculated since the epoch. Here the term since give a direction in time. So positive will be after, negative will be before. (this is how I understand it)

    – AxelH
    Dec 27 '16 at 12:56













  • 1





    @mplungjan note the word since

    – TrojanByAccident
    Dec 27 '16 at 7:28











  • Note that new Date(0) is 1970 (with relevant TZ)

    – mplungjan
    Dec 27 '16 at 7:34











  • @mplungjan does this mean there is a way to represent a time in BC ?

    – Flying Gambit
    Dec 27 '16 at 7:35











  • @FlyingGambit Gregorian calendar can be "reverse extended" to BC dates, but it will cease to be historically accurate long before that. Jesus did not invent the Gregorian calendar.

    – Sheepy
    Dec 27 '16 at 10:44












  • @TrojanByAccident, this is the number of milliseconds that is calculated since the epoch. Here the term since give a direction in time. So positive will be after, negative will be before. (this is how I understand it)

    – AxelH
    Dec 27 '16 at 12:56








1




1





@mplungjan note the word since

– TrojanByAccident
Dec 27 '16 at 7:28





@mplungjan note the word since

– TrojanByAccident
Dec 27 '16 at 7:28













Note that new Date(0) is 1970 (with relevant TZ)

– mplungjan
Dec 27 '16 at 7:34





Note that new Date(0) is 1970 (with relevant TZ)

– mplungjan
Dec 27 '16 at 7:34













@mplungjan does this mean there is a way to represent a time in BC ?

– Flying Gambit
Dec 27 '16 at 7:35





@mplungjan does this mean there is a way to represent a time in BC ?

– Flying Gambit
Dec 27 '16 at 7:35













@FlyingGambit Gregorian calendar can be "reverse extended" to BC dates, but it will cease to be historically accurate long before that. Jesus did not invent the Gregorian calendar.

– Sheepy
Dec 27 '16 at 10:44






@FlyingGambit Gregorian calendar can be "reverse extended" to BC dates, but it will cease to be historically accurate long before that. Jesus did not invent the Gregorian calendar.

– Sheepy
Dec 27 '16 at 10:44














@TrojanByAccident, this is the number of milliseconds that is calculated since the epoch. Here the term since give a direction in time. So positive will be after, negative will be before. (this is how I understand it)

– AxelH
Dec 27 '16 at 12:56






@TrojanByAccident, this is the number of milliseconds that is calculated since the epoch. Here the term since give a direction in time. So positive will be after, negative will be before. (this is how I understand it)

– AxelH
Dec 27 '16 at 12:56













4 Answers
4






active

oldest

votes


















14















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 eopch 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 Earth 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.







share|improve this answer

























  • Just a question - why does new Date('00000100') report the same as new Date(0100)?

    – TrojanByAccident
    Dec 27 '16 at 22:57











  • @TrojanByAccident I tested in Firefox 50 and Edge 38, both reports "Invalid Date" for new Date("00000100"), so don't do that. Chrome 55 parse it as new Date("0100") not new Date(0100) (type matters).

    – Sheepy
    Dec 28 '16 at 5:05












  • Interesting. Testing in Chrome 55, new Date('00000100') reports as Fri Jan 01 100, and new Date(00000100) reports as Wed Dec 31 1969

    – TrojanByAccident
    Dec 28 '16 at 5:29


















1














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.






share|improve this answer























  • I am unable to open that link due to web security issues, however , can you explain it in brief so that even if the link breaks in future, we still have some concrete answer

    – Flying Gambit
    Dec 27 '16 at 7:37











  • I really don't think we're allowed to just copy paste someone elses blog post on the topic

    – darryn.ten
    Dec 27 '16 at 7:39






  • 2





    You could always quote it. I say this because I can't open that link either (just infinite loading icon)

    – Jhecht
    Dec 27 '16 at 7:41






  • 3





    @darryn.ten you can sumarise the ideas or copy small pieces that are relevant. As long as you link to the source it is usually considered OK. As it stands your post could be flagged as a link only answer

    – K Scandrett
    Dec 27 '16 at 7:43











  • @darryn.ten That explains how new Date('-9999', '99', '99'); // "-009991-07-08T04:00:00.000Z" works but not the rest, especially new Date('0000', '00', '00'); // "1899-12-31T05:00:00.000Z"

    – Flying Gambit
    Dec 27 '16 at 8:28



















0















Then why does it accept negative values ?




You are confusing the description of how the data is stored internally with the arguments that the constructor function takes.




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




No, for the above reason. Nothing stops the year, month or day from being negative. You just end up adding a negative number to something.




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




Numbers which start with a 0 are expressed in octal, not decimal. 0100 === 64.






share|improve this answer






























    0














    Please have a look at the documentation




    Year: Values from 0 to 99 map to the years 1900 to 1999




    1. 1970 with appropriate timezone: new Date(0); // int MS since 1970

    2. 1900 (or 1899 with applied timezone): new Date(0,0) or new Date(0,0,1) - date is 1 based, month and year are 0 based

    3. 1899: new Date(0,0,-1)





    share|improve this answer
























      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f41340836%2fwhy-does-date-accept-negative-values%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      14















      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 eopch 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 Earth 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.







      share|improve this answer

























      • Just a question - why does new Date('00000100') report the same as new Date(0100)?

        – TrojanByAccident
        Dec 27 '16 at 22:57











      • @TrojanByAccident I tested in Firefox 50 and Edge 38, both reports "Invalid Date" for new Date("00000100"), so don't do that. Chrome 55 parse it as new Date("0100") not new Date(0100) (type matters).

        – Sheepy
        Dec 28 '16 at 5:05












      • Interesting. Testing in Chrome 55, new Date('00000100') reports as Fri Jan 01 100, and new Date(00000100) reports as Wed Dec 31 1969

        – TrojanByAccident
        Dec 28 '16 at 5:29















      14















      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 eopch 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 Earth 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.







      share|improve this answer

























      • Just a question - why does new Date('00000100') report the same as new Date(0100)?

        – TrojanByAccident
        Dec 27 '16 at 22:57











      • @TrojanByAccident I tested in Firefox 50 and Edge 38, both reports "Invalid Date" for new Date("00000100"), so don't do that. Chrome 55 parse it as new Date("0100") not new Date(0100) (type matters).

        – Sheepy
        Dec 28 '16 at 5:05












      • Interesting. Testing in Chrome 55, new Date('00000100') reports as Fri Jan 01 100, and new Date(00000100) reports as Wed Dec 31 1969

        – TrojanByAccident
        Dec 28 '16 at 5:29













      14












      14








      14








      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 eopch 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 Earth 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.







      share|improve this answer
















      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 eopch 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 Earth 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.








      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jan 11 '18 at 3:19

























      answered Dec 27 '16 at 12:19









      SheepySheepy

      11.6k33158




      11.6k33158












      • Just a question - why does new Date('00000100') report the same as new Date(0100)?

        – TrojanByAccident
        Dec 27 '16 at 22:57











      • @TrojanByAccident I tested in Firefox 50 and Edge 38, both reports "Invalid Date" for new Date("00000100"), so don't do that. Chrome 55 parse it as new Date("0100") not new Date(0100) (type matters).

        – Sheepy
        Dec 28 '16 at 5:05












      • Interesting. Testing in Chrome 55, new Date('00000100') reports as Fri Jan 01 100, and new Date(00000100) reports as Wed Dec 31 1969

        – TrojanByAccident
        Dec 28 '16 at 5:29

















      • Just a question - why does new Date('00000100') report the same as new Date(0100)?

        – TrojanByAccident
        Dec 27 '16 at 22:57











      • @TrojanByAccident I tested in Firefox 50 and Edge 38, both reports "Invalid Date" for new Date("00000100"), so don't do that. Chrome 55 parse it as new Date("0100") not new Date(0100) (type matters).

        – Sheepy
        Dec 28 '16 at 5:05












      • Interesting. Testing in Chrome 55, new Date('00000100') reports as Fri Jan 01 100, and new Date(00000100) reports as Wed Dec 31 1969

        – TrojanByAccident
        Dec 28 '16 at 5:29
















      Just a question - why does new Date('00000100') report the same as new Date(0100)?

      – TrojanByAccident
      Dec 27 '16 at 22:57





      Just a question - why does new Date('00000100') report the same as new Date(0100)?

      – TrojanByAccident
      Dec 27 '16 at 22:57













      @TrojanByAccident I tested in Firefox 50 and Edge 38, both reports "Invalid Date" for new Date("00000100"), so don't do that. Chrome 55 parse it as new Date("0100") not new Date(0100) (type matters).

      – Sheepy
      Dec 28 '16 at 5:05






      @TrojanByAccident I tested in Firefox 50 and Edge 38, both reports "Invalid Date" for new Date("00000100"), so don't do that. Chrome 55 parse it as new Date("0100") not new Date(0100) (type matters).

      – Sheepy
      Dec 28 '16 at 5:05














      Interesting. Testing in Chrome 55, new Date('00000100') reports as Fri Jan 01 100, and new Date(00000100) reports as Wed Dec 31 1969

      – TrojanByAccident
      Dec 28 '16 at 5:29





      Interesting. Testing in Chrome 55, new Date('00000100') reports as Fri Jan 01 100, and new Date(00000100) reports as Wed Dec 31 1969

      – TrojanByAccident
      Dec 28 '16 at 5:29













      1














      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.






      share|improve this answer























      • I am unable to open that link due to web security issues, however , can you explain it in brief so that even if the link breaks in future, we still have some concrete answer

        – Flying Gambit
        Dec 27 '16 at 7:37











      • I really don't think we're allowed to just copy paste someone elses blog post on the topic

        – darryn.ten
        Dec 27 '16 at 7:39






      • 2





        You could always quote it. I say this because I can't open that link either (just infinite loading icon)

        – Jhecht
        Dec 27 '16 at 7:41






      • 3





        @darryn.ten you can sumarise the ideas or copy small pieces that are relevant. As long as you link to the source it is usually considered OK. As it stands your post could be flagged as a link only answer

        – K Scandrett
        Dec 27 '16 at 7:43











      • @darryn.ten That explains how new Date('-9999', '99', '99'); // "-009991-07-08T04:00:00.000Z" works but not the rest, especially new Date('0000', '00', '00'); // "1899-12-31T05:00:00.000Z"

        – Flying Gambit
        Dec 27 '16 at 8:28
















      1














      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.






      share|improve this answer























      • I am unable to open that link due to web security issues, however , can you explain it in brief so that even if the link breaks in future, we still have some concrete answer

        – Flying Gambit
        Dec 27 '16 at 7:37











      • I really don't think we're allowed to just copy paste someone elses blog post on the topic

        – darryn.ten
        Dec 27 '16 at 7:39






      • 2





        You could always quote it. I say this because I can't open that link either (just infinite loading icon)

        – Jhecht
        Dec 27 '16 at 7:41






      • 3





        @darryn.ten you can sumarise the ideas or copy small pieces that are relevant. As long as you link to the source it is usually considered OK. As it stands your post could be flagged as a link only answer

        – K Scandrett
        Dec 27 '16 at 7:43











      • @darryn.ten That explains how new Date('-9999', '99', '99'); // "-009991-07-08T04:00:00.000Z" works but not the rest, especially new Date('0000', '00', '00'); // "1899-12-31T05:00:00.000Z"

        – Flying Gambit
        Dec 27 '16 at 8:28














      1












      1








      1







      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.






      share|improve this answer













      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.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Dec 27 '16 at 7:31









      darryn.tendarryn.ten

      4,83923362




      4,83923362












      • I am unable to open that link due to web security issues, however , can you explain it in brief so that even if the link breaks in future, we still have some concrete answer

        – Flying Gambit
        Dec 27 '16 at 7:37











      • I really don't think we're allowed to just copy paste someone elses blog post on the topic

        – darryn.ten
        Dec 27 '16 at 7:39






      • 2





        You could always quote it. I say this because I can't open that link either (just infinite loading icon)

        – Jhecht
        Dec 27 '16 at 7:41






      • 3





        @darryn.ten you can sumarise the ideas or copy small pieces that are relevant. As long as you link to the source it is usually considered OK. As it stands your post could be flagged as a link only answer

        – K Scandrett
        Dec 27 '16 at 7:43











      • @darryn.ten That explains how new Date('-9999', '99', '99'); // "-009991-07-08T04:00:00.000Z" works but not the rest, especially new Date('0000', '00', '00'); // "1899-12-31T05:00:00.000Z"

        – Flying Gambit
        Dec 27 '16 at 8:28


















      • I am unable to open that link due to web security issues, however , can you explain it in brief so that even if the link breaks in future, we still have some concrete answer

        – Flying Gambit
        Dec 27 '16 at 7:37











      • I really don't think we're allowed to just copy paste someone elses blog post on the topic

        – darryn.ten
        Dec 27 '16 at 7:39






      • 2





        You could always quote it. I say this because I can't open that link either (just infinite loading icon)

        – Jhecht
        Dec 27 '16 at 7:41






      • 3





        @darryn.ten you can sumarise the ideas or copy small pieces that are relevant. As long as you link to the source it is usually considered OK. As it stands your post could be flagged as a link only answer

        – K Scandrett
        Dec 27 '16 at 7:43











      • @darryn.ten That explains how new Date('-9999', '99', '99'); // "-009991-07-08T04:00:00.000Z" works but not the rest, especially new Date('0000', '00', '00'); // "1899-12-31T05:00:00.000Z"

        – Flying Gambit
        Dec 27 '16 at 8:28

















      I am unable to open that link due to web security issues, however , can you explain it in brief so that even if the link breaks in future, we still have some concrete answer

      – Flying Gambit
      Dec 27 '16 at 7:37





      I am unable to open that link due to web security issues, however , can you explain it in brief so that even if the link breaks in future, we still have some concrete answer

      – Flying Gambit
      Dec 27 '16 at 7:37













      I really don't think we're allowed to just copy paste someone elses blog post on the topic

      – darryn.ten
      Dec 27 '16 at 7:39





      I really don't think we're allowed to just copy paste someone elses blog post on the topic

      – darryn.ten
      Dec 27 '16 at 7:39




      2




      2





      You could always quote it. I say this because I can't open that link either (just infinite loading icon)

      – Jhecht
      Dec 27 '16 at 7:41





      You could always quote it. I say this because I can't open that link either (just infinite loading icon)

      – Jhecht
      Dec 27 '16 at 7:41




      3




      3





      @darryn.ten you can sumarise the ideas or copy small pieces that are relevant. As long as you link to the source it is usually considered OK. As it stands your post could be flagged as a link only answer

      – K Scandrett
      Dec 27 '16 at 7:43





      @darryn.ten you can sumarise the ideas or copy small pieces that are relevant. As long as you link to the source it is usually considered OK. As it stands your post could be flagged as a link only answer

      – K Scandrett
      Dec 27 '16 at 7:43













      @darryn.ten That explains how new Date('-9999', '99', '99'); // "-009991-07-08T04:00:00.000Z" works but not the rest, especially new Date('0000', '00', '00'); // "1899-12-31T05:00:00.000Z"

      – Flying Gambit
      Dec 27 '16 at 8:28






      @darryn.ten That explains how new Date('-9999', '99', '99'); // "-009991-07-08T04:00:00.000Z" works but not the rest, especially new Date('0000', '00', '00'); // "1899-12-31T05:00:00.000Z"

      – Flying Gambit
      Dec 27 '16 at 8:28












      0















      Then why does it accept negative values ?




      You are confusing the description of how the data is stored internally with the arguments that the constructor function takes.




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




      No, for the above reason. Nothing stops the year, month or day from being negative. You just end up adding a negative number to something.




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




      Numbers which start with a 0 are expressed in octal, not decimal. 0100 === 64.






      share|improve this answer



























        0















        Then why does it accept negative values ?




        You are confusing the description of how the data is stored internally with the arguments that the constructor function takes.




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




        No, for the above reason. Nothing stops the year, month or day from being negative. You just end up adding a negative number to something.




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




        Numbers which start with a 0 are expressed in octal, not decimal. 0100 === 64.






        share|improve this answer

























          0












          0








          0








          Then why does it accept negative values ?




          You are confusing the description of how the data is stored internally with the arguments that the constructor function takes.




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




          No, for the above reason. Nothing stops the year, month or day from being negative. You just end up adding a negative number to something.




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




          Numbers which start with a 0 are expressed in octal, not decimal. 0100 === 64.






          share|improve this answer














          Then why does it accept negative values ?




          You are confusing the description of how the data is stored internally with the arguments that the constructor function takes.




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




          No, for the above reason. Nothing stops the year, month or day from being negative. You just end up adding a negative number to something.




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




          Numbers which start with a 0 are expressed in octal, not decimal. 0100 === 64.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 27 '16 at 11:51









          QuentinQuentin

          641k718651035




          641k718651035





















              0














              Please have a look at the documentation




              Year: Values from 0 to 99 map to the years 1900 to 1999




              1. 1970 with appropriate timezone: new Date(0); // int MS since 1970

              2. 1900 (or 1899 with applied timezone): new Date(0,0) or new Date(0,0,1) - date is 1 based, month and year are 0 based

              3. 1899: new Date(0,0,-1)





              share|improve this answer





























                0














                Please have a look at the documentation




                Year: Values from 0 to 99 map to the years 1900 to 1999




                1. 1970 with appropriate timezone: new Date(0); // int MS since 1970

                2. 1900 (or 1899 with applied timezone): new Date(0,0) or new Date(0,0,1) - date is 1 based, month and year are 0 based

                3. 1899: new Date(0,0,-1)





                share|improve this answer



























                  0












                  0








                  0







                  Please have a look at the documentation




                  Year: Values from 0 to 99 map to the years 1900 to 1999




                  1. 1970 with appropriate timezone: new Date(0); // int MS since 1970

                  2. 1900 (or 1899 with applied timezone): new Date(0,0) or new Date(0,0,1) - date is 1 based, month and year are 0 based

                  3. 1899: new Date(0,0,-1)





                  share|improve this answer















                  Please have a look at the documentation




                  Year: Values from 0 to 99 map to the years 1900 to 1999




                  1. 1970 with appropriate timezone: new Date(0); // int MS since 1970

                  2. 1900 (or 1899 with applied timezone): new Date(0,0) or new Date(0,0,1) - date is 1 based, month and year are 0 based

                  3. 1899: new Date(0,0,-1)






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Dec 27 '16 at 13:43

























                  answered Dec 27 '16 at 11:42









                  mplungjanmplungjan

                  87.3k21122181




                  87.3k21122181



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f41340836%2fwhy-does-date-accept-negative-values%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      這個網誌中的熱門文章

                      How to read a connectionString WITH PROVIDER in .NET Core?

                      Node.js Script on GitHub Pages or Amazon S3

                      Museum of Modern and Contemporary Art of Trento and Rovereto