414

In my Java Script app I have the date stored in a format like so:

2011-09-24

Now when I try using the above value to create a new Date object (so I can retrieve the date in a different format), the date always comes back one day off. See below:

var date = new Date("2011-09-24");
console.log(date);

logs:

Fri Sep 23 2011 20:00:00 GMT-0400 (Eastern Daylight Time)
levi
  • 23,693
  • 18
  • 59
  • 73
  • 35
    Javascript's Date class doesn't represent a date, it represents a timestamp (same in Java). To make it a date, it uses a time zone and that's the cause of your problem. It parses it with the GMT/UTC timezone (Sep 24 2011, **00**:00 UTC) and then outputs it with a different timezone of 4 hours (Sep 23 2011, **20**:00 GMT-0400). – Codo Sep 26 '11 at 14:26
  • 4
    I get "invalid date". Replace the '-' characters with '/' characters and try again. Or split the date into its bits and set the components individually (if you do that, subtract 1 from the month number). – RobG Sep 26 '11 at 14:28
  • 1
    @Codo - yes, good reply. ECMA-262 15.9.1.15 applies. The OP should use "2011-09-24T20:00:00-04:00" or similar. – RobG Sep 26 '11 at 14:34
  • 1
    I found that the format "Sep 24 2011" will return the proper date. See here for an explanation: http://stackoverflow.com/questions/2587345/javascript-date-parse – christurnerio Apr 02 '13 at 03:18
  • If you're working with ISO date, just add a space at the end of your date: ``new Date("2011-09-25\n");``. Another solution is to replace hyphen with slash: ``new Date("2011/09/25");`` – aldwinp35 Jul 01 '23 at 17:05

33 Answers33

479

There are several crazy things that happen with a JS DATE object that convert strings, for example consider the following date you provided

Note: The following examples may or may not be ONE DAY OFF depending on YOUR timezone and current time.

new Date("2011-09-24"); // Year-Month-Day
// => Fri Sep 23 2011 17:00:00 GMT-0700 (MST) - ONE DAY OFF.

However, if we rearrange the string format to Month-Day-Year...

new Date("09-24-2011");
// => Sat Sep 24 2011 00:00:00 GMT-0700 (MST) - CORRECT DATE.

Another strange one

new Date("2011-09-24");
// => Fri Sep 23 2011 17:00:00 GMT-0700 (MST) - ONE DAY OFF AS BEFORE.

new Date("2011/09/24"); // change from "-" to "/".
// => Sat Sep 24 2011 00:00:00 GMT-0700 (MST) - CORRECT DATE.

We could easily change hyphens in your date "2011-09-24" when making a new date

new Date("2011-09-24".replace(/-/g, '\/')); // => "2011/09/24".
// => Sat Sep 24 2011 00:00:00 GMT-0700 (MST) - CORRECT DATE.

What if we had a date string like "2011-09-24T00:00:00"

new Date("2011-09-24T00:00:00");
// => Fri Sep 23 2011 17:00:00 GMT-0700 (MST) - ONE DAY OFF.

Now change hyphen to forward slash as before; what happens?

new Date("2011/09/24T00:00:00");
// => Invalid Date.

I typically have to manage the date format 2011-09-24T00:00:00 so this is what I do.

new Date("2011-09-24T00:00:00".replace(/-/g, '\/').replace(/T.+/, ''));
// => Sat Sep 24 2011 00:00:00 GMT-0700 (MST) - CORRECT DATE.

UPDATE

If you provide separate arguments to the Date constructor you can get other useful outputs as described below

Note: arguments can be of type Number or String. I'll show examples with mixed values.

Get the first month and day of a given year

new Date(2011, 0); // Normal behavior as months in this case are zero based.
// => Sat Jan 01 2011 00:00:00 GMT-0700 (MST)

Get the last month and day of a year

new Date((2011 + 1), 0, 0); // The second zero roles back one day into the previous month's last day.
// => Sat Dec 31 2011 00:00:00 GMT-0700 (MST)

Example of Number, String arguments. Note the month is March because zero based months again.

new Date(2011, "02"); 
// => Tue Mar 01 2011 00:00:00 GMT-0700 (MST)

If we do the same thing but with a day of zero, we get something different.

new Date(2011, "02", 0); // Again the zero roles back from March to the last day of February.
// => Mon Feb 28 2011 00:00:00 GMT-0700 (MST)

Adding a day of zero to any year and month argument will get the last day of the previous month. If you continue with negative numbers you can continue rolling back another day

