0

I live in the UK. If I create a date object for 1st June, I would have expected .getUTCDate() to return the "correct" day of the month as 1, but instead it returns 31 and .getDate(), which I thought was meant to return the locale date returns 1.

new Date(2020,5,1).getUTCDate() // 31
new Date(2020,5,1).getDate(); // 1

Why is this? Is it because new Date(2020,5,1) is already converted to local time or something? I thought dates were stored universally, and it is only when the date is printed out that the locale rules are applied? I've read all the MDN docs and still don't understand, I would really appreciate if someone can walk through the steps of what happens for the above to return 31 and 1.

Max888
  • 3,089
  • 24
  • 55
  • 1
    you kinda answered your own questions. by default the date goes by your local computer unless you specify utc. see here https://www.google.com/search?q=is+javascript+date+using+local+timezone&rlz=1C1GCEU_enUS821US821&oq=is+javascript+date+using+local+timezone&aqs=chrome..69i57j33.13311j0j7&sourceid=chrome&ie=UTF-8 – full-stack Aug 13 '20 at 18:30
  • @full-stack But if "The internal representation of a Date object is a single number, representing the number of milliseconds that have elapsed since 1970-01-01 00:00:00 UTC", surely `new Date(2020,5,1)` should just be 1st Jun 2020 UTC, and `new Date(2020,5,1).getUTCDate()` should be 1. I don't understand at what point BST is entering the mix and causing it to be 31 instead. – Max888 Aug 13 '20 at 18:37
  • see here: "When various functions of the Date object are used, the computer's local time zone is applied to the internal representation" https://stackoverflow.com/questions/15141762/how-to-initialize-a-javascript-date-to-a-particular-time-zone#:~:text=There%20is%20no%20time%20zone,applied%20to%20the%20internal%20representation. – full-stack Aug 13 '20 at 18:39
  • Seems `new Date(2020,5,1)` will store the date as UTC as expected, but when you call either `.getUTCDate()` or `.getDate()`, the date is then treated as if it is actually stored as local time and is first converted from the the local time (which is 1 hour ahead in BST) back to UTC (so go back 1 hour) and then `.getUTCDate` will return this date, and `.getDate` will convert "back to local" so add an hour one, taking us back to the original 1st Jun 2020 as expected. Is this correct? – Max888 Aug 13 '20 at 19:04

1 Answers1

1

A brief explanation of how ECMAScript Date constructor works.

Single string values are parsed and converted to Dates in weird and wonderful ways that are mostly implementation dependent, see below. So all of the following ignores parsing and assumes the Date constructor is called with at least two arguments, year and month. In this case, string values are converted to number as if by Number(value).

All the non–UTC methods work in local time, i.e. based on the host system date, time and timezone offset settings. When creating a Date object using the constructor and values for year, month, day, etc. then any missing values are treated as 0 except for the day, which defaults to 1.

So

new Date(2020, 5, 1)

creates a date based on the host (local) settings for date, time and timezone offset for that date and time, respecting historical changes like daylight saving and other adjustments (common before 1900) as if by:

new Date(2020, 5, 1, 0, 0, 0, 0); // Local 1 Jun 2020 00:00:00.000

So getUTCDate will return 31 (i.e. 31 May) for systems with a timezone offset that is less than zero and 1 (i.e. 1 Jun) for any with an offset of zero or greater. The largest positive offset in common use is +14 and the smallest is -10.

If you want to create a Date based on UTC values, then use the Date.UTC method, whcih returns a number, the time value, so you have to pass it to the Date constructor to create a Date object:

new Date(Date.UTC(2020, 5, 1)).getUTCDate(); // 1 regardless of host settings

Parsing strings: new Date(string) and Date.parse(string)

This where the Date object crashes and burns. While the constructor mostly uses local, it can also use UTC even where UTC is not specified. Parsing of strings is almost entirely implementation dependent except for the 3 formats supported by ECMA-262. Even the supported formats are not parsed consistently across implementations so the general advice is do not use the built–in parser. See Why does Date.parse give incorrect results?

RobG
  • 142,382
  • 31
  • 172
  • 209