0

I have developed a page where users can filter records based on their selections in the filters. The datetime picker allows users to select a specific datetime and a dropdown allows the user to select the time zone in which they want that selected date to be converted to UTC.

For example, on my computer the time zone set is Asia/Karachi which has an offset of +5 UTC. But I want to select Europe/Prague from the dropdown and 09/14/2021 3.30pm as the date time. The time should be converted to 1.20 PM as Europe/Prague has a time offset of +2 from UTC using below code.

var ddate = new Date(date.toLocaleString('en-US', {
    timeZone: 'Europe/Prague'
  }));

However, this yields 12.30 PM as the time. Apparently it is converting from Asia/Karachi(my computer time zone) to Europe/Prague. But I want the selected datetime to be converted to UTC based on the time zone the user selects from the dropdown of available time zones. Is there any possible solution? I have tried researching and coding a lot but haven't found any yet.

Azher Aleem
  • 738
  • 6
  • 15
  • 2
    That code takes a `date`, converting it to a string, in `en-US` format and `'Europe/Prague'` time zone. Then it takes that string and passes it to the `Date` constructor, where the result will be implementation-specific (see [Why does Date.parse give incorrect results?](https://stackoverflow.com/questions/2587345/why-does-date-parse-give-incorrect-results)). – Heretic Monkey Sep 14 '21 at 15:25

2 Answers2

0

Have you tried moment & moment-timezone? maybe something like this:

import moment from "moment";
const myDate = "09/14/2021 3:30 PM";
const myTimeZone = "Europe/Prague";

let convertedTime = moment.tz(myDate, time_zone).format();

and you can set your format to be ("HH:mm A")

username
  • 33
  • 5
  • That will yield me 12:38 PM but it should be 1:38 PM since, Prague is +2 – Azher Aleem Sep 14 '21 at 14:40
  • 1
    What if you first convert the date/time to UTC from your local timezone then try converting it from UTC to the selected timezone ? It's not the best practice, but it might do it! – username Sep 14 '21 at 14:51
  • @username—that doesn't work, the timestamp needs to be parsed in the appropriate timezone. – RobG Sep 14 '21 at 23:17
0

If you want a date constructor for specific timezones make use of new Date('YYYY-MM-DDTHH:NN:SS.sss±HH:NN').

What you describe and want, is what Date already does if you generate a Date using new Date('YYYY-MM-DDTHH:NN:SS.sss±HH:NN'). You simply have to use it in this format.

±HH:NN is timezone information from your timezone-dropdown. It can either start with a + or a -. (Take a look at the 3rd snippet)

Other formats as the ones i mentioned, are invalid if passed to the Date constructor and you may get unexpected results.

The dropdown (the one about the timezone) requires the information of +hrs:mins and -hrs:mins respective to the timezone selected.

The following describes the Date constructor.

Don't pass a formated string like this to new Date() - it's invalid.

If you use new Date() you either have to pass a time value in milliseconds, a date only or an ISO Timestamp.

  • new Date(date.valueOf()) results in a copy
  • new Date(date.toISOString()) results in a copy
  • new Date(date.toJSON()) results in a copy
  • new Date(date.toDateString()) results in a copy of the date only => no hour GMT +0 on the current day.

All examples above (except the last one) are a copy of the original date.

For more information on the arguments supported by the Date-constructor take a look at Date.parse()#Date Time String Format

There is no need to change anything. If it's midnight at Asia/Karachi, it will be 9pm (21:00) in Europe/Prague.

As you can see on this example, use GMT+0 or any other accepted Time-Zone String.

Examples of different arguments

1

const date = new Date("2021-02-14T00:00:05.000+00:00"); // 5 seconds after midnight on February 14th, 2021 GMT+0

["GMT+0", "UTC", "America/New_York", "Europe/Madrid", "Europe/Prague", "Europe/Moscow", "Asia/Karachi", "Asia/Tokyo", "PRC"].forEach(timeZone => {
  console.log(timeZone, date.toLocaleString('en-US', { timeZone }))
});

2

const date = new Date("2021-09-14");
["GMT+0", "UTC", "America/New_York", "Europe/Madrid", "Europe/Prague", "Europe/Moscow", "Asia/Karachi", "Asia/Tokyo", "PRC"].forEach(timeZone => {
  console.log(timeZone, date.toLocaleString('en-US', { timeZone }))
});

3

// 16:00 at timezone +9 is 7 am at gmt
const date = new Date("2021-09-14T16:00:00.000+09:00");
["GMT+0", "UTC", "America/New_York", "Europe/Madrid", "Europe/Prague", "Europe/Moscow", "Asia/Karachi", "Asia/Tokyo", "PRC"].forEach(timeZone => {
  console.log(timeZone, date.toLocaleString('en-US', { timeZone }))
});
Christopher
  • 3,124
  • 2
  • 12
  • 29
  • The main goal is to select a time zone Europe Prague and a date from the picker, If I select 3.30 PM it should convert the time to UTC i.e. 1.30 PM since. Prague is +2 GMT. However, by doing the above since, I will get 12.30 as it will convert the time selected by me as my computer's Tim zone is set to Asia/karachi and the difference between prague and karachi time zones is 3 hours. – Azher Aleem Sep 14 '21 at 18:09
  • I updated my answer. See example #3 and the explaination in the beginning. – Christopher Sep 14 '21 at 20:09
  • GMT+0 is an offset, not a timezone. The OP wants to parse, not format, timestamps for a particular timezone, something like `new Date(timestamp, timezone)` which, of course, is not supported. The new [*Temporal* object](https://tc39.es/proposal-temporal/docs/cookbook.html?futuredate=2021-09-16#time-zone-conversion) will allow parsing in a particular IANA location, e.g. `Temporal.ZonedDateTime.from('2020-01-09T00:00[Europe/Berlin]')`. – RobG Sep 14 '21 at 20:47
  • `GMT+0` is also an accepted alias for UTC at this point, but yeah you are right. Thanks for the hint at `Temporal.ZonedDateTime` it's currently just experimental, but seems a nice addition instead of parsing it with the offsets as before. – Christopher Sep 14 '21 at 20:59