1

i want to convert selected time into timezone saved in user profile using moment-timezone library

my local system timezone is PKT(pakistan) and user has saved timezone in his Profile is AEST(australian/sydney). so when user select time i just want that time in userTimezone and send in API. e.g

const time  =  "07:00"
const date = "06/13/2023"
const timezone = "Australian/Sydney"
moment(`${date} ${time}`).tz(timezone).format() // 2023-06-20T12:00:00+10:00

converted time should be 7Am AESt but library has convert it into 12pm. if i change moment default timezone into user profile timezone then still i dont get correct output

e.g

const time  =  "07:00"
const date = "06/13/2023"
const timezone = "Australian/Sydney"
 moment.tz.setDefault(timezone)

 moment(`${date} ${time}`).tz(timezone).format() //2023-06-20T12:00:00+10:00
 moment(`${date} ${time}`).format() //2023-06-20T12:00:00+10:00
moment.tz(`${date} ${time}`, timezone).format() // 2023-06-20T17:00:00+10:00

you can see none of the output is what i am trying to acheive. it would be greate if you let me know other library if moment does not support this.

Ouroborus
  • 16,237
  • 4
  • 39
  • 62
Bilal Butt
  • 1,202
  • 3
  • 12
  • 15

3 Answers3

0

// use the following npm package, "luxon"
// https://moment.github.io/luxon/api-docs/index.html

const { DateTime } = require("luxon");

const yourInputTime = "13:45:21";
const yourDateInput = "2023-06-25";
// these inputs are in your timezone

// now you want to convert these to let's day Singapore timezone
// you can find the whole list of timezone from the following link
/* https://stackoverflow.com/questions/38399465/how-to-get-list-of-all-timezones-in-javascript/54500197#54500197 */

// first construct an ISO string
const yourInputISO = `${yourDateInput}T${yourInputTime}`;
const convertedISO = DateTime.fromISO(yourInputISO).setZone("Asia/Singapore").toISO(); // 2023-06-25T15:45:21.000+08:00

const yourDesiredTime = convertedISO.split("T")[1].split(".")[0] // 15:45:21
DanteDX
  • 1,059
  • 7
  • 12
  • thanks for your reply. But if you see i want to keep time same just want to change timezone. lets say if i select 9pm Pakistan time, i want to convert it to 9pm Singapore time, time should remain same like in my example 9pm just timezone change. I want to acheive this – Bilal Butt Jun 13 '23 at 19:54
  • So there is no time calculation? – DanteDX Jun 13 '23 at 20:00
  • yes, because we want to save time in timezone that is saved in user profile. if i live in pakistan but timezone is saved in my profile is Singapore i want to save time in singapore timezone. I hope i have clear my question – Bilal Butt Jun 13 '23 at 21:26
  • I don't understand the process. If you are in pakistan, select 8am, your user profile is in Singapore. So you want to save which data? time is unchanged? so you just want to update timezone ? – DanteDX Jun 14 '23 at 05:38
  • yes time should remain unchanged. if i select 8am it should save 8am singpapore time not 8am pakistan time. – Bilal Butt Jun 14 '23 at 10:26
  • then why you just simply fetch the timezone from your profile? I don't understand the task you are trying to accomplish here. – DanteDX Jun 14 '23 at 10:30
  • i can get timezone from profile, but it is just a timezone name like `asia/karachi` . i am working on a system where user can create events like meetup.com. and when a user create an event and select a event time i want to save that time based on timezone saved in user profile. no matter where user lives, time should be saved based on timezone saved in user Profile. Hope i am able to clear my issue – Bilal Butt Jun 14 '23 at 13:14
  • Okay. When you are taking time input, is it in ISOString? What is the format your input? – DanteDX Jun 14 '23 at 18:00
  • it is just a string e.g `08:00 am` and then i am trying to get time in timezone like this `moment(`${date} ${time}`).tz(timezone || moment.tz.guess()).format()` – Bilal Butt Jun 14 '23 at 19:11
  • when you take time input, try to take it as ISOString, convert it anyway – DanteDX Jun 14 '23 at 19:27
  • didn't work, i selected `6:30 am` time and tried to convert time like this `moment('06:30am', "hh:mm").toISOString()` and return the following `2023-06-15T01:30:00.000Z` and if i try without ISO string i get following output `moment(`${date} ${time}`).tz(timezone).format()` `023-06-22T11:30:00+10:00` – Bilal Butt Jun 14 '23 at 19:58
