1

An example would be 9am CST (central standard time), or 6am CET (Central European Time).

Using any new Date() calls will always give me a date in my local time zone (BST, or GMT+1).

I think I need to first create the date in the desired timezone, no?

function convertToUTC(date, tzString) { // some code? } let resp = convertToUTC("2022-07-12 09:00:00", "America/Chicago"); console.log(resp) should be "2022-07-12T14:00:00Z" 
5
  • 1
    developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Jul 12, 2022 at 14:25
  • "considering daylight savings" This is more complicated than it first appears to be. Commented Jul 12, 2022 at 15:18
  • updates made for @Yogi Commented Jul 12, 2022 at 15:24
  • There are some physical locations that actually fall or appear to fall into multiple time zones and they vary depending on the time of year. Navajo Nation and Australia come to mind along with some locations that have 30 minute offsets. Commented Jul 12, 2022 at 15:31
  • The OP also might have a look into ... "Create a date object in a specific time zone and convert it to UTC in JavaScript" ... where the implemented approach is library agnostic, utilizing the Intl.DateTimeFormat Internationalization API and Date.prototype.getTimezoneOffset only. Commented Jul 13, 2022 at 9:36

1 Answer 1

2

I would definitely suggest using a specialized date/time library for this purpose.

Timezone conversion in vanilla JavaScript is tricky to say the least (especially converting from a timezone to UTC)

However this is quite straightforward in luxon:

I'm using the DateTime.fromSQL() function here since it matches the input timestamp format.

const { DateTime } = luxon; function convertToUTC(date, tzString) { const dt = DateTime.fromSQL(date, { zone: tzString }); return dt.setZone('UTC'); } console.log(convertToUTC("2022-07-12 09:00:00", "America/Chicago")); console.log(convertToUTC("2022-07-12 09:00:00", "America/Los_Angeles")); console.log(convertToUTC("2022-07-12 09:00:00", "Europe/London")); console.log(convertToUTC("2022-07-12 09:00:00", "Etc/GMT+12")); console.log(convertToUTC("2022-07-12 09:00:00", "Pacific/Kiritimati"));
.as-console-wrapper { max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.3.1/luxon.min.js" integrity="sha512-Nw0Abk+Ywwk5FzYTxtB70/xJRiCI0S2ORbXI3VBlFpKJ44LM6cW2WxIIolyKEOxOuMI90GIfXdlZRJepu7cczA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

We can do this in vanilla JavaScript, it's just a little awkward.

We're essentially searching for the UTC date that will, when converted to the target timezone, equal the target date.

I'm using the 'sv' language (BCP47 language tag) since it will give us ISO timestamps.

function convertToUTC(date, tzString) { const dt = Date.parse(toIso(date) + 'Z'); // Go from UTC offset +15 hours to UTC offset -15 hours. This should cover existing / future zones. for(let offsetMinutes = -900; offsetMinutes <= 900; offsetMinutes += 15) { const utc = new Date(dt + offsetMinutes * 60000); if (toIso(date) === toIso(utc, tzString)) { return toIso(utc, 'UTC') + 'Z'; } } } function toIso(date, timeZone) { return new Date(date).toLocaleString('sv', { timeZone }).replace(' ', 'T'); } console.log(convertToUTC("2022-07-12 09:00:00", "America/Chicago")); console.log(convertToUTC("2022-07-12 09:00:00", "America/Los_Angeles")); console.log(convertToUTC("2022-07-12 09:00:00", "Europe/London")); console.log(convertToUTC("2022-07-12 09:00:00", "Etc/GMT+12")); console.log(convertToUTC("2022-07-12 09:00:00", "Pacific/Kiritimati"));
.as-console-wrapper { max-height: 100% !important; }

Sign up to request clarification or add additional context in comments.

3 Comments

Nice, good answer. I'm liking Luxon so far. As I was trying to solution this myself I was thinking "do I need to just keep trying to find the UTC date that matches the timezone, that can't be"... but it seems to be the case.
It's certainly not simple to do with JavaScript dates! Hopefully the new Temporal object will help things along: tc39.es/proposal-temporal/docs/index.html.
"SV" isn't a locale, it's a language (or more precisely, a BCP47 language tag).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.