@@ -26,7 +26,7 @@ import timezoneSmall from './timezone-small';
2626import timezoneLarge from './timezone-large' ;
2727import timezoneLargeAlt from './timezone-large-alt' ;
2828import { parse } from './format-parse' ;
29- import { forEach , isString , toNumber } from '@tubular/util' ;
29+ import { forEach , isBoolean , isString , toNumber } from '@tubular/util' ;
3030import { CalendarType , DayOfWeek , Month , LAST } from './calendar' ;
3131import { getDeltaTAtJulianDate , tdtToUt , utToTdt } from './ut-converter' ;
3232import { defaultLocale , getMinDaysInWeek , getStartOfWeek , getWeekend , hasDateTimeStyle , hasIntlDateTime } from './locale-data' ;
@@ -105,8 +105,12 @@ export function initTimezoneLargeAlt(failQuietly = false): void {
105105}
106106
107107let pollingInterval : any ;
108+ let lastUpdateName = 'small' ;
109+ let currentTzVersion = Timezone . version === 'unspecified' ? '' : Timezone . version ;
108110
109- const zonesUrl = 'https://unpkg.com/@tubular/time/dist/data/timezone-{name}.js' ;
111+ const versionCheckUrl = 'https://tzexplorer.org/api/tz-version' ;
112+ const zonesUrl1 = 'https://unpkg.com/@tubular/time/dist/data/timezone-{name}.js' ;
113+ const zonesUrl2 = 'https://tzexplorer.org/tzdata/timezone-{name}.js' ;
110114
111115export type ZoneOptions = 'small' | 'large' | 'large-alt' ;
112116
@@ -115,15 +119,50 @@ export function pollForTimezoneUpdates(zonePoller: IZonePoller | false, name: Zo
115119 clearInterval ( pollingInterval ) ;
116120
117121 if ( zonePoller && name && intervalDays >= 0 ) {
118- const url = zonesUrl . replace ( '{name}' , name ) ;
119- const poll = ( ) : void => {
120- zonePoller . getTimezones ( url ) . then ( zones => {
121- dispatchUpdateNotification ( Timezone . defineTimezones ( zones ) ) ;
122- } )
123- . catch ( err => dispatchUpdateNotification ( err instanceof Error ? err : new Error ( err ) ) ) ;
122+ const poll = async ( ) : Promise < void > => {
123+ let latestTzVersion : string ;
124+
125+ try {
126+ latestTzVersion = await zonePoller . getLatestVersion ( versionCheckUrl ) ;
127+ }
128+ catch ( e ) {
129+ dispatchUpdateNotification ( e ) ;
130+ return ;
131+ }
132+
133+ if ( latestTzVersion <= currentTzVersion && lastUpdateName === name ) {
134+ dispatchUpdateNotification ( false ) ;
135+ return ;
136+ }
137+
138+ let zones : any ;
139+ let updated = false ;
140+
141+ try {
142+ zones = await zonePoller . getTimezones ( zonesUrl1 . replace ( '{name}' , name ) ) ;
143+ updated = Timezone . defineTimezones ( zones ) ;
144+ }
145+ catch { }
146+
147+ if ( ! updated ) {
148+ try {
149+ zones = await zonePoller . getTimezones ( zonesUrl2 . replace ( '{name}' , name ) ) ;
150+ updated = Timezone . defineTimezones ( zones ) ;
151+ }
152+ catch ( e ) {
153+ dispatchUpdateNotification ( e ) ;
154+ return ;
155+ }
156+ }
157+
158+ if ( updated )
159+ currentTzVersion = latestTzVersion ;
160+
161+ lastUpdateName = name ;
162+ dispatchUpdateNotification ( updated ) ;
124163 } ;
125164
126- poll ( ) ;
165+ poll ( ) . finally ( ) ;
127166
128167 if ( intervalDays > 0 ) {
129168 pollingInterval = setInterval ( poll , Math . max ( intervalDays * DAY_MSEC , 3600000 ) ) ;
@@ -154,6 +193,9 @@ export async function getTimezones(zonePoller: IZonePoller, name: ZoneOptions =
154193const listeners = new Set < ( result : boolean | Error ) => void > ( ) ;
155194
156195function dispatchUpdateNotification ( result : boolean | Error ) : void {
196+ if ( ! ( result instanceof Error ) && ! isBoolean ( result ) )
197+ result = new Error ( String ( result ) ) ; // Oddly, some errors come through as numbers like 404.
198+
157199 listeners . forEach ( listener => {
158200 try {
159201 listener ( result ) ;
0 commit comments