0

Start by reading the supported values as part of the Intl Web/JS APi and checking what's available => https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/supportedValuesOf . Anything that's returned in the list you can use in your code/app and browser - but may not work in other clients and browsers.

Unless you dig deep into the topic of time I wouldn't try to convert time that a user has entered from a new location selected in their profile - this could be complicated. Better to let the user pick a location and let the location set the time then save that. Calculation back and off of the time? No need - just use Int API to read from.

That said have a try at my code using no external libraries:

  1. User logs in and is based in Pakistan or wherever
  2. User then changes the timezone to Singapore or somewhere else - this is done in this section of code let userSelectedCountry = 'Asia/Singapore' and call our function by using the Date and RegEx APIs to achieve what we need and pull out the correct time for selected (available timezone in our array!) timezone

To use it follow step 1 and 2 in the code comments.

    const event = new Date();
    //list of locales - NOT exhaustive
    const localeCodes = ['el', 'en-au', 'en-ca', 'en-gb', 'en-us', 'es-es', 'es-mx','it-it']
    //list of timezones - NOT exhaustive
    const timeZonesL =   ["Africa/Abidjan"
          , "Asia/Aden"
          , "Asia/Almaty"
          , "Asia/Amman"
          , "Asia/Anadyr"
          , "Asia/Aqtau"
          , "Asia/Aqtobe"
          , "Asia/Ashgabat"
          , "Asia/Ashkhabad"
          , "Asia/Atyrau"
          , "Asia/Baghdad"
          , "Asia/Bahrain"
          , "Asia/Baku"
          , "Asia/Bangkok"
          , "Asia/Barnaul"
          , "Asia/Beirut"
          , "Asia/Bishkek"
          , "Asia/Brunei"
          , "Asia/Calcutta"
          , "Asia/Chita"
          , "Asia/Choibalsan"
          , "Asia/Chongqing"
          , "Asia/Chungking"
          , "Asia/Colombo"
          , "Asia/Dacca"
          , "Asia/Damascus"
          , "Asia/Dhaka"
          , "Asia/Dili"
          , "Asia/Dubai"
          , "Asia/Dushanbe"
          , "Asia/Famagusta"
          , "Asia/Gaza"
          , "Asia/Harbin"
          , "Asia/Hebron"
          , "Asia/Ho_Chi_Minh"
          , "Asia/Hong_Kong"
          , "Asia/Hovd"
          , "Asia/Irkutsk"
          , "Asia/Istanbul"
          , "Asia/Jakarta"
          , "Asia/Jayapura"
          , "Asia/Jerusalem"
          , "Asia/Kabul"
          , "Asia/Kamchatka"
          , "Asia/Karachi"
          , "Asia/Kashgar"
          , "Asia/Kathmandu"
          , "Asia/Katmandu"
          , "Asia/Khandyga"
          , "Asia/Kolkata"
          , "Asia/Krasnoyarsk"
          , "Asia/Kuala_Lumpur"
          , "Asia/Kuching"
          , "Asia/Kuwait"
          , "Asia/Macao"
          , "Asia/Macau"
          , "Asia/Magadan"
          , "Asia/Makassar"
          , "Asia/Manila"
          , "Asia/Muscat"
          , "Asia/Nicosia"
          , "Asia/Novokuznetsk"
          , "Asia/Novosibirsk"
          , "Asia/Omsk"
          , "Asia/Oral"
          , "Asia/Phnom_Penh"
          , "Asia/Pontianak"
          , "Asia/Pyongyang"
          , "Asia/Qatar"
          , "Asia/Qostanay"
          , "Asia/Qyzylorda"
          , "Asia/Rangoon"
          , "Asia/Riyadh"
          , "Asia/Saigon"
          , "Asia/Sakhalin"
          , "Asia/Samarkand"
          , "Asia/Seoul"
          , "Asia/Shanghai"
          , "Asia/Singapore"
          , "Asia/Srednekolymsk"
          , "Asia/Taipei"
          , "Asia/Tashkent"
          , "Asia/Tbilisi"
          , "Asia/Tehran"
          , "Asia/Tel_Aviv"
          , "Asia/Thimbu"
          , "Asia/Thimphu"
          , "Asia/Tokyo"
          , "Asia/Tomsk"
          , "Asia/Ujung_Pandang"
          , "Asia/Ulaanbaatar"
          , "Asia/Ulan_Bator"
          , "Asia/Urumqi"
          , "Asia/Ust-Nera"
          , "Asia/Vientiane"
          , "Asia/Vladivostok"
          , "Asia/Yakutsk"
          , "Asia/Yangon"
          , "Asia/Yekaterinburg"
          , "Asia/Yerevan"
          , "Europe/London"]
    
    getDateTime = (country) => { 
      const regexp = new RegExp(`\\b${country}\\b`, 'gi') // showing how to pass optional flags
      const userTimeZone = timeZonesL.filter(timeZ => timeZ == timeZ.match(country))
      return event.toLocaleString('en-GB', { timeZone: userTimeZone });
      //return event.toLocaleString('en-GB', { timeZone: 'Asia/Singapore' });;
    }
    
    //step 1
    //test 1 - after user signs in and selects new country/timezone we call it for them
    //e.g. from a dropdown
    //Value in drop down must match a value in the timeZonesL array
    let userSelectedCountry = 'Asia/Singapore'
    //build regex and pass in selected country
    var re = new RegExp("\\b"+userSelectedCountry+"\\b"); 
    //we then call our function with it as a param if it tests truthy to regex match      
    console.log(getDateTime(userSelectedCountry.match(re)))
    
    //step 2
    //On sign out save the time as to what the user selected e.g. 
    //mongoDB.save(getDateTime(userSelectedCountry.match(re)))
    //now we can save any time the user selects
    //NOTE: more needs to be done to finalise list of timezones as some are redundant, not supported by some
    //browsers and you don't want all of them
    
Shucoder
  • 37
  • 2
  • 10
0

i could not solve this issue with moment-timezone libarary and so i shift to dayjs it solved my problem. it is correctly converting time in selected timezone. below is the code for this

import dayjs from "dayjs";
import utc from "dayjs/plugin/utc"; // Import the UTC plugin for dayjs
import timezone from "dayjs/plugin/timezone";
import customParseFormat from "dayjs/plugin/customParseFormat";

// Extend dayjs with the required plugins
dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.extend(customParseFormat);

const getStartAndEndDateTime = (date, time, timezone, duration) => {
  let startDateTime = "";
  let endDateTime = "";

  if (date && time) {
    const formateDDate = dayjs(date).format("YYYY-MM-DD");
    const formatedTime = dayjs(time, "hh:mm a").format("H:mm");
    const timestamp = `${formateDDate} ${formatedTime}`;

    startDateTime = dayjs.tz(timestamp, timezone || dayjs.tz.guess()).format();
    endDateTime = dayjs
      .tz(timestamp, timezone || dayjs.tz.guess())
      .add(duration.value, "m")
      .format();
  }
  return { start_datetime: startDateTime, end_datetime: endDateTime };
};
Bilal Butt
  • 1,202
  • 3
  • 12
  • 15