Reputation:
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
Upvotes: 6
Views: 39820
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
Reputation: 1
In my case, i add utc like :
this.tM01CNKD.signDate = new Date(this.tM01CNKD.signDate +'UTC')
and it work
Upvotes: 0
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
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
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 ofUTC−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.
var date = new Date(2019, 3, 5)
. //Fri Apr 05 2019 00:00:00 GMT+0800 (Singapore Standard Time)
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
var date = new Date(2019, 3, 5)
// Fri Apr 05 2019 00:00:00 GMT-0700 (Pacific Standard Time)
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
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/
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
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