1

I'm trying to find the best way in JavaScript to get the day of the week of a particular date in any time zone, given only a date string.

Specifically, if I have a date string like:

2022-01-29

And I create a new Date object in JS with that string, and then call the getDay method on the Date object, because I'm in the "America/New_York" time zone, I actually get the day of the week for the day before that date, not the day of the week of the date itself.

This can be easily demonstrated for anyone in a time zone that is minus-UTC time (e.g., America, Canada, etc.) by running:

new Date('2022-01-29').getDay()

which should return 6 for Saturday, but because of the time zone shift, I get 5 for Friday.

I found "https://stackoverflow.com/a/39209842/128421", which recommended using the getTimezoneOffset method like:

var date = new Date('2016-08-25T00:00:00')
var userTimezoneOffset = date.getTimezoneOffset() * 60000;
new Date(date.getTime() - userTimezoneOffset);

That does seem to work, but a couple of points:

  1. The SO post recommends using - userTimezoneOffset at the end, but it only works for me with + userTimezoneOffset. Why?
  2. Comments on the post said that it doesn't work for Daylight Saving Time or in all time zones, something I'm not sure how to easily confirm. In my initial testing, it seems to work fine for DST, but maybe there's something I'm missing, and either way, I'm not sure how to test it for other time zones.

What is the best way to get the day of the week in JavaScript when all I have is a date string?

HartleySan
  • 7,404
  • 14
  • 66
  • 119
  • _"what is the best way..."_ asks for an opinion, and that's [off-topic](https://stackoverflow.com/help/on-topic) – Andreas Jan 29 '22 at 17:19
  • Dates are hard (as you already know), hence there are specialized libraries. Use one of them. – Andreas Jan 29 '22 at 17:19
  • @Andreas, how about: "What's the correct way..."? – HartleySan Jan 29 '22 at 17:20
  • Also, @Andreas, there are times when I'd prefer not to use a library for something seemingly so simple. If it turns out that it's that difficult, then I will use a library, yes. – HartleySan Jan 29 '22 at 17:21
  • Who defines what _"correct"_ is? -> Opinion. You haven't even defined what the actual requirement is. What "day" do you want to get (in which timezone)? What's the timestamp (local, UTC, ...)? -> [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask) – Andreas Jan 29 '22 at 17:22
  • 2
    @Andreas, not to be rude, but this attitude is exactly why many users complain about SO. One example: https://meta.stackoverflow.com/questions/262791/the-rudeness-on-stack-overflow-is-too-damn-high. Should I rephrase my question as "What's one way to..."? I mean, really, please tell me exactly how I should write my question and post to fit within your guidelines? And for what it's worth, Carsten Massmann gave a perfectly short, simple and "correct" answer, which I already marked as the correct answer. – HartleySan Jan 29 '22 at 17:30
  • [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask) – Andreas Jan 29 '22 at 17:48
  • 1
    @Andreas, just went through that entire page, and my question seems to check all the boxes. I still don't see the problem. – HartleySan Jan 29 '22 at 17:54

3 Answers3

7

Use

new Date('2022-01-29').getUTCDay()

new Date('2022-01-29') will create a Date object with the UTC (Greenwhich) date "2022-01-29" and time "00:00h". When getting a weekday with .getDay() your browser would calculate it for your local timezone. By using .getUTCDay() instead you get the weekday for the UTC timezone.

Interesting point made by @RayHatfield

console.log("UTC-time:", new Date("2022-01-29").getUTCHours()) // 0
console.log("UTC-time:", new Date("2022-01-29Z00:00:00").getUTCHours()) // 0 ("Z" is for "ZULU" -> UTC)
console.log("UTC-time:", new Date("2022-01-29T00:00:00Z").getUTCHours()) // 0 (ISO 8601 date string -> UTC)
console.log("UTC-time:", new Date("2022-01-29T00:00:00").getUTCHours()) // UTC time (h) for your local midnight

See https://en.m.wikipedia.org/wiki/ISO_8601 for details on date strings.

Carsten Massmann
  • 26,510
  • 2
  • 22
  • 43
  • Also, I see that there is an entire set of `UTC` methods for all of the regular (local-time) methods as well. Super helpful. Thanks a lot! – HartleySan Jan 29 '22 at 17:27
  • 4
    Additional info on this: Usually when you construct a Date it gets instantiated in the local timezone, but date-only ISO 8601 strings (e.g. "2022-01-29") are treated as UTC, not local. If you append a timestamp ("2022-01-29T00:00:00") you'll get a local date and getDay will return what you expect. (This is not confusing at all.) – ray Jan 29 '22 at 17:29
  • That's very handy, ray hatfield. Thanks for providing that additional info. – HartleySan Jan 29 '22 at 17:31
  • The second example is malformed, the result is NaN. – RobG Jan 29 '22 at 21:52
  • @RobG: which browser were you using? It works on my Chrome and Edge browsers. – Carsten Massmann Jan 29 '22 at 22:18
  • @CarstenMassmann—Safari. In "2022-01-29Z00:00:00" the Z has replaced the T, it should be at the end. So the string is malformed and parsing is implementation dependent (hence different results). :-) – RobG Jan 29 '22 at 22:25
2

If you want to get the weekday name of any date in any timezone, you can use toLocaleString with suitable options.

Because the built–in parser parses '2022-01-29' as UTC, the timezone needs to be set to UTC. If the day name for some other timezone is required, just insert the appropriate IANA representative location.

// Saturday
console.log(new Date('2022-01-29').toLocaleString('en',{
  weekday: 'long',
  timeZone: 'UTC'
}));

That way you're not trying to manually adjust the date.

The getTimezoneOffset method in the OP works too, even where the offset has changed such as for daylight saving or historic changes, but can be a bit simpler:

let d = new Date('2022-01-29');
d.setMinutes(d.getMinutes() - d.getTimezoneOffset());

console.log(d.getDay()); // 6
console.log(d.toLocaleString('en',{weekday:'long'})); // Saturday
RobG
  • 142,382
  • 31
  • 172
  • 209
-2
let weekday = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][new Date().getDay()]
  • Lasha, thanks for the response, but please read my original post again. I'm asking how to get the day of the week when I have only a date string as the input. For example: `new Date('2022-01-29').getDay()` – HartleySan Jan 29 '22 at 17:16
  • Ah, use .toLocaleDateString() method – Lasha Markhvaidze Jan 29 '22 at 17:18
  • It helps more if you supply an explanation why this is the preferred solution and explain how it works. We want to educate, not just provide code. – the Tin Man Feb 07 '22 at 05:15