Angular: Date Timezone Global parameter setting
Asked Answered
S

6

6

I am searching for a way to

  • Convert all-new Dates upon construction/declaration to Pacific Standard time. (Without every developer in team manually setting the timezone)

  • Additionally, dates displayed should be showed in Pacific Timezone when displaying in HTML, console.log, etc

    let test = new Date(2019, 3, 5);
    console.log(test);
    

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)

Slade answered 8/6, 2020 at 23:45 Comment(7)
Is this helpful?Headlong
hi @arcticwhite I have to update 500 lines of code with this, trying to find a global way,if possibleSlade
you can use moment to set global timezoneUnwisdom
momentjs.com/timezoneUnwisdom
hi @AdeshKumar currently we are using Date, and are not converting to Moment as of yetSlade
actually Date is totally machine dependent.Unwisdom
did you tried overriding date constructor ? (may be in index,html) #8922645.Cartilage
A
5

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.

Aminaamine answered 12/6, 2020 at 7:25 Comment(2)
hi, would this work? just learned about this, tzutil /s "Pacific Standard Time" , in googleSlade
I would not know how it will fit in your use case. It just came out of my mind without any actual testing :)Aminaamine
P
3

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.

Promptbook answered 11/6, 2020 at 4:34 Comment(4)
so there is probably no solution then? with a global parameter? thanksSlade
You have already said you don't want to use moment, that would be your easiest client side solution but you still rely on an accurate clock on the clients machine. One solution is to convert the clients date to UTC and then apply the Pacific timezone offset to it. This will give you the date in Pacific timezone but it is only useful if the client has their clock set correctly. If it is for unimportant display purposes then it might be OK but anything like creating orders you have to use the server time or else you can't trust it.Promptbook
@Artportraitdesign1 does that solve your issue? #13854605Sitarski
hi, would this work? just learned about this, tzutil /s "Pacific Standard Time" , in googleSlade
P
1

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
}
Pyrene answered 13/6, 2020 at 2:47 Comment(0)
S
0

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;
  }
}
Sacaton answered 14/6, 2020 at 3:0 Comment(0)
I
0

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

Impasse answered 16/11, 2022 at 3:46 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Slavey
B
0

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...

Buzzer answered 7/5, 2024 at 5:11 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.