What is the best method to determine the time gap according to time zones?

I am trying to calculate the time difference in hours and minutes of a user located in a different country. Here is my approach so far.

const targetTimeZone = "Asia/tokyo"; // Time zone can be adjusted

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

let currentTime = new Date();

I need to determine the difference between the current time and the targetTime.

Answer №1

Jaromanda X's solution, as shown below using Intl.DateTimeFormat.formatToParts, is acceptable; however, it would be more optimal to pass an actual Date object instead of individual date and time values.

In my opinion, a more refined approach would involve calculating the difference between the actual offsets (refer to the section below).

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)));

Utilizing 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)`
);

Answer №2

To start, utilize the en-CA locale for the "calculation" process which will yield an output of yyyy-mm-dd hh:mm:ss, simplifying further manipulation.

Next, include hour12: false to ensure a 24-hour time format is used.

Now you can proceed with:

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'; // unique timezone choice for consistent minute variations
const date = new Date();
date.setMilliseconds(0); // omit milliseconds for uniformity

const other = new Date(...date
  .toLocaleString('en-CA', {
    timeZone,
    hour12: false,
  })
  .replaceAll('-',':') // convert yyyy-mm-dd to yyyy:mm:dd
  .replaceAll(', ', ':') // insert ':' between date and time
  .split(':') 
  .map((v,i) => v - (i===1)) 

console.log("other time", other.toLocaleString());
console.log("local time", date.toLocaleString());
console.log("difference", minutesToHHMM((other-date)/60000));

Although my Typescript implementation may not be perfect...

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'; // chosen timezone for clarity in minute differences
const date = new Date();
date.setMilliseconds(0); // exclude milliseconds from time comparison

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(':')
  .map(Number)
  .map((v:number, i:number) => v - ((i===1) ? 1 : 0)) as []) // offset month by 1

console.log("other time", other.toLocaleString());
console.log("local time", date.toLocaleString());
console.log("difference", minutesToHHMM((+other - +date)/60000));

Tested this on a TS Playground, appears to function correctly

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Show input field depending on chosen option

I'm looking to create a dynamic form where specific input fields are displayed based on the selection made in another field. For example, if "gender: male" is selected, the input field for "blue" should appear, and if "gender: female" is selected, the ...

Make an ajax call, pause for a moment, and then make a second ajax call

Here is what I have done: $.when(Results.ServiceController.Ajax1(clickedNumber)) .then(Results.UtilFunctions.Wait(5000)) .then(Results.ServiceController.Ajax2(clickedNumber)); The Ajax1 function returns an ajax object. The Wait function has the following ...

What is the best way to retrieve an ID when parsing JSON recursively?

Could you provide guidance on how to retrieve the IDs of all children when parsing JSON data? I have attempted to use a recursive function, but it seems to be calling infinitely. For reference, here is my code snippet: http://jsfiddle.net/Ds8vQ/ for(var ...

Enhancing the functionality of ng-click within ng-repeat

I am seeking a solution to enhance the functionality of the ngClickDirective by implementing a custom listener. The provided code successfully works with ng-click elements that are not nested within ng-repeat: $provide.decorator('ngClickDirective&apo ...

Troubleshooting JQuery Variable Overwriting Problem

Here is the code snippet I am working with: <script> $(document).ready(function() { var settings_image ={ url:"<?php echo site_url('/cms/editor/upload/images');?>", method: "POST", fileName: "file", returnType: ...

The PHP-generated table is not being appended to the specified div with jQuery

I am currently working on developing a webpage that displays live forex rates to users. I am pulling the values from a feed and echoing them into a table. My goal now is to use jQuery to show this table to the user. The issue I am facing is that when I tr ...

Experiencing difficulty adjusting the width of a Tumblr post with JavaScript or jQuery?

Calling all coding experts! I've been working on customizing a Tumblr theme, and everything is looking good except for one issue. I'm struggling to adjust the width of photos on a permalink (post) page. Check out this link: You'll notice t ...

Codeigniter 3 and JQuery seamless refresh: A dynamic duo

I'm currently attempting to utilize the following code: setInterval(function() { $('#myDiv').load('contentToLoad.php');}, 5000); while working with CodeIgniter. My attempt so far has been: setInterval(function() { $('.image ...

How can you extract elements from a JSON array into separate variables based on a specific property value within each element?

In the following JSON array, each item has a category property that determines its grouping. I need to split this array into separate JSON arrays based on the category property of each item. The goal is to extract all items with the category set to person ...

What are the key indicators that differentiate a serialized dictionary from a regular JSON object?

When my application sends an ajax POST request to the server, and if the server validation fails, it returns either a string or a Dictionary<string, object> back to the client. If the server returns a Dictionary, then the serialized responseText tha ...

Deactivate the Landscape orientation feature on your AMP website

Is it feasible to prevent landscape mode in an AMP site without the ability to add custom JavaScript or event listeners? ...

Angular: Design dependent on attributes

Can I customize the styling of a div in accordance with a boolean property called "isActive" on my controller using Angular? <div class="col-md-3" (click)="isActive = !isActive"> <div class="center"> <i class="fa fa-calendar"& ...

Setting up SKPM (Sketch Plugin Manager) using npm

I've been trying to install a specific npm package, but I keep encountering numerous errors that are unfamiliar to me. It's important to note that these errors occur after running the command sudo npm install -g skpm: gyp ERR! configure error g ...

TypeScript Error: The Object prototype must be an Object or null, it cannot be undefined

Just recently, I delved into TypeScript and attempted to convert a JavaScript code to TypeScript while incorporating more object-oriented features. However, I encountered an issue when trying to execute it with cmd using the ns-node command. private usern ...

Obtaining an authorization token through a POST request and subsequently utilizing the POST response in a GET request

After requesting a Spotify access code using the POST method and storing the response in a variable, an attempt was made to access the token using the GET method immediately after. { angular.module('app') .controller(&apo ...

The NgFor is unable to iterate over an array because it is being treated as an

When attempting to call a new endpoint for displaying data, I noticed that the previous set of data is wrapped with an extra pair of brackets '[]', which seems to be causing a problem. The new endpoint does not format the data in this way when I ...

What is the best way to switch out an image every 5 seconds?

I am trying to make three images in my HTML code change every five seconds, but for some reason, it's not working. Can anyone help me figure out why? var images = []; images[0] = ['photoFromInternet']; images[1] = ['photoFromInternet2 ...

Verify the user's activity status in the MySQL database using Node.js by checking the timestamp of their last login

I have a query regarding user activity and deletion from the database. I need to determine when a user last logged in to see if their account is inactive. Unfortunately, I am unsure of how to tackle this task or check for the last login time. If anyone c ...

Typescript's Approach to Currying

In TypeScript, I am attempting to define types for a currying function. The implementation in JavaScript is shown below: function curry1(fn) { return (x) => (fn.length === 1 ? fn(x) : curry1(fn.bind(undefined, x))); } This function works effectively ...

What is the best way to get rid of a connect-flash notification?

I'm having trouble removing the message (with the username displayed) after logging out by pressing the logout button. Every time I try to press the logout button, it just refreshes the page without any action. I want to stay on the same page and not ...