Upstream spencermountain/spacetime state of the touched files before fe90cae667

This commit is contained in:
upstream committed 2026-10-02 16:02:11 +02:00
1 parent 081c965030
commit d47824c8f3
6 files changed
+2406

No files matched your search

+212
View File
@@ -0,0 +1,212 @@
// CLI orchestration: read zoneinfo, normalize records, report differences, then write.
import { execFileSync } from 'node:child_process'
import {
existsSync,
readFileSync,
readdirSync,
renameSync,
statSync,
unlinkSync,
writeFileSync
} from 'node:fs'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import data from '../../zonefile/iana.js'
import aliases from '../../zonefile/aliases.js'
import { parseIntervals, normalizeZone } from './lib.js'
import { printHeader, printReport, printResult, printError, printHelp } from './report.js'
const root = fileURLToPath(new URL('../../', import.meta.url))
// Directory-only legacy keys may be retained with --allow-unsupported.
// Missing or malformed files remain fatal because their timezone state is unknown.
export class UnsupportedZoneError extends Error {}
export const parseArgs = (args) => {
const options = {
year: new Date().getUTCFullYear(),
zoneinfoDir: '/usr/share/zoneinfo',
check: false,
verbose: false,
allowUnsupported: false
}
for (let i = 0; i < args.length; i += 1) {
const arg = args[i]
if (arg === '--check') {
options.check = true
} else if (arg === '--verbose') {
options.verbose = true
} else if (arg === '--allow-unsupported') {
options.allowUnsupported = true
} else if (arg === '--help') {
options.help = true
} else if (['--year', '--zoneinfo-dir', '--output'].includes(arg)) {
const value = args[++i]
if (!value || value.startsWith('--')) {
throw new Error('Missing value for ' + arg)
}
if (arg === '--year') {
if (!/^\d{4}$/.test(value) || Number(value) < 1900 || Number(value) > 9998) {
throw new Error('Year must be 1900–9998')
}
options.year = Number(value)
} else {
options[arg === '--output' ? 'output' : 'zoneinfoDir'] = resolve(value)
}
} else {
throw new Error('Unknown option: ' + arg)
}
}
options.output ||= join(root, `zonefile.${options.year}.js`)
return options
}
// Library keys are lowercase; zoneinfo paths are case-sensitive on many systems.
// Apply known aliases, then resolve every component using its actual spelling.
export const resolveZone = (directory, name) => {
name = aliases[name] || name
let path = directory
for (const component of name.split('/')) {
if (!component || component === '.' || component === '..') {
throw new Error('Invalid zone name')
}
const matches = readdirSync(path).filter(
(entry) => entry.toLowerCase() === component.toLowerCase()
)
if (matches.length !== 1) {
throw new Error('Missing or ambiguous zone: ' + name)
}
path = join(path, matches[0])
}
const stats = statSync(path)
// zdump can silently report UTC for a directory. Reject it before invocation.
if (stats.isDirectory()) {
throw Object.assign(new UnsupportedZoneError('Zone name resolves to a directory, not a timezone: ' + name), {
details: [
`Resolved path: ${path}`,
`Available entries: ${readdirSync(path).sort().join(', ')}`,
'Choose a specific timezone or define an explicit library alias; a directory has no offset or transitions.'
]
})
}
if (!stats.isFile() || readFileSync(path).subarray(0, 4).toString() !== 'TZif') {
throw new Error('Not a compiled TZif file: ' + name)
}
return path
}
// macOS provides +VERSION; common Linux distributions embed it in tzdata.zi.
// File modification times are not reliable tzdata release identifiers.
const sourceVersion = (directory) => {
for (const name of ['+VERSION', 'tzdata.zi']) {
const path = join(directory, name)
if (existsSync(path)) {
const text = readFileSync(path, 'utf8')
const version = name === '+VERSION' ? text.trim() : /^# version (\S+)/m.exec(text)?.[1]
if (version) {
return version
}
}
}
return 'unknown'
}
// Inject the reader so callers can supply fixtures without invoking zdump.
// Build a fresh result and retain diagnostic context without mutating source data.
export const updateZones = (zones, year, readZone) => {
const result = {}
const changes = []
const unsupported = []
for (const [name, previous] of Object.entries(zones)) {
// Acquisition and parsing errors must fail, even with --allow-unsupported.
let intervals
try {
intervals = parseIntervals(readZone(name))
} catch (error) {
if (error instanceof UnsupportedZoneError) {
unsupported.push({ name, reason: error.message, previous, details: error.details })
result[name] = { ...previous }
continue
}
throw new Error(`${name}: ${error.message}`)
}
try {
result[name] = normalizeZone(intervals, previous, name, year)
} catch (error) {
unsupported.push({ name, reason: error.message, previous, intervals, details: error.details })
result[name] = { ...previous }
continue
}
if (JSON.stringify(previous) !== JSON.stringify(result[name])) {
changes.push({ name, before: previous, after: result[name] })
}
}
return { result, changes, unsupported }
}
export const main = (args = process.argv.slice(2)) => {
const options = parseArgs(args)
if (options.help) {
printHelp()
return
}
const { year, zoneinfoDir } = options
const version = sourceVersion(zoneinfoDir)
const total = Object.keys(data).length
printHeader({ ...options, version, total })
const { result, changes, unsupported } = updateZones(data, year, (name) => {
const path = resolveZone(zoneinfoDir, name)
// Bound extraction to one UTC year; argument arrays avoid shell interpretation.
// Interval output includes an initial offset even for zones with no transitions.
return execFileSync('zdump', ['-i', '-c', `${year},${year + 1}`, path], {
encoding: 'utf8',
timeout: 10000,
maxBuffer: 1024 * 1024,
env: { ...process.env, LC_ALL: 'C' },
stdio: ['ignore', 'pipe', 'pipe']
})
})
printReport({ changes, unsupported, total, verbose: options.verbose })
// Check mode and the unsupported-zone gate must run before any file write.
if (options.check) {
if (changes.length > 0 || unsupported.length > 0) {
process.exitCode = 1
}
printResult(
changes.length > 0 || unsupported.length > 0 ? 'Check needs attention. No files written.' : 'Check passed. No files written.',
Boolean(changes.length > 0 || unsupported.length > 0)
)
return
}
if (unsupported.length > 0 && !options.allowUnsupported) {
throw new Error(
'No output written. Resolve unsupported zones or explicitly preserve them with --allow-unsupported.'
)
}
const source = JSON.stringify({
year,
tzdata: version,
unsupported: unsupported.map((o) => o.name)
})
const text = `// Generated by scripts/tz/update.js: ${source}\nexport default ${JSON.stringify(result, null, 2)}\n`
// Rename within the destination directory so readers never see a partial file.
// Only remove a temporary file created by this run (exclusive creation may fail).
const temporary = join(dirname(options.output), `.zonefile-${process.pid}.tmp`)
let created = false
try {
writeFileSync(temporary, text, { encoding: 'utf8', flag: 'wx' })
created = true
renameSync(temporary, options.output)
} finally {
if (created && existsSync(temporary)) {
unlinkSync(temporary)
}
}
printResult(`Wrote ${options.output}`)
}
try {
main()
} catch (error) {
printError(error.message)
process.exitCode = 1
}
+68
View File
@@ -0,0 +1,68 @@
import Spacetime from './spacetime.js'
import whereIts from './whereIts.js'
import version from './_version.js'
const main = (input, tz, options) => new Spacetime(input, tz, options)
// set all properties of a given 'today' object
const setToday = function (s) {
const today = s._today || {}
Object.keys(today).forEach((k) => {
s = s[k](today[k])
})
return s
}
//some helper functions on the main method
main.now = (tz, options) => {
let s = new Spacetime(new Date().getTime(), tz, options)
s = setToday(s)
return s
}
main.today = (tz, options) => {
let s = new Spacetime(new Date().getTime(), tz, options)
s = setToday(s)
return s.startOf('day')
}
main.tomorrow = (tz, options) => {
let s = new Spacetime(new Date().getTime(), tz, options)
s = setToday(s)
return s.add(1, 'day').startOf('day')
}
main.yesterday = (tz, options) => {
let s = new Spacetime(new Date().getTime(), tz, options)
s = setToday(s)
return s.subtract(1, 'day').startOf('day')
}
main.fromUnixSeconds = (secs, tz, options) => {
return new Spacetime(secs * 1000, tz, options)
}
main.extend = function (obj = {}) {
Object.keys(obj).forEach((k) => {
Spacetime.prototype[k] = obj[k]
})
return this
}
main.timezones = function () {
const s = new Spacetime()
return s.timezones
}
main.max = function (tz, options) {
const s = new Spacetime(null, tz, options)
s.epoch = 8640000000000000
return s
}
main.min = function (tz, options) {
const s = new Spacetime(null, tz, options)
s.epoch = -8640000000000000
return s
}
//find tz by time
main.whereIts = whereIts
main.version = version
//aliases:
main.plugin = main.extend
export default main
+94
View File
@@ -0,0 +1,94 @@
import type { Spacetime, ParsableDate, TimezoneSet } from './types.js'
export interface SpacetimeConstructorOptions {
/** javascript dates use millisecond-epochs, instead of second-epochs, like some other languages. This is a common bug, and by default spacetime warns if you set an epoch within January 1970. to disable set to true */
silent?: boolean
/** the day number, between 0-6, that the week starts on. (Sunday is 0) */
weekStart?: number
/** pass true to change parsing behaviour to dd/mm/yyyy. By default American interpretation will be used. */
dmy?: boolean
}
export interface SpacetimeConstructor {
/**
* @param epoch Timestamp in **milliseconds**. If you are getting a date in 1970, you are likely using seconds.
* @param timezone Optional timezone. If omitted uses the browser timezone.
* @param options Options for silencing warnings.
*/
(epoch: number, timezone?: string, options?: SpacetimeConstructorOptions): Spacetime
/**
* @param arr Date values in an array such as [yyyy, m, d].
*
* ```typescript
* let d = spacetime([2011, 1, 15]);
* d.format('nice-year'); // "Feb 15th, 2011"
* ```
* @param timezone Optional timezone. If omitted uses the browser timezone.
* @param options Options for silencing warnings.
*/
(arr: Array<number>, timezone?: string, options?: SpacetimeConstructorOptions): Spacetime
/**
* @param obj Date as a key-value object. ex {month:'june', year:2019}
* @param timezone Optional timezone. If omitted uses the browser timezone.
* @param options Options for silencing warnings.
*/
(
obj: { [unit: string]: string | number },
timezone?: string,
options?: SpacetimeConstructorOptions
): Spacetime
/**
* @param iso Date as an iso string. ex '2017-04-03T08:00:00'
* @param timezone Optional timezone. If omitted uses the browser timezone.
* @param options Options for silencing warnings.
*/
(iso: string, timezone?: string, options?: SpacetimeConstructorOptions): Spacetime
/**
* @param parsableDate a parsable date like object
* @param timezone Optional timezone. If omitted uses the browser timezone.
* @param options Options for silencing warnings.
*/
(
parsableDate?: ParsableDate | null,
timezone?: string,
options?: SpacetimeConstructorOptions
): Spacetime
}
export interface SpacetimeStatic extends SpacetimeConstructor {
/** set as the current time */
now: (timezone?: string, options?: SpacetimeConstructorOptions) => Spacetime
/** set as this morning */
today: (timezone?: string, options?: SpacetimeConstructorOptions) => Spacetime
/** set as tomorrow morning */
tomorrow: (timezone?: string, options?: SpacetimeConstructorOptions) => Spacetime
/** set as yesterday morning */
yesterday: (timezone?: string, options?: SpacetimeConstructorOptions) => Spacetime
/** set epoch using seconds instead of milliseconds */
fromUnixSeconds: (seconds: number, timezone?: string, options?: SpacetimeConstructorOptions) => Spacetime
/** Extend Spacetime with a custom function/object. */
extend: (extension: { [key: string]: any } | {}) => SpacetimeStatic
/** get a list of current timezones and their offsets */
timezones: () => TimezoneSet
/** list timezones by their time */
whereIts: (a: string, b?: string) => string[]
/** set as earliest-possible date */
min: (timezone?: string, options?: SpacetimeConstructorOptions) => Spacetime
/** set as furthest-possible future date */
max: (timezone?: string, options?: SpacetimeConstructorOptions) => Spacetime
}
+88
View File
@@ -0,0 +1,88 @@
export default {
"9|s": "2/dili,2/jayapura",
"9|n": "2/chita,2/khandyga,2/pyongyang,2/seoul,2/tokyo,2/yakutsk,11/palau,japan,rok",
"9.5|s|04/05:03->10/04:02": "4/adelaide,4/broken_hill,4/south,4/yancowinna",
"9.5|s": "4/darwin,4/north",
"8|s": "12/casey,2/makassar,4/perth,2/ujung_pandang,4/west",
"8|n": "2/brunei,2/hong_kong,2/irkutsk,2/kuala_lumpur,2/kuching,2/macau,2/manila,2/shanghai,2/singapore,2/taipei,2/ulaanbaatar,2/chongqing,2/chungking,2/harbin,2/macao,2/ulan_bator,2/choibalsan,hongkong,prc,roc,singapore",
"8.75|s": "4/eucla",
"7|s": "12/davis,2/jakarta,2/pontianak,9/christmas",
"7|n": "2/bangkok,2/barnaul,2/hovd,2/krasnoyarsk,2/novokuznetsk,2/novosibirsk,2/phnom_penh,2/ho_chi_minh,2/tomsk,2/vientiane,2/saigon",
"6|s": "9/chagos",
"6|n": "2/bishkek,2/dhaka,2/omsk,2/thimphu,2/urumqi,2/dacca,2/kashgar,2/thimbu",
"6.5|s": "9/cocos",
"6.5|n": "2/yangon,2/rangoon",
"5|s": "12/mawson,12/vostok,9/kerguelen",
"5|n": "2/almaty,2/aqtau,2/aqtobe,2/ashgabat,2/atyrau,2/dushanbe,2/karachi,2/oral,2/qyzylorda,2/qostanay,2/samarkand,2/tashkent,2/yekaterinburg,9/maldives,2/ashkhabad",
"5.75|n": "2/kathmandu,2/katmandu",
"5.5|n": "2/kolkata,2/colombo,2/calcutta",
"4|s": "9/mahe,9/mauritius,9/reunion",
"4|n": "2/baku,2/dubai,2/muscat,2/tbilisi,2/yerevan,8/astrakhan,8/samara,8/saratov,8/ulyanovsk",
"4.5|n": "2/kabul",
"3|s": "0/dar_es_salaam,0/nairobi,12/syowa,9/antananarivo,9/comoro,9/mayotte",
"3|n|04/24:00->10/29:24": "0/cairo,egypt",
"3|n|03/29:03->10/25:04": "2/famagusta,2/nicosia,8/athens,8/bucharest,8/chisinau,8/helsinki,8/kyiv,8/mariehamn,8/riga,8/sofia,8/tallinn,8/uzhgorod,8/vilnius,8/zaporozhye,8/nicosia,8/tiraspol,8/kiev,eet",
"3|n|03/29:00->10/24:24": "2/beirut",
"3|n|03/28:02->10/24:02": "2/gaza,2/hebron",
"3|n|03/27:02->10/25:02": "2/jerusalem,2/tel_aviv,israel",
"3|n": "0/addis_ababa,0/asmara,0/asmera,0/djibouti,0/kampala,0/mogadishu,2/aden,2/amman,2/baghdad,2/bahrain,2/damascus,2/kuwait,2/qatar,2/riyadh,8/istanbul,8/kirov,8/minsk,8/moscow,8/simferopol,8/volgograd,2/volgograd,2/istanbul,turkey,w-su",
"3.5|n": "2/tehran,iran",
"2|s": "0/blantyre,0/bujumbura,0/gaborone,0/harare,0/johannesburg,0/kigali,0/lubumbashi,0/lusaka,0/maputo,0/maseru,0/mbabane,0/windhoek",
"2|n|03/29:02->10/25:03": "0/ceuta,arctic/longyearbyen,8/amsterdam,8/andorra,8/belgrade,8/berlin,8/bratislava,8/brussels,8/budapest,8/busingen,8/copenhagen,8/gibraltar,8/ljubljana,8/luxembourg,8/madrid,8/malta,8/monaco,8/oslo,8/paris,8/podgorica,8/prague,8/rome,8/san_marino,8/sarajevo,8/skopje,8/stockholm,8/tirane,8/vaduz,8/vatican,8/vienna,8/warsaw,8/zagreb,8/zurich,3/jan_mayen,poland,cet,met",
"2|n|03/29:01->10/25:03": "12/troll",
"2|n": "0/juba,0/khartoum,0/tripoli,8/kaliningrad,libya",
"1|s": "0/brazzaville,0/kinshasa,0/luanda",
"1|n|03/29:01->10/25:02": "3/canary,3/faroe,3/madeira,8/dublin,8/guernsey,8/isle_of_man,8/jersey,8/lisbon,8/london,3/faeroe,eire,8/belfast,gb-eire,gb,portugal,wet",
"1|n": "0/algiers,0/bangui,0/douala,0/lagos,0/libreville,0/malabo,0/ndjamena,0/niamey,0/porto-novo,0/tunis",
"14|n": "11/kiritimati",
"13|s": "11/apia,11/enderbury,11/kanton,11/fakaofo,11/tongatapu",
"12|s|04/05:03->09/27:02": "12/mcmurdo,11/auckland,12/south_pole,nz",
"12|s": "11/fiji,11/funafuti,11/nauru,11/wallis",
"12|n": "2/anadyr,2/kamchatka,11/kwajalein,11/majuro,11/tarawa,11/wake,kwajalein",
"12.75|s|04/05:03:45->09/27:02:45": "11/chatham,nz-chat",
"11|s|04/05:03->10/04:02": "11/norfolk",
"11|s": "11/bougainville,11/efate,11/guadalcanal,11/noumea",
"11|n": "2/magadan,2/sakhalin,2/srednekolymsk,11/kosrae,11/pohnpei,11/ponape",
"10|s|04/05:03->10/04:02": "12/macquarie,4/currie,4/hobart,4/melbourne,4/sydney,4/act,4/canberra,4/nsw,4/tasmania,4/victoria",
"10|s": "12/dumontdurville,4/brisbane,4/lindeman,11/port_moresby,4/queensland",
"10|n": "2/ust-nera,2/vladivostok,11/guam,11/saipan,11/chuuk,11/truk,11/yap",
"10.5|s|04/05:02->10/04:02": "4/lord_howe,4/lhi",
"0|s|02/15:03->09/20:02": "0/casablanca",
"0|s|02/15:03->03/22:02": "0/el_aaiun",
"0|s": "3/st_helena",
"0|n|03/29:00->10/25:01": "3/azores",
"0|n": "0/abidjan,0/accra,0/bamako,0/banjul,0/bissau,0/conakry,0/dakar,0/freetown,0/lome,0/monrovia,0/nouakchott,0/ouagadougou,0/sao_tome,1/danmarkshavn,3/reykjavik,13/gmt,13/utc,0/timbuktu,13/greenwich,13/uct,13/universal,13/zulu,gmt-0,gmt+0,gmt0,greenwich,iceland,uct,universal,utc,zulu,13/unknown,factory",
"-9|s": "11/gambier",
"-9|n|03/08:02->11/01:02": "1/adak,1/atka,us/aleutian",
"-9.5|s": "11/marquesas",
"-8|s": "11/pitcairn",
"-8|n|03/08:02->11/01:02": "1/anchorage,1/juneau,1/metlakatla,1/nome,1/sitka,1/yakutat,us/alaska",
"-7|n|03/08:02->12/31:23": "1/vancouver,6/pacific",
"-7|n|03/08:02->11/01:02": "1/los_angeles,1/santa_isabel,1/tijuana,1/ensenada,10/bajanorte,us/pacific-new,us/pacific,pst8pdt",
"-7|n": "1/creston,1/dawson,1/dawson_creek,1/fort_nelson,1/hermosillo,1/mazatlan,1/phoenix,1/whitehorse,6/yukon,10/bajasur,us/arizona,mst",
"-6|s|04/04:22->09/05:22": "11/easter,7/easterisland",
"-6|s": "11/galapagos",
"-6|n|03/08:02->12/31:23": "1/edmonton,1/yellowknife,6/mountain",
"-6|n|03/08:02->11/01:02": "1/boise,1/cambridge_bay,1/denver,1/inuvik,1/ciudad_juarez,1/shiprock,navajo,us/mountain,mst7mdt",
"-6|n": "1/bahia_banderas,1/belize,1/chihuahua,1/costa_rica,1/el_salvador,1/guatemala,1/managua,1/merida,1/mexico_city,1/monterrey,1/regina,1/swift_current,1/tegucigalpa,6/east-saskatchewan,6/saskatchewan,10/general",
"-5|s": "1/eirunepe,1/guayaquil,1/lima,1/rio_branco,1/porto_acre,5/acre",
"-5|n|03/08:02->11/01:02": "1/chicago,1/matamoros,1/menominee,1/north_dakota,1/ojinaga,1/rainy_river,1/rankin_inlet,1/resolute,1/winnipeg,1/indiana/knox,1/indiana/tell_city,1/north_dakota/beulah,1/north_dakota/center,1/north_dakota/new_salem,1/knox_in,6/central,us/central,us/indiana-starke,cst6cdt",
"-5|n": "1/bogota,1/cancun,1/cayman,1/coral_harbour,1/jamaica,1/panama,1/atikokan,jamaica,est",
"-4|s|04/04:24->09/06:00": "1/santiago,7/continental",
"-4|s": "1/campo_grande,1/cuiaba,1/la_paz,1/manaus,1/porto_velho,5/west",
"-4|n|03/08:02->11/01:02": "1/detroit,1/grand_turk,1/indiana,1/indianapolis,1/iqaluit,1/kentucky,1/louisville,1/montreal,1/nassau,1/new_york,1/nipigon,1/pangnirtung,1/port-au-prince,1/thunder_bay,1/toronto,1/indiana/marengo,1/indiana/petersburg,1/indiana/vevay,1/indiana/vincennes,1/indiana/winamac,1/kentucky/monticello,1/fort_wayne,1/indiana/indianapolis,1/kentucky/louisville,6/eastern,us/east-indiana,us/eastern,us/michigan,est5edt",
"-4|n|03/08:00->11/01:01": "1/havana,cuba",
"-4|n": "1/anguilla,1/antigua,1/aruba,1/barbados,1/blanc-sablon,1/boa_vista,1/caracas,1/curacao,1/dominica,1/grenada,1/guadeloupe,1/guyana,1/kralendijk,1/lower_princes,1/marigot,1/martinique,1/montserrat,1/port_of_spain,1/puerto_rico,1/santo_domingo,1/st_barthelemy,1/st_kitts,1/st_lucia,1/st_thomas,1/st_vincent,1/tortola,1/virgin",
"-3|s": "1/araguaina,1/argentina,1/asuncion,1/bahia,1/belem,1/buenos_aires,1/catamarca,1/cordoba,1/coyhaique,1/fortaleza,1/jujuy,1/maceio,1/mendoza,1/montevideo,1/punta_arenas,1/recife,1/santarem,1/sao_paulo,12/palmer,12/rothera,3/stanley,1/argentina/la_rioja,1/argentina/rio_gallegos,1/argentina/salta,1/argentina/san_juan,1/argentina/san_luis,1/argentina/tucuman,1/argentina/ushuaia,1/argentina/comodrivadavia,1/argentina/buenos_aires,1/argentina/catamarca,1/argentina/cordoba,1/argentina/jujuy,1/argentina/mendoza,1/argentina/rosario,1/rosario,5/east",
"-3|n|03/08:02->11/01:02": "1/glace_bay,1/goose_bay,1/halifax,1/moncton,1/thule,3/bermuda,6/atlantic",
"-3|n": "1/cayenne,1/paramaribo",
"-2|s": "1/noronha,3/south_georgia,5/denoronha",
"-2|n|03/08:02->11/01:02": "1/miquelon",
"-2.5|n|03/08:02->11/01:02": "1/st_johns,6/newfoundland",
"-1|n|03/28:23->10/24:24": "1/nuuk,1/scoresbysund,1/godthab",
"-1|n": "3/cape_verde",
"-11|s": "11/niue,11/pago_pago,11/samoa,us/samoa",
"-11|n": "11/midway",
"-10|s": "11/rarotonga,11/tahiti",
"-10|n": "11/honolulu,11/johnston,us/hawaii,hst"
}
+1897
View File
File diff suppressed because it is too large. Load diff
+47
View File
@@ -0,0 +1,47 @@
//turn our timezone data into a small-as-possible string
import { writeFileSync } from 'node:fs'
import iana from './iana.js'
import aliases from './aliases.js'
import prefixes from './_prefixes.js'
const all = {}
// add aliases in
Object.keys(aliases).forEach((k) => {
const found = iana[aliases[k]]
if (!found) {
console.log('missing', aliases[k]) //eslint-disable-line
}
iana[k] = Object.assign({}, found)
})
//pack iana data into a [o|h] object
Object.keys(iana).forEach((k) => {
const o = iana[k]
let key = o.offset + '|' + o.hem
if (o.dst) {
key += '|' + o.dst
}
all[key] = all[key] || []
const name = k.replace(/(.*?)\//, (a, prefix) => {
const index = prefixes.indexOf(prefix)
if (index !== -1) {
return index + '/'
}
return a
})
all[key].push(name)
})
//add-in informal abbreviations
// all = addHemisphere(all, informal.south, 's')
// all = addHemisphere(all, informal.north, 'n')
let keys = Object.keys(all)
keys = keys.sort((a, b) => (a < b ? 1 : -1))
const result = {}
keys.forEach((k) => {
result[k] = all[k].join(',')
})
// console.log(result)
writeFileSync('./zonefile/_build.js', 'export default ' + JSON.stringify(result, null, 2))