skip to Main Content

I need to get time difference in hours and minutes of other user who is situated in anather country. Here is what i have done.

const timeZone = "Asia/tokyo"; // Time zone can be changed

let arr: any = new Date().toLocaleString("en-US", {
  timeZone: timeZone,
  dateStyle: "full",
  timeStyle: "full",
});

let currentTime = new Date();

Need to get difference between currentHour and arr

2

Answers


  1. Firstly, use en-CA locale for the "calculation" … it outputs yyyy-mm-dd hh:mm:ss which makes it simple to manipulate

    Secondly, add hour12: false as you want 24 hour time

    Then you can

    const minutesToHHMM = (m) => {
      const s = m < 0 ? '-' : '';
      m = Math.abs(m);
      const mm = (m % 60).toString().padStart(2, 0);
      const hh = Math.floor(m / 60);
      return `${s}${hh}:${mm}`;
    }
    const timeZone = 'Australia/Eucla'; // odd timezone to always show minutes in difference
    const date = new Date();
    date.setMilliseconds(0); // remove millisecond since we are not creating the "other" time with milliseconds
    const other = new Date(...date
      .toLocaleString('en-CA', {
        timeZone,
        hour12: false,
      })
      .replaceAll('-',':') // convert yyyy-mm-dd to yyyy:mm:dd
      .replaceAll(', ', ':') // add ':' between date and time
      .split(':') // split all the values
      .map((v,i) => v - (i===1)) // subtract one from month
    );
    
    console.log("other time", other.toLocaleString());
    console.log("local time", date.toLocaleString());
    console.log("difference", minutesToHHMM((other-date)/60000));

    My Typescript is inelegant … but

    const minutesToHHMM = (m:number) => {
      const s = m < 0 ? '-' : '';
      m = Math.abs(m);
      const mm = (m % 60).toString().padStart(2, "0");
      const hh = Math.floor(m / 60);
      return `${s}${hh}:${mm}`;
    }
    const timeZone = 'Australia/Eucla'; // odd timezone to always show minutes in difference
    const date = new Date();
    date.setMilliseconds(0); // remove millisecond since we are not creating the "other" time with milliseconds
    
    const other = new Date(...(date
      .toLocaleString('en-CA', {
          timeZone,
          hour12: false,
      })
      .replaceAll('-',':') // convert yyyy-mm-dd to yyyy:mm:dd
      .replaceAll(', ', ':') // add ':' between date and time
      .split(':') // split all the values
      .map(Number)
      .map((v:number, i:number) => v - ((i===1) ? 1 : 0)) as []) // subtract 1 from month
    );
    
    console.log("other time", other.toLocaleString());
    console.log("local time", date.toLocaleString());
    console.log("difference", minutesToHHMM((+other - +date)/60000));
    

    Tried that on a TS Playground, seems to work

    Login or Signup to reply.
  2. Solutions like that from Jaromanda X (reproduced below using Intl.DateTimeFormat.formatToParts) are OK, however better to pass an actual Date object rather than the date and time values.

    I think it’s more elegant to get the difference between the actual offsets (see lower).

    function msToHMS(ms) {
      let sign = ms < 0? '-' : '+';
      ms = Math.abs(ms);
      let z = n => (n < 10? '0':'') + n;
      let hr = (ms / 3.6e6) | 0;
      let min = ((ms % 3.6e6) / 6e4) | 0;
      let sec = ((ms % 6e4) / 1e3) | 0;
      return `${sign}${z(hr)}:${z(min)}:${z(sec)}`;
    }
    
    function getTZDiff(tz, d = new Date()) {
      let tv = d - (d % 1e3);
      let {year, month, day, hour, minute, second} = new Intl.DateTimeFormat('en', {
        year:'numeric', month:'numeric', day:'numeric',
        hour:'numeric', minute:'numeric', second:'numeric',
        timeZone: tz,
        hour12: false
      }).formatToParts(d).reduce((acc,part) => {
          acc[part.type] = part.value;
          return acc;
        }, Object.create(null)
      );
      return msToHMS(new Date(year, month-1, day, hour, minute, second) - tv);
    }
    
    console.log(getTZDiff('America/New_York', new Date(2023,3,2,1,30)));

    Using timezone offsets:

    /* Return offset at loc for date
     * @param {string} loc - IANA representative location
     * @param {Date} date to get offset for
     * @returns {string} offset as ±hh:mm
     */
    function getOffsetForLoc(loc, d = new Date()) {
      let offset = d.toLocaleString('en',{
        timeZoneName:'longOffset', timeZone: loc
      }).match(/[+|-][^+-]+$/); 
      return offset[0];
    }
    
    /* Convert offset in ±hh:mm:ss format to seconds
     * @param {string} offset - ±hh:mm:ss format
     * @returns {number} offset in seconds
     */
    function offsetToSecs(offset) {
      let sign = offset[0] == '-' ? -1 : 1;
      let [hr, min, sec] = offset.match(/d+/g);
      return sign * (hr*3600 + min*60 + (sec||0)*1); 
    }
    
    /* Convert secons to time in ±hh:mm:ss format
     * @param {number} secs - seconds to convert
     * @returns {string} equivalent in ±hh:mm:ss format
     */
    function secsToHMS(secs) {
      let sign = secs < 0? '-' : '+';
      secs = Math.abs(secs);
      let z = n => (n < 10? '0':'') + n;
      let hr = (secs / 3600) | 0;
      let min = ((secs % 3600) / 60) | 0;
      let sec = secs % 60;
      return `${sign}${z(hr)}:${z(min)}:${z(sec)}`;
    }
    
    // Get diference in offset between two locations.
    // Add difference to loc1 to get time in loc2
    function getOffsetDifference(loc1, loc2, d = new Date()) {
      let off1 = offsetToSecs(getOffsetForLoc(loc1, d));
      let off2 = offsetToSecs(getOffsetForLoc(loc2, d));
      return secsToHMS(off2 - off1);
    }
    
    // Examples
    let yourLoc = new Intl.DateTimeFormat().resolvedOptions().timeZone;
    let cha = 'Pacific/Chatham';
    
    console.log(
        `You  : ${yourLoc} ${getOffsetForLoc(yourLoc)}` +
      `nOther: ${cha} ${getOffsetForLoc(cha)}` +
      `nDiff : ${getOffsetDifference(yourLoc, cha)}` +
      ` (i.e. You + Diff == Other)` +
      `nRev  : ${getOffsetDifference(cha, yourLoc)}` +
      ` (i.e. Other + Rev == You)`
    );
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search