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"
blomster
  • 768
  • 2
  • 10
  • 27
  • 1
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat – aca Jul 12 '22 at 14:25
  • 2
    The question is very unclear. Please provide some expected input and output values and explain how the code is to be used. – Yogi Jul 12 '22 at 15:06
  • "considering daylight savings" This is more complicated than it first appears to be. – Mark Schultheiss Jul 12 '22 at 15:18
  • updates made for @Yogi – blomster Jul 12 '22 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. – Mark Schultheiss Jul 12 '22 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"_](https://stackoverflow.com/questions/72149681/create-a-date-object-in-a-specific-time-zone-and-convert-it-to-utc-in-javascript/72155524#72155524) ... where the implemented approach is library agnostic, utilizing the [`Intl.DateTimeFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) Internationalization API and `Date.prototype.getTimezoneOffset` only. – Peter Seliger Jul 13 '22 at 09:36

1 Answers1

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; }
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40
  • 1
    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. – blomster Jul 13 '22 at 08:08
  • It's certainly not simple to do with JavaScript dates! Hopefully the new Temporal object will help things along: https://tc39.es/proposal-temporal/docs/index.html. – Terry Lennox Jul 13 '22 at 08:22
  • 1
    "SV" isn't a locale, it's a language (or more precisely, a BCP47 language tag). – RobG Jul 13 '22 at 13:05