new Date(2011, "02", -1);
// => Sun Feb 27 2011 00:00:00 GMT-0700 (MST)
ctrlaltdeleon
  • 356
  • 3
  • 14
SoEzPz
  • 14,958
  • 8
  • 61
  • 64
  • 28
    This actually helped me the best. I just added the .replace(/-/g, '\/').replace(/T.+/, '') to the end of my data when I made a new date. Super easy! – Devin Prejean Jan 26 '16 at 14:51
  • 132
    Wow - javascript is terribly inconsistent. – psparrow Feb 09 '16 at 20:36
  • 3
    The .replace() calls really helped out in a pinch this evening. – disuse Mar 20 '16 at 06:44
  • 2
    yes i have tested this all, and its really strange. – chintan adatiya Jun 22 '16 at 16:18
  • 75
    All of this is due to the behavior of the underlying Date.parse() trying to follow ISO 8601. When the date string follows the yyyy-mm-dd format, it's assumed to be ISO 8601 with implicit UTC 00:00. When the string deviates from the format (e.g. mm-dd-yyyy or slash instead of hyphen), it falls back to the looser parser according to RFC 2822 which uses local time when the timezone is absent. Admittedly, this will all be quite arcane to an average person. – Mizstik Jul 04 '16 at 02:15
  • 9
    But not to us! This comment is a great addition. I didn't know why it did this, just that it did. – SoEzPz Jul 13 '16 at 18:39
  • 1
    This is beautiful. Somehow I didn't find your Q&A last time I ran into this and after wasting about 3-4 hours gave in and used this absurd function called "weirdDate" all over my typescript program: weirdDate(date: Date): Date { // ToDo find a better way to handle this weird date issue return new Date(new Date(date.toString()).setDate(new Date(date.toString()).getDate() + 1)); } It worked wonders for the moment but is bad... – Methodician Nov 12 '16 at 02:14
  • 1
    jesus! utter craziness, but the `replace()` technique helped me a lot. – Anjan Biswas Nov 19 '18 at 21:50
  • 2
    WOW. Been racking my brain over why my JS Date was the wrong day and turns out its simply because of the yyy-MM-dd format. Good thing the HTML5 date input MUST be formatted as yyy-MM-dd... Thank you for this explanation! – Brian Wright Dec 17 '18 at 20:52
  • 2
    Oh - and - is JS ever going to fix this? Having hyphens instead of slashes causing behavioral change is beyond bizarre. – Sat Thiru Jan 03 '19 at 07:46
  • 1
    One of the most useful answers I've seen related to dates so far on SO. – Train Oct 14 '19 at 20:00
  • Could someone please help me to reproduce the situation with one day off. I have a client who have this issue. I want to apply the .replace(/-/g, '\/').replace(/T.+/, '')) fix. But I can't test if it helps on my machine. new Date("2011-09-24") gives me the correct date. I change time in windows datetime settings to my client's timezone, but I still get the correct date. My local timezone is UTC+3:00, my client's timezone is UTC+6:00. What should I do see the one day off example on my computer? – Илья Иваницкий Feb 05 '21 at 15:11
  • 1
    Can you wait until your timezone is still today and your clients is at least one minute past midnight GMT the next day? Then see if it's one day off on your machine when applying new Date("yyyy-mm-dd") in that format. At that point you can test your fix. – SoEzPz Feb 05 '21 at 16:18
  • @SoEzPz, This does not help. The function in question is new Date("2021-02-18"). My current timezone is UTC+3:00. It is 21:30 here. My client is in the UTC+6:00 timezone. It is 00:30 there. I try new Date("2021-02-18") in my Chrome console. I get "Thu Feb 18 2021 03:00:00 GMT+0300". I change my system datetime settings to UTC+6:00. I try again. I get "Thu Feb 18 2021 06:00:00 GMT+0600". The date did not change. Hence, I still cannot reproduce this issue and am not sure if the .replace(/-/g, '\/').replace(/T.+/, '')) solution would fix it. I've seen it reproducing in my client's console though. – Илья Иваницкий Feb 06 '21 at 18:41
  • 1
    Can you switch your machine time before the current GMT time? You should see a rollback, then perhaps you can troubleshoot. – SoEzPz Feb 07 '21 at 05:25
  • 1
    @SoEzPz, Ah, finally got it! I set my machine time to UTC-4:00 and saw the date change in console. I applied the fix then and it worked. Thank you! – Илья Иваницкий Feb 07 '21 at 08:28
  • Another trick that worked for me is to add a few hours to the date e.g. `new Date(myDate + "06:00:00")` to ensure it evaluates to the correct date in my timezone. But replacing with slashes is a better solution. – twhitney Jul 12 '21 at 17:52
  • We really need the temporal standard to be implemented... – serraosays Apr 13 '22 at 22:27
  • I really can't believe this is true. Thanks for the replace() fix. still shaking my head. – Shayne Sep 12 '22 at 22:07
155

Notice that Eastern Daylight Time is -4 hours and that the hours on the date you're getting back are 20.

20h + 4h = 24h

which is midnight of 2011-09-24. The date was parsed in UTC (GMT) because you provided a date-only string without any time zone indicator. If you had given a date/time string w/o an indicator instead (new Date("2011-09-24T00:00:00")), it would have been parsed in your local timezone. (Historically there have been inconsistencies there, not least because the spec changed more than once, but modern browsers should be okay; or you can always include a timezone indicator.)

You're getting the right date, you just never specified the correct time zone.

If you need to access the date values, you can use getUTCDate() or any of the other getUTC*() functions:

var d,
  days;
d = new Date('2011-09-24');
days = ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'];
console.log(days[d.getUTCDay()]);
naveen
  • 53,448
  • 46
  • 161
  • 251
zzzzBov
  • 174,988
  • 54
  • 320
  • 367
  • 40
    How do you "specify the correct timezone"? The date constructor always interprets date string as UTC, but then adjusts for timezone. I can even do `new Date('2012-01-02 EDT') and still moves it back to the previous day due to applying the offset for daylight savings, which makes no sense because if I told you that is the date as per the current local timezone of EDT, then don't apply an additional offset to it. I told it the timezone was EDT but it still applies an **additional** offset moving it back one day. – AaronLS Jan 28 '13 at 17:43
  • 2
    @AaronLS, `EDT` is [daylight savings time (also known as summer time)](http://en.wikipedia.org/wiki/Daylight_saving_time), `EST` is the timezone that applies in January. – zzzzBov Jan 28 '13 at 17:59
  • Right, that's the fun part is writing something generic to determine that timezone. Because the goal is just to work with dates and disregard the time+timezone. More fun is to be had if you have leading zeros with/without: `new Date('2013-01-08')` == `Mon Jan 07 2013 19:00:00 GMT-0500 (Eastern Standard Time)` but `new Date('2013-1-8')` == `Tue Jan 08 2013 00:00:00 GMT-0500 (Eastern Standard Time)`. So even if you use getTimezoneOffset to normalize the dates, you better making sure you consistently have leading 0/double digit dates/months. – AaronLS Jan 28 '13 at 19:26
  • @AaronLS, it sounds like you should be using the `new Date(year, month, day)` form of the date constructor, and accessing values via the `getUTC*` methods. – zzzzBov Jan 28 '13 at 19:27
  • getUTC methods don't return a date object. One javascript API gives me a string and I have to pass it to another API that requires Date object. I was hoping not to do a bunch of parsing because usually Date APIs handle parsing date strings pretty well and let you work with timezone agnostic dates. I posted my workaround. – AaronLS Jan 28 '13 at 19:45
  • @AaronLS, what does the other API do with the date object? Any reason you can't just pass in a Date object instantiated using GMT or UTC time zones? It sounds to me like the API that you're passing the Date object to is buggy. – zzzzBov Jan 28 '13 at 19:48
  • 1
    Creating it as just UTC from a string would be what I'd like to do, hence why I asked "How do you "specify the correct timezone"?" regarding where you stated "you just never specified the correct time zone.". If I do `new Date('2012-01-01 GMT')` it still applies an offset as it converts it to the user's local date time. – AaronLS Jan 28 '13 at 21:08
  • 9
    @AaronLS, if you're forced to use the `get*` methods and need it to return the correct date/time including the unknown timezone offset, simply add in the unknown timezone offset: `d = new Date('2013-01-08 GMT'); d.setMinutes(d.getMinutes() + d.getTimezoneOffset());` This will normalize the date to the user's locale so that the `.get*` methods return the expected value. The `.getUTC*` methods will then be incorrect, so be careful. – zzzzBov Jul 08 '14 at 23:08
  • "You're getting the right date" - Documentation does not equal correct behavior - anyone dealing with PHP for a substantial amount of time, for example, will tell you this. If you are only handling dates because you don't care about times, and you are getting a different date than what you put in, it's still wrong, no matter how it handles it under the hood. The language should work toward what the user expects. – Dissident Rage Dec 01 '16 at 21:01
  • @DissidentRage, "Documentation does not equal correct behavior" Documentation is meant to *define* the behavior, so in that regard it absolutely is the correct behavior. If you don't like the definition you may discuss it with the implementors. No one says you have to like or approve of the correct behavior. "If you are only handling dates because you don't care about times, and you are getting a different date than what you put in" but you're not getting a different date than what you put in, you're getting a different *representation* of **the same exact date and time**. – zzzzBov Dec 01 '16 at 21:07
  • 1
    There is a difference between defining behavior to provide a reference and using it as an escape when the implementors failed to implement something correctly. And it's *not* the same representation if the data does not line up to expectations. – Dissident Rage Dec 01 '16 at 21:15
  • @DissidentRage, "There is a difference between defining behavior to provide a reference and using it as an escape..." The ECMAScript standard provides a definition of the behavior of `Date`. You may make an argument that the original implementation was poor, but your argument that it is *incorrect* doesn't hold. "...not the same representation if the data does not line up to expectations" when one expects the wrong results, one is wrong, not the results. That all said, I don't understand why you feel that it's worth telling me any of this, I didn't write the spec nor the implementation. – zzzzBov Dec 01 '16 at 21:38
  • 4
    Many of these comments are making a huge assumption which is that were using a date that WE created. What if, like me, you're getting dates from another source, like oracle that uses a dd-mmm-yy format. I also have NO IDEA if they plan to change this format in the future, since their application is old which if handled manually could break my program if they change so I need a universal converter. This assumption of UTC date is just as bad without a mechanism to specify local time zone during the parse. For me the question remains. How do I make sure that during parse the date is not changed – Clarence May 03 '19 at 20:48
  • In my particular case, I didn't care about the time, but converting dates from `xx/xx/xxxx` to literal date string('January 1, 1980') was off by one day. suggestion to append `T00:00:00` to the end of the date string passed to the JS Date function solved my problem. – cloudxix Sep 03 '22 at 18:45
93

To normalize the date and eliminate the unwanted offset (tested here : https://jsfiddle.net/7xp1xL5m/ ):

var doo = new Date("2011-09-24");
console.log(  new Date( doo.getTime() + Math.abs(doo.getTimezoneOffset()*60000) )  );
// Output: Sat Sep 24 2011 00:00:00 GMT-0400 (Eastern Daylight Time)

This also accomplishes the same and credit to @tpartee (tested here : https://jsfiddle.net/7xp1xL5m/1/ ):

var doo = new Date("2011-09-24");
console.log( new Date( doo.getTime() - doo.getTimezoneOffset() * -60000 )  );
AaronLS
  • 37,329
  • 20
  • 143
  • 202
  • This did it for me - I had to work with dates from an API then sort/compare them, so simply adding the timezone offset works best. – chakeda May 04 '16 at 15:56
  • 3
    This worked for me except I had to subtract the timeZoneOffset, not add it – ErikAGriffin Nov 30 '16 at 11:11
  • @ErikAGriffin Are you in a positive time zone, I.E. GMT+0X00 instead of GMT-0X00 ? – AaronLS Dec 01 '16 at 01:45
  • I did something similar: `doo.setMinutes(doo.getMinutes() + doo.getTimezoneOffset())` – Dissident Rage Dec 01 '16 at 21:18
  • @AaronLS yes but the subtraction continued to work as I moved my computer timezone around, both in front of and behind GMT – ErikAGriffin Dec 02 '16 at 08:10
  • @ErikAGriffin Problem with that is if timezone is negative, then it shifts the date by one day, notice day is 23 instead of 24: http://imgur.com/a/L2iiG – AaronLS Dec 02 '16 at 09:48
  • See this answer for another discussion of + vs - of the timezone offset. http://stackoverflow.com/a/16048201/1739675 It seems this method is not reliable in all situations – ErikAGriffin Dec 05 '16 at 11:19
  • @ErikAGriffin Way ahead of you my friend. I already added an update to handle both situations after your first comment. – AaronLS Dec 05 '16 at 12:04
  • 5
    @AaronLS You were on the right track but slightly wrong logic. To compensate for the TZ offset the correct logic is: console.log( new Date( doo.getTime() - doo.getTimezoneOffset() * -60000 ) ); - The offset's sign is important and can't be absoluted away but you also need the inverse sign for correction so we multiply the offset by -60000 for the inverse sign to apply. – tpartee Jan 10 '17 at 23:19
  • @tpart Excellent catch, did some research to do proper tests with both positive and negative timezones and fixed and added your example. Also added jsfiddle tests to confirm. – AaronLS Jan 11 '17 at 00:13
  • @AaronLS Yes I have thoroughly tested this code in production on a global website with QA analysts around the world. Positive and negative offsets are being compensated for correctly and with that code I always get the correct date with a time of 00:00:00 as desired. – tpartee Jan 12 '17 at 07:36
48

I believe that it has to do with time-zone adjustment. The date you've created is in GMT and the default time is midnight, but your timezone is EDT, so it subtracts 4 hours. Try this to verify:

var doo = new Date("2011-09-25 EDT");
FishBasketGordo
  • 22,904
  • 4
  • 58
  • 91
  • 6
    This is the best answer here. +1million for using the built-in timezone localization strings instead of programmatically converting. – blearn Apr 10 '17 at 17:51
  • 2
    This one helps. It works like this: $scope.dat = new Date(datestring + ' EDT'). Note the difference between EDT and EST though: [link](https://stackoverflow.com/questions/26453226/javascript-date-gives-me-edt-but-i-want-est) – Weihui Guo Sep 12 '17 at 18:27
  • I don't know whats happening behind the scenes, but it works perfectly. – the_haystacker Jul 23 '18 at 06:56
  • This I would say is the most simplistic of answers and less code reformatting. – Michael May 26 '19 at 09:34
  • Thanks, I consider the best way to me. – Janderson Constantino Jun 13 '19 at 21:51
  • Yup time-zone adjustment is a key to resolve that issue, I found the below article that explains some "mysterious" things happening with the javascript date https://css-tricks.com/everything-you-need-to-know-about-date-in-javascript – Przemek Nowicki Sep 28 '19 at 08:47
  • Except for those people unlucky enough to live in a time zone that does not have a common three-letter abbreviation, or one that collides with another (e.g. IST, which could be India Standard Time, Irish Standard Time, or Israel Standard Time). It's also implementation dependent; implementations are free not to implement parsing the time zone in this manner at all. – Heretic Monkey Sep 03 '22 at 20:30
  • Dang why dates are so hard in every language... Works for me by using GMT+0 also to avoid confusion and when using EDT it adds +4hrs for me. – Sauer Voussoir Nov 10 '22 at 03:01
  • **EDT** is the time zone used in summer and spring, while **EST** is the time zone used in winter and autumn. – aldwinp35 Jul 01 '23 at 17:10
36

Just want to add that apparently adding a space at the end of the string will use UTC for creation.

new Date("2016-07-06")
> Tue Jul 05 2016 17:00:00 GMT-0700 (Pacific Daylight Time)

new Date("2016-07-06 ")
> Wed Jul 06 2016 00:00:00 GMT-0700 (Pacific Daylight Time)

Edit: This is not a recommended solution, just an alternative answer. Please do not use this approach since it is very unclear what is happening. There are a number of ways someone could refactor this accidentally causing a bug.

Kyle Shrader
  • 912
  • 11
  • 16
  • For the example with the space at the end, console returns "Invalid Date = $2" – Brian Risk Jan 19 '16 at 18:37
  • 2
    works very well! new Date(data.Date+ " ").toLocaleDateString("en-US") – Nakres Oct 04 '18 at 15:06
  • To be fair, this was just an alternative answer, and is not a recommended solution. – Kyle Shrader Oct 05 '18 at 16:21
  • actually this answer is very useful for when you're not sure what the date string looks like, cause it would fix it if formatted as above but won't break anything if written out as 'Wed Jul 20 2022 11:15:24 GMT-0400 (Eastern Daylight Time) ' or any other way – yih613 Jul 20 '22 at 15:15
32

If you want to get hour 0 of some date in the local time zone, pass the individual date parts to the Date constructor.

new Date(2011,08,24); // month value is 0 based, others are 1 based.
lincolnk
  • 11,218
  • 4
  • 40
  • 61
23

if you need a simple solution for this see:

new Date('1993-01-20'.split('-')); 

enter image description here

Marcos Dantas
  • 836
  • 1
  • 11
  • 10
11

Your issue is specifically with time zone. Note part GMT-0400 - that is you're 4 hours behind GMT. If you add 4 hours to the displayed date/time, you'll get exactly midnight 2011/09/24. Use toUTCString() method instead to get GMT string:

var doo = new Date("2011-09-24");
console.log(doo.toUTCString());
Aleks G
  • 56,435
  • 29
  • 168
  • 265
10

This probably is not a good answer, but i just want to share my experience with this issue.

My app is globally use utc date with the format 'YYYY-MM-DD', while the datepicker plugin i use only accept js date, it's hard for me to consider both utc and js. So when i want to pass a 'YYYY-MM-DD' formatted date to my datepicker, i first convert it to 'MM/DD/YYYY' format using moment.js or whatever you like, and the date shows on datepicker is now correct. For your example

var d = new Date('2011-09-24'); // d will be 'Fri Sep 23 2011 20:00:00 GMT-0400 (EDT)' for my lacale
var d1 = new Date('09/24/2011'); // d1 will be 'Sat Sep 24 2011 00:00:00 GMT-0400 (EDT)' for my lacale

Apparently d1 is what i want. Hope this would be helpful for some people.

Jie Zhang
  • 115
  • 1
  • 7
10

You can convert this date to UTC date by

new Date(Date.UTC(Year, Month, Day, Hour, Minute, Second))

And it is always recommended to use UTC (universal time zone) date instead of Date with local time, as by default dates are stored in Database with UTC. So, it is good practice to use and interpret dates in UTC format throughout entire project. For example,

Date.getUTCYear(), getUTCMonth(), getUTCDay(), getUTCHours()

So, using UTC dates solves all the problem related to timezone issues.

Akhil Ramani
  • 391
  • 4
  • 6
8

This through me for a loop, +1 on zzzBov's answer. Here is a full conversion of a date that worked for me using the UTC methods:

//myMeeting.MeetingDate = '2015-01-30T00:00:00'

var myDate = new Date(myMeeting.MeetingDate);
//convert to JavaScript date format
//returns date of 'Thu Jan 29 2015 19:00:00 GMT-0500 (Eastern Standard Time)' <-- One Day Off!

myDate = new Date(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate());
//returns date of 'Fri Jan 30 2015 00:00:00 GMT-0500 (Eastern Standard Time)' <-- Correct Date!
cmartin
  • 2,819
  • 1
  • 26
  • 31
5

Though in the OP's case the timezone is EDT, there's not guarantee the user executing your script will be int he EDT timezone, so hardcoding the offset won't necessarily work. The solution I found splits the date string and uses the separate values in the Date constructor.

var dateString = "2011-09-24";
var dateParts = dateString.split("-");
var date = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);

Note that you have to account for another piece of JS weirdness: the month is zero-based.

Brian Risk
  • 1,244
  • 13
  • 23
5

I encountered this exact problem where my client was on Atlantic Standard Time. The date value the client retrieved was "2018-11-23" and when the code passed it into new Date("2018-11-23") the output for the client was for the previous day. I created a utility function as shown in the snippet that normalized the date, giving the client the expected date.

date.setMinutes(date.getMinutes() + date.getTimezoneOffset());

var normalizeDate = function(date) {
  date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
  return date;
};

var date = new Date("2018-11-23");

document.getElementById("default").textContent = date;
document.getElementById("normalized").textContent = normalizeDate(date);
<h2>Calling new Date("2018-11-23")</h2>
<div>
  <label><b>Default</b> : </label>
  <span id="default"></span>
</div>
<hr>
<div>
  <label><b>Normalized</b> : </label>
  <span id="normalized"></span>
</div>
Gabe Gates
  • 902
  • 1
  • 14
  • 19
4

My solution to parse an ISO date without beeing annoyed by the timezone is to add a "T12:00:00" at the end before parsing it, because when it's noon at Greenwich, well the whole world is on the same day :

function toDate(isoDateString) {
  // isoDateString is a string like "yyyy-MM-dd"
  return new Date(`${isoDateString}T12:00:00`);
}

Before:

> new Date("2020-10-06")
> Date Mon Oct 05 2020 14:00:00 GMT-1000 (heure normale d’Hawaii - Aléoutiennes)

After:

> toDate("2020-10-06")
> Date Tue Oct 06 2020 12:00:00 GMT-1000 (heure normale d’Hawaii - Aléoutiennes)
Xamage
  • 41
  • 2
4

It means 2011-09-24 00:00:00 GMT, and since you're at GMT -4, it will be 20:00 the previous day.

Personally, I get 2011-09-24 02:00:00, because I'm living at GMT +2.

pimvdb
  • 151,816
  • 78
  • 307
  • 352
3

As most answers are hacky, allow me to propose my very simple hack that worked for me: Set the script's timezone to UTC

process.env.TZ = 'UTC' // this has to be run before any use of dates

With this change, any timezone modifications are neutralized, so as long as you don't need the runner's actual timezone, this is probably the easiest fix.

Giszmo
  • 1,944
  • 2
  • 20
  • 47
  • 1
    Note that the `process` object is specific to Node.js and is not included as part of the ECMAScript specification, so this will only work in Node.js, and not in the browser. – Hoppeduppeanut Apr 19 '21 at 23:33
  • 1
    This is the best answer regarding nodejs – kursus May 03 '22 at 12:57
2

if you're just looking to make sure the individual parts of the date stay the same for display purposes, *this appears to work, even when I change my timezone:

var doo = new Date("2011-09-24 00:00:00")

just add the zeros in there.

In my code I do this:

let dateForDisplayToUser = 
  new Date( `${YYYYMMDDdateStringSeparatedByHyphensFromAPI} 00:00:00` )
  .toLocaleDateString( 
    'en-GB', 
    { day: 'numeric', month: 'short', year: 'numeric' }
  )

And I switch around my timezone on my computer and the date stays the same as the yyyy-mm-dd date string I get from the API.

But am I missing something/is this a bad idea ?

*at least in chrome. This Doesn't work in Safari ! as of this writing

2

You can use moment library to format the date. https://momentjs.com/

let format1 = "YYYY-MM-DD"
let date = new Date();

console.log(moment(date).format(format1))

EDIT

The moment is now deprecated, you can use date-fns format method for formatting a date.

import { format } from 'date-fns'
format(new Date(), "yyyy-MM-dd")
Sashini Hettiarachchi
  • 1,630
  • 2
  • 10
  • 21
2

// When the time zone offset is absent, date-only formats such as '2011-09-24' 
// are interpreted as UTC time, however the date object will display the date 
// relative to your machine's local time zone, thus producing a one-day-off output.
const date = new Date('2011-09-24');
console.log(date); // Fri Sep 23 2011 17:00:00 GMT-0700 (PDT)
console.log(date.toLocaleDateString('en-US')); // "9/23/2011"
            
// To ensure the date object displays consistently with your input, simply set
// the timeZone parameter to 'UTC' in your options argument.  
console.log(date.toLocaleDateString('en-US', { timeZone: 'UTC' })); // "9/24/2011"
de3z1e
  • 411
  • 4
  • 8
1

The best way to handle this without using more conversion methods,

 var mydate='2016,3,3';
 var utcDate = Date.parse(mydate);
 console.log(" You're getting back are 20.  20h + 4h = 24h :: "+utcDate);

Now just add GMT in your date or you can append it.

 var  mydateNew='2016,3,3'+ 'GMT';
 var utcDateNew = Date.parse(mydateNew);
 console.log("the right time that you want:"+utcDateNew)

Live: https://jsfiddle.net/gajender/2kop9vrk/1/

Gajender Singh
  • 1,285
  • 14
  • 13
1

I faced some issue like this. But my issue was the off set while getting date from database.

this is stroed in the database and it is in the UTC format.

2019-03-29 19:00:00.0000000 +00:00

So when i get from database and check date it is adding offset with it and send back to javascript.

enter image description here

It is adding +05:00 because this is my server timezone. My client is on different time zone +07:00.

2019-03-28T19:00:00+05:00 // this is what i get in javascript.

So here is my solution what i do with this issue.

var dates = price.deliveryDate.split(/-|T|:/);
var expDate = new Date(dates[0], dates[1] - 1, dates[2], dates[3], dates[4]);
var expirationDate = new Date(expDate);

So when date come from the server and have server offset so i split date and remove server offset and then convert to date. It resolves my issue.

Uxmaan Ali
  • 339
  • 1
  • 15
1

Trying to add my 2 cents to this thread (elaborating on @paul-wintz answer).

Seems to me that when Date constructor receives a string that matches first part of ISO 8601 format (date part) it does a precise date conversion in UTC time zone with 0 time. When that date is converted to local time a date shift may occur if midnight UTC is an earlier date in local time zone.

new Date('2020-05-07')
Wed May 06 2020 20:00:00 GMT-0400 (Eastern Daylight Time)

If the date string is in any other "looser" format (uses "/" or date/month is not padded with zero) it creates the date in local time zone, thus no date shifting issue.

new Date('2020/05/07')
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
new Date('2020-5-07')
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
new Date('2020-5-7')
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
new Date('2020-05-7')
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)

So then one quick fix, as mentioned above, is to replace "-" with "/" in your ISO formatted Date only string.

new Date('2020-05-07'.replace('-','/'))
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
Florin D
  • 1,610
  • 18
  • 17
1

This solved my problem (thanks to @Sebastiao answer)

var date = new Date();
//"Thu Jun 10 2021 18:46:00 GMT+0200 (Eastern European Standard Time)"

date.toString().split(/\+|-/)[0] ;  // .split(/\+|-/) is a regex for matching + or -
//"Thu Jun 10 2021 18:46:00 GMT"

var date_string_as_Y_M_D = (new Date(date)).toISOString().split('T')[0];
//2021-06-10
Omar
  • 607
  • 3
  • 8
  • 18
1

I just wanted to give my 2 cents on this, as this post was very helpful to figure out the issue. I don't think I've seen this solution mentioned, correct me if I'm wrong.

As it has been mentioned numerous times already here, the problem comes mainly from summer/winter time. I noticed that in January, the GMT was +1. If the time is not set, it will always be 00.00.00 (midnight), which results in going on the 23rd hour of the previous day.

If you have a dynamic date and don't care about the hour, you can set the hour using the setHours() method before using it with toISOString().

syntax: setHours(hoursValue, minutesValue, secondsValue, msValue)

Which means that:

dynamicDate.setHours(12, 0, 0, 0)
dynamicDate.toISOString()

should hopefully work for you as even if the date is one hour ahead/behind it will still be the same day now that we're setting the hour to be noon.

More about setHours() on MDN.

0

You are using the ISO date string format which, according to this page, causes the date to be constructed using the UTC timezone:

Note: parsing of date strings with the Date constructor (and Date.parse, they are equivalent) is strongly discouraged due to browser differences and inconsistencies. Support for RFC 2822 format strings is by convention only. Support for ISO 8601 formats differs in that date-only strings (e.g. "1970-01-01") are treated as UTC, not local.

If you format the text differently, such as "Jan 01 1970", then (at least on my machine) it uses your local timezone.

Paul Wintz
  • 2,542
  • 1
  • 19
  • 33
0

Storing yyyy-mm-dd in MySql Date format you must do the following:

const newDate = new Date( yourDate.getTime() + Math.abs(yourDate.getTimezoneOffset()*60000) );
console.log(newDate.toJSON().slice(0, 10)); // yyyy-mm-dd
rick
  • 479
  • 5
  • 14
-1

Using moment you can keep Offset while converting toISOString

let date = moment("2022-03-15").toISOString();
// WRONG OUTPUT 2022-03-14T18:30:00.000Z

let date = moment("2022-03-15").toISOString(true);
// CORRECT OUTPUT 2022-03-15T00:00:00.000+05:30
dev99
  • 143
  • 3
  • 7
-1

Following Code worked for me. First I converted to date and time string to localeDateString then apply the split function on the returned string.

const dateString = "Thu Dec 29 2022 00:00:00 GMT+0500 (Pakistan Standard Time)";
const date = new Date(dateString).toLocaleDateString().split("/");
const year = new Date(dateString).getFullYear();
const month = new Date(dateString).getMonth();

console.log(new Date(`${date[2]}-${date[0]}-${date[1]}`));
// 2022-12-29T00:00:00.000Z


// Due to timezone issue, the date is one day off.
console.log(new Date("2011-09-24"));
// => 2011-09-24T00:00:00.000Z-CORRECT DATE.

console.log(new Date("2011/09/24"));
// => 2011-09-23T19:00:00.000Z -ONE DAY OFF AS BEFORE.
-1

You can also use getUTCDate() to get the correct date.

 const date = new Date('Apr 04 2023') // Any Format
 // Tue Apr 04 2023 00:00:00 GMT-0700 (Pacific Daylight Time)
 date.getUTCDate() // 5
-1

Tried multiple solutions. My suggestion would be convert the existing date to string

date.toDateString()

accept string from backend and then Convert.ToDateTime(date) from backend

In this way it worked well for me in all scenarios, Please try this.

if your want to convert from ui side itself

date = this.datepipe.transform(date,"yyyy-MM-ddT00:00:00")
turtle
  • 1
  • 1
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 08 '23 at 08:27
-1

This is just because, Javascript by default give result in UTC time. So, If you don't give time zone when initializing date it will give UTC. And that is happening in your case.

Asad Mehmood
  • 341
  • 2
  • 12
-2

I had data coming from an sql server and did not want to modify it, but rather the display of it in React. I created a function to add the hours to the date displayed by the picker, rather than change the date format stored on my server.

function addHours(date) {
  //this function add 19 hours to match CST with the UTC Zulu time
  var result = new Date(date);
  result.setHours(result.getHours() + 19);
  return result;
}

and called it like this, here:

<input name='ToDt' type='date' id='toInput' value={addHours(new Date((systemData.ToDt))).toLocaleDateString('en-CA')} onChange={setInput} />

-3

The following worked for me -

    var doo = new Date("2011-09-24").format("m/d/yyyy");
Venu
  • 1