Home > OS >  get new Date() in other timezone in full text string format
get new Date() in other timezone in full text string format

Time:11-11

I need to get Thailand timezone in this format: Thu Nov 10 2022 14:08:37 GMT 0800 (Malaysia Time). I have tried new Date().toLocaleString("en-US", {timeZone: "Asia/Bangkok"}) but didn't get the correct format I want, probably because of the .toLocaleString(). Is there a simple way to do it?

CodePudding user response:

You can configure the locale string formatter with a whole bunch of options:

console.log(new Date().toLocaleString('en-US', {
  timeZone: 'Asia/Bangkok',
  weekday: 'short',
  year: 'numeric',
  month: 'short',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric',
  timeZoneName: 'short',
  hour12: false
}));

However, the exact format it will output will always be dependent on the locale used and the browser's understanding of how dates should be formatted for that locale. If you want more control over the exact formatting, you'll need to cobble it together yourself:

const date = new Date();

const time = date.toLocaleString('en-US', {
  timeZone: 'Asia/Bangkok',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric',
  timeZoneName: 'short',
  hour12: false
});

const weekday = date.toLocaleString('en-US', {
  timeZone: 'Asia/Bangkok',
  weekday: 'short'
});

console.log(`${weekday} ${date.getFullYear()} ... ${time}`);

If that seems too complicated, use some 3rd party library like Luxon, which can simplify that a bit.

CodePudding user response:

As deceze suggests, you can use Intl.DateTimeFormat with suitable options to get the values you want. Then you can use formatToParts to reorganise them as you wish, e.g. to replicate the format of Date.prototype.toString for any timezone, you can use:

// Return timestamp in same format as Date.prototype.toString
// in designated timezone (IANA representative location)
function toTimezone(tz, date = new Date()) {
  // Get parts except timezone name
  let opts = {
    year: 'numeric',
    month: 'short',
    day: '2-digit',
    weekday: 'short',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    timeZone: tz,
    timeZoneName: 'shortOffset',
    hour12: false
  }
  // To get full timezone name
  let opts2 = {
    hour: 'numeric',
    timeZone: tz,
    timeZoneName: 'long'
  }
  let toParts = opts => new Intl.DateTimeFormat('en', opts)
         .formatToParts(date)
         .reduce((acc, part) => {
           acc[part.type] = part.value;
           return acc;
         }, Object.create(null));
     
  let {year, month, day, weekday, hour, minute,
       second, timeZoneName} = toParts(opts);
  // Fix offset
  let sign = /\ /.test(timeZoneName)? ' ' : '-';
  let [oH, oM] = timeZoneName.substr(4).split(':');
  let offset = `GMT${sign}${oH.padStart(2, '0')}${oM || '00'}`;
  // Get timezone name
  timeZoneName = toParts(opts2).timeZoneName;

return `${weekday} ${month} ${day} ${year} ${hour}:${minute}:${second} ${offset} (${timeZoneName})`;
}

// Examples
['Australia/Adelaide',
 'Asia/Bangkok',
 'Asia/Kolkata',
 'America/New_York',
 'Pacific/Yap',
 'Pacific/Pago_Pago'
].forEach(tz => console.log(toTimezone(tz)));

Support for some options like shortOffset may not be ubiquitous yet. A formatting library with timezone support is a simpler (and more reliable) option. :-)

  • Related