Hi there, in the big application that supports user from multiple countries should always have the support for selecting timezone and even their locale somewhere. In Zyllem, as the SaaS company, this feature has been embedded inside the product since day 1.
What we have applied so far is to follow the best practice to store UTC date/times in our database and display to the user in their local timezone. We’ll also store the time zone rather than the offset so we can support daylight savings time. In the post, I’ll only cover how we display the date in the correct timezone as the server deliver the result via an API and we have the client app to consume it.
As described in the timezone tag wiki, there are two different styles of time zones.
Singapore Standard Time
.Asia/Singapore
.I did a quick test with Moment timezone, and basically most client-side library using standard IANA time zones. Refer to the resource below.
Which is very different from our technology since we are using Microsoft and it come with their timezone (Microsoft’s one).
Singapore Standard Time
ISO 8601 meaning it should always include either a Z (for UTC values)
, or an offset (for local values)
. Therefore, you may take the user’s time zone into account, but the result you deliver should include the local offset so it is unambiguous.
For example, you have the UTC value 2018-04-28T03:00:00.00Z
, then in Asia/Singapore
it should be 2018-04-28T11:00:00.00+08:00
. And that’s what should be delivered over the API.
On the client-side, you can render that value for the user with a library like moment.js. For example:
var string = moment.parseZone('2018-04-28T11:00:00.00+08:00').format('LLL')
See more about localized format at https://momentjs.com/docs/#/displaying/format/.
So that we write a class to also handle both the locale and timezone. Basically, it will extract the locale from browser and display accordingly. For the getSafe function, refer to my previous post here
timezone.ts
import { getSafe } from "./utils";
import * as moment from "moment";
export const DEFAULT_FORMAT = "DD MMM YYYY, HH:mm";
export const NUMERAL_DATE_TIME_ZONE_FORMAT = "L LT";
export const NAME_DATE_TIME_ZONE_FORMAT = "ll LT";
export const NAME_DATE_ONLY_ZONE_FORMAT = "ll";
export const NAME_DATE_TIME_ZONE_FULL_FORMAT = "llll";
export const TIME_ONLY_FORMAT = "LT";
export class MomentTimezone {
private static momentLocale: string;
private static setLocale() {
if(!this.momentLocale) {
this.momentLocale = getSafe(() => navigator.languages[0]) || navigator.language;
moment.locale(this.momentLocale);
}
}
//input format "2018-04-28T11:00:00.00+08:00"
public static formatDateInTimeZone(input: string): string {
this.setLocale();
return moment.parseZone(input).format(this.momentLocale ? NUMERAL_DATE_TIME_ZONE_FORMAT : DEFAULT_FORMAT)
}
public static parseDateInTimeZone(input) {
this.setLocale();
return moment.parseZone(input);
}
}
So If I configure the browser language in Chinese, it will also display in the correct locale as well.