@@ -15,38 +15,47 @@ export interface ITimezoneMetadata {
1515}
1616
1717export function getTimezoneMetadata ( timezone : string , date : Date ) : ITimezoneMetadata {
18- const timestamp = date . getTime ( ) ;
19- const zone = moment . tz . zone ( timezone ) ;
20- const zonedDate = moment . tz ( timestamp , timezone ) ;
21- const offset = zonedDate . utcOffset ( ) ;
22- const offsetAsString = zonedDate . format ( "Z" ) ;
23- const abbreviation = getAbbreviation ( timezone , timestamp ) ;
24-
18+ const { abbrs, offsets, population, untils } = moment . tz . zone ( timezone ) ;
19+ const index = findOffsetIndex ( date . getTime ( ) , untils ) ;
20+ const offset = offsets [ index ] * - 1 ;
2521 return {
26- abbreviation,
22+ abbreviation : getNonOffsetAbbreviation ( abbrs [ index ] ) ,
2723 offset,
28- offsetAsString,
29- population : zone . population ,
24+ offsetAsString : getOffsetAsString ( offset ) ,
25+ population,
3026 timezone,
3127 } ;
3228}
3329
3430/**
35- * Get the abbreviation for a timezone.
36- * We need this utility because moment-timezone's `abbr` will not always give the abbreviated time zone name,
37- * since it falls back to the time offsets for each region.
38- * https://momentjs.com/timezone/docs/#/using-timezones/formatting/
31+ * Ignore abbreviations that are simply offsets, i.e. "+14" instead of "PST"
32+ * @param abbreviation
3933 */
40- function getAbbreviation ( timezone : string , timestamp : number ) : string | undefined {
41- const zone = moment . tz . zone ( timezone ) ;
42- if ( zone ) {
43- const abbreviation = zone . abbr ( timestamp ) ;
44-
45- // Only include abbreviations that are not just a repeat of the offset
46- if ( abbreviation . length > 0 && abbreviation [ 0 ] !== "-" && abbreviation [ 0 ] !== "+" ) {
47- return abbreviation ;
34+ function getNonOffsetAbbreviation ( abbreviation : string ) {
35+ return isNonOffsetAbbreviation ( abbreviation ) ? abbreviation : undefined ;
36+ }
37+
38+ function isNonOffsetAbbreviation ( abbreviation : string ) {
39+ return abbreviation != null && abbreviation . length > 0 && abbreviation [ 0 ] !== "-" && abbreviation [ 0 ] !== "+" ;
40+ }
41+
42+ function findOffsetIndex ( timestamp : number , untils : number [ ] ) {
43+ for ( let i = 0 ; i < untils . length ; i ++ ) {
44+ if ( i === untils . length - 1 || timestamp < untils [ i ] ) {
45+ return i ;
4846 }
4947 }
48+ return 0 ;
49+ }
50+
51+ function getOffsetAsString ( offset : number ) {
52+ const offsetVal = Math . abs ( offset ) ;
53+ const minutes = offsetVal % 60 ;
54+ const hours = ( offsetVal - minutes ) / 60 ;
55+ const sign = offset >= 0 ? "+" : "-" ;
56+ return `${ sign } ${ lpad ( hours ) } :${ lpad ( minutes ) } ` ;
57+ }
5058
51- return undefined ;
59+ function lpad ( num : number ) {
60+ return num < 10 ? "0" + num : num ;
5261}
0 commit comments