user12425844
user12425844

Reputation:

Angular: Date Timezone Global parameter setting

I am searching for a way to

How can this be done? Is there a global parameter in Angular to set this, maybe in the config files?

*We have 500 lines of date codes in the code base, which require this global conversion. Sometimes when people are working in different timezones, the application will render different timezone dates. Need to correct previous people's code.

Currently cannot convert these lines to Moment, working with Date in the current codebase.

Also, would this be a proper solution? tzutil /s "Pacific Standard Time" , just learned about this in google

https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/hh875624(v=ws.11)

Upvotes: 6

Views: 39820

Answers (6)

Amol Kalgave
Amol Kalgave

Reputation: 1

You can convert date in any time zone with static value addition or subtraction in UTC time

I converted my date in CST time zone in MM-DD-YYYY HH:mm:ss format in HTML page as below

*<td mat-cell matCellDef="let element"> {{ element.CreateDtm | date: 'MM-dd-yyyy HH:mm:ss' : 'UTC+530' }}

'UTC+530' is used here as my database date value stored in CST timezone but UI display is not synchronized with DB because of DatePipe directive ("The default timezone of DatePipe is your local timezone, which is GMT-8 or -800 in Seattle").

Hence to synchronize UI and DB date values, I added 'UTC+530' which is time difference in my UI and DB date .

Hope this will help to convert your dates in desired timezone format by static value addition or subtraction in UTC time ..

HAPPY CODING...

Upvotes: 0

datpt
datpt

Reputation: 1

In my case, i add utc like : this.tM01CNKD.signDate = new Date(this.tM01CNKD.signDate +'UTC') and it work

Upvotes: 0

Rick
Rick

Reputation: 1880

This should do it.

Pass in null to get pacific date now, or pass in any date to get it converted to pacific:

pacificTimeOfDate(d:Date=null) {
  if (!d)
    d = new Date();
  var year = d.getUTCFullYear();
  var month = d.getUTCMonth();
  var day = d.getUTCDate();
  var hours = d.getUTCHours();
  var minutes = d.getUTCMinutes();
  var seconds = d.getUTCSeconds();
  var utcDate = new Date(year, month, day, hours, minutes, seconds);
  utcDate.setMinutes(utcDate.getMinutes() - 420);
  return utcDate
}

Upvotes: 1

Karthik
Karthik

Reputation: 466

It is best to use date time in ISO 8601 format. Please see as to why and what it gives benefits for using ISO-8601 date format. https://www.iso.org/iso-8601-date-and-time-format.html

The complete post is here Implementing ISO 8601 date time format in Angular

ISO 8601 can be used by anyone who wants to use a standardized way of presenting:

Date,
Time of day,
Coordinated Universal Time (UTC),
Date and time,
Time intervals,
Recurring time intervals

You can use the format in the way you want by using this code. I hope this helps.

export interface HashTable<T> {
  [key: string]: T;
}
import { Injectable } from '@angular/core';
import { HashTable } from './hash-table';

type FormatFunc = (date: Date) => string;
@Injectable({
  providedIn: 'root'
})
export class DateFormat {
  formattingTokenFunc: HashTable<FormatFunc> = {};

  private formattingTokens = /(HH?|HH?|hh?|mm?|ss?|MM?|dd?|yy?y?y?|.)/g;

  constructor() {
    // add years function
    const getYearFunc = (date: Date) => date.getFullYear().toString();

    // Year, no leading zero (e.g. 2015 would be 15)
    this.addFormatToken('y', 0, (date: Date) =>
      (date.getFullYear() % 100).toString()
    );
    this.addFormatToken('yyy', 0, getYearFunc);
    this.addFormatToken('yyyy', 0, getYearFunc);
    // Year, leading zero (e.g. 2015 would be 015)
    this.addFormatToken('yy', 3, (date: Date) =>
      (date.getFullYear() % 100).toString()
    );

    // add months function
    const getMonthFunc = (date: Date) => (date.getMonth() + 1).toString();

    this.addFormatToken('M', 0, getMonthFunc);
    this.addFormatToken('MM', 2, getMonthFunc);

    // add day function
    const getDayFunc = (date: Date) => date.getDate().toString();

    this.addFormatToken('d', 0, getDayFunc);
    this.addFormatToken('dd', 2, getDayFunc);

    // add hours function
    const get12HrFunc = (date: Date) => (date.getHours() % 12).toString();

    // 12-hour clock, with a leading 0 eg (e.g. 06)
    this.addFormatToken('hh', 2, get12HrFunc);
    // 12-hour clock hour
    this.addFormatToken('h', 0, get12HrFunc);

    const get24HrFunc = (date: Date) => date.getHours().toString();

    this.addFormatToken('HH', 2, get24HrFunc);
    this.addFormatToken('H', 0, get24HrFunc);

    // add minute function
    const getMinFunc = (date: Date) => date.getMinutes().toString();
    this.addFormatToken('m', 0, getMinFunc);
    // Minutes with a leading zero
    this.addFormatToken('mm', 2, getMinFunc);

    // add seconds function
    const getSecFunc = (date: Date) => date.getSeconds().toString();
    this.addFormatToken('s', 0, getSecFunc);
    this.addFormatToken('ss', 2, getSecFunc);
  }

  formatToISO8601Date(date: Date | string): string {
    return this.format(date, 'yyyy-MM-dd');
  }

  format(date: Date | string, format: string): string {
    const finalDate = date instanceof Date ? date : new Date(date);

    const matches = format.match(this.formattingTokens);
    let result = '';

    matches.forEach(match => {
      // const hasFunc = this.formattingTokenFunc.hasOwnProperty('match');
      const formatFunc = this.formattingTokenFunc[match];

      result += formatFunc ? formatFunc(finalDate) : match;
    });

    return result;
  }

  prefixZero(length: number, input: string): string {
    return `${Math.pow(10, length)}${input}`.slice(-1 * length);
  }

  prefixZeroFunc(length: number, formatFunc: FormatFunc): FormatFunc {
    return (c: Date) => this.prefixZero(length, formatFunc(c));
  }

  private addFormatToken(
    token: string,
    addZeroesLength: number,
    // formatFunc: ((date: Date) => string)
    formatFunc: FormatFunc
  ): void {
    this.formattingTokenFunc[token] =
      addZeroesLength > 0
        ? this.prefixZeroFunc(addZeroesLength, formatFunc)
        : formatFunc;
  }
}

Upvotes: 0

trungvose
trungvose

Reputation: 20034

I totally agree with @Adrian Brand. Also, it is not an Angular problem. It is more like how you handle your date time on your application.

From my experience. It is always tricky to do this date-time stuff with build-in JavaScript Date.

Also, for handling the Pacific Time, you might need to handle the daylight saving. Which is another problem on its own.

The Pacific Time Zone (PT) is a time zone encompassing parts of western Canada, the western United States, and western Mexico. Places in this zone observe standard time by subtracting eight hours from Coordinated Universal Time (UTC−08:00). During daylight saving time, a time offset of UTC−07:00 is used.

I assume you still send the data as the ISO format to the server.


So I am in Singapore, see the below result for a normal Date constructor.

  1. var date = new Date(2019, 3, 5). //Fri Apr 05 2019 00:00:00 GMT+0800 (Singapore Standard Time)
  2. date.toISOString() //2019-04-04T16:00:00.000Z. Because Singapore is in +08:00 which is 8 hours ahead of UTC.

So if you want always do new Date to result in PST time, which mean

  1. var date = new Date(2019, 3, 5) // Fri Apr 05 2019 00:00:00 GMT-0700 (Pacific Standard Time)
  2. date.toISOString() //2019-04-05T08:00:00.000Z. Because PST is at -08:00, 8 hours behind the UTC. The daylight saving topic of -07:00, I leave it for you.

You will either need to

  1. Override the Date constructor, which is not recommended at all.
  2. Add a new method to the Date construction for displaying or give you a correct ISO format but consider the PST Time zone. Which is involving some string replacement and some math for offset calculation.

Add a method to display string in PST

If you do the constructor with an exact date as var date = new Date(2019, 3, 5). You can just add a new method call toPSTString() and use regex to replace the text inside () to Pacific Standard Time and the GMT+xxx to GMT-08:00 Because the value of the date is absolute.

Date.prototype.toPSTString = function () {
  let date = this.toString();
  //date.replace.... easy part, you could use Regex to do it
  return date;
};

But if you passed in the constructor the date in the ISO String format or a number of milliseconds. It will be very tricky to handle. For instance, if you do new Date("2019-04-05T07:00:00.000Z"), what do you want to see?

See below for how I output the ISO String based on the offset difference. It might give you some idea/

Add a method to get the string in ISO format that consider the PST -08:00 time zone

new Date will always work in your local machine timezone. So If I am in Singapore, I do new Date(2019, 3, 5).toISOString(), it will always give me 2019-04-04T16:00:00.000Z, not the 2019-04-05T08:00:00.000Z as you expected.

You could also overwrite the JS function to output the UTC date but with consideration of PST time.

Date.prototype.toPSTString = function () {
  function convertMinuteToMillisecond(mins) {
    return mins * 60 * 1000;
  }
  let localDateOffsetToUtc = this.getTimezoneOffset(); //the offset between the user local timezone with UTC. In my use case of Singapore, it give me -480.
  const offSetBetweenPSTAndUTC = 480;
  let offsetBetweenPSTAndLocal = offSetBetweenPSTAndUTC - localDateOffsetToUtc;
  let newDate = new Date(
    this.getTime() + convertMinuteToMillisecond(offsetBetweenPSTAndLocal)
  );
  return newDate.toISOString();
};

var date = new Date(2019, 3, 5);
date.toISOString(); //"2019-04-04T16:00:00.000Z" Singapore
date.toPSTString(); //"2019-04-05T08:00:00.000Z" PST

The output looks correct. I haven't really tested it but hope you can get the idea.


But usually, if you are in Singapore, you wanted to see the date in Singapore timezone. Nobody cares about PST timezone. Same if you are in London, you don't want to see the time in Singapore or PST timezone. I think you might want to think about that. Because If your application is growing up, it is getting more difficult to fix this kind of problem.

I wrote about how I handle the timezone and locale in my blog. In my use case, I use moment.js and also, the server side need to support me on that. If you want to have more idea, you can take a look too.

Upvotes: 5

Adrian Brand
Adrian Brand

Reputation: 21658

Working with dates can drive you insane. The biggest problem with working with dates clientside is you have to rely on the clients machine having the date, time and timezone set properly. You are always best to create dates on your server, that way you are in control of the clock.

Having an api endpoint that returns a date for you is the most reliable option. It is well worth the overhead of a round trip to the server.

Upvotes: 3

Related Questions