moment-timezone icon indicating copy to clipboard operation
moment-timezone copied to clipboard

Links are not recursive across data bundles

Open sosnik opened this issue 4 years ago • 4 comments

Version: 0.5.32

Issue description:

moment-timezone doesn't seem to recursively resolve links that point to other links outside of the bundle.

To illustrate, this is with vanilla moment.tz:

// US/Central is a link to America/Chicago
> moment.tz.zone('US/Central')
{
  name: 'US/Central',
  abbrs: [...],
  offsets: [...],
  untils: [...],
  population: ...
}
> moment().tz('US/Central').format('hh:mm Z z')
'03:05 -06:00 CST'
// Add a 'link to a link' within the current dataset
> moment.tz.link('US/Central|CT')
undefined
> moment.tz.zone('CT')
{
  name: 'CT',
  ...
}
> moment().tz('CT').format('hh:mm Z z')
'03:29 -06:00 CST'
// as expected

If, instead of using moment.tz.link() to create the link in the current dataset, I load a similar link (US/Pacific/PT) as part of a larger dataset using moment.tz.load(), the PT link will no longer resolve.

Below is an extract of my packed data that I am loading:

packedBundle = {
	version: '2020-abbr',
	zones: [...],
	links: [
		'US/Central|CT',
		'US/Pacific|PT',
		'Asia/Kabul|AFT'
		...
	]
}

Now it gets interesting:

> moment.tz.load(packedBundle)
undefined
// Asia/Kabul is a canonical location within the tz database (and moment's default dataset). Linking across bundles works here as expected.
> moment.tz.zone('AFT')
{
  name: 'AFT',
  abbrs: [ '+04', '+0430' ],
  untils: [ -788932800000, Infinity ],
  offsets: [ -240, -270 ],
  population: 4600000
}
// CT was linked using moment.tz.link() previously, so it works here:
> moment.tz.zone('CT')
{
  name: 'CT',
  abbrs: [...  ],
  untils: [...  ],
  offsets: [...  ],
  population: 9200000
}
// PT was linked to US/Pacific in the newly-loaded bundle as per the extract above. US/Pacific is a link to America/Los_Angeles within the tz database and the default dataset.
> moment.tz.zone('PT')
null
// Interestingly enough, US/Pacific no longer returns a zone object:
> moment.tz.zone('US/Pacific')
null

As you can see, links are not resolved recursively across datasets, Moreover, defining a link in a loaded dataset breaks link resolution in the original.

Initial Investigation

At first I thought that defining links in a new data bundle overrides all links from the vanilla data bundle. This is not the case:

> moment.tz.zone('America/Argentina/Catamarca')
{
  name: 'America/Argentina/Catamarca',
  ...
}
> moment.tz.zone('America/Catamarca')
{
  name: 'America/Catamarca',
}
// America/Catamarka links to America/Argentina/Catamarca within the vanilla dataset, as I didn't link to America/Catamarca within the dataset I was loading manually, the link still works

sosnik avatar Dec 13 '20 10:12 sosnik

My guess is that this has the same root cause as https://github.com/moment/moment-timezone/issues/301#issuecomment-466765295

gilmoreorless avatar Dec 13 '20 10:12 gilmoreorless

Seems possible. In my particular usecase, I could work around this issue by:

  1. Splitting out zones[] and links[] from the bundle and feeding them to moment with .add() and link() separately;
  2. Overwriting the default data bundle (but reconciliation after updates will be annoying, not to mention portability);
  3. Mapping links to destinations on my end before passing the "proper" input to moment for parsing.

Having said that, here's hoping for an official fix at the library level.

sosnik avatar Dec 13 '20 11:12 sosnik

Update: I attempted to load my set of links with the m.tz.link() method instead of the load() method. Link resolution is still broken:

> const moment = require('moment-timezone')
> const packedBundle = require('./tz.abbr.packed.json')
> moment.tz.add(packedBundle.zones) // adding just the zones
> moment.tz.zone('Atlantic Standard Time')
// This returns a zone object
> moment.tz.link(packedBundle.links)
> moment.tz.zone('CT')
// Returns null
> moment.tz.zone('US/Central')
// also returns null. Link resolution is indeed broken.

I am not (yet) sure why creating links in bulk causes an issue while doing it "manually" doesn't, but I am beginning to suspect that @gilmoreorless is right and this is similar to his issue.

sosnik avatar Dec 14 '20 07:12 sosnik

Iterating over links[] and adding them one at a time with m.tz.link() instead of chucking the whole array at it produces the same result: link resolution is still broken.

This leads me to question, at what point are things falling apart? Adding a single link (as seen in my original issue) does work.

sosnik avatar Dec 14 '20 07:12 sosnik

Close in favor of https://github.com/moment/moment-timezone/issues/301

ichernev avatar Aug 25 '22 15:08 ichernev