diff --git a/scripts/parse-iana-timezones.js b/scripts/parse-iana-timezones.js deleted file mode 100644 index e2b35885c..000000000 --- a/scripts/parse-iana-timezones.js +++ /dev/null @@ -1,189 +0,0 @@ -const fs = require('fs'); -const chalk = require('chalk'); -const path = require('path'); - -/** - * Prints error, since source file was not provided - */ -const sourceFileNotProvided = () => ` -${chalk.bold.red(`You didn't provide source file!`)} - -You need to run the script with source file: -${chalk.cyan.bold('yarn run timezones source-file.json')} - -You could find applicable IANA timezone source file in json format from moment-timezone repository: -${chalk.underline( - 'https://raw.githubusercontent.com/moment/moment-timezone/develop/data/unpacked/latest.json' -)} - -`; - -/** - * Prints error, since source file did not exist. - * - * @param pathToFile source file. - */ -const sourceFileMissing = pathToFile => ` -${chalk.bold.red(`The provided source file didn't exist!`)} - -Did you mistype the name of the source file: -${chalk.cyan.bold(pathToFile)} - -`; - -/** - * Prints error, since source file contained unknown JSON structure. - */ -const sourceFileHasUnknownStructure = () => ` -${chalk.bold.red(`The provided source file has unknown structure!`)} - -The file should contain IANA timezone data in JSON format: -{ - "version": "2019b", - "zones": [ - { - "name": "Africa/Abidjan", - //... - } - //... - ], - "links": [] -} -`; - -/** - * Generate the content for exported '.js' file. - * - * @param stringifiedZoneNames an array of timezone keys to be exported. - * Use JSON.stringify to generate this string. - * @param relevantZonesPattern RexExp pattern to make it explicit that we are filtering - * IANA database instead of exposing all the keys. - */ -const targetFileContent = (stringifiedZoneNames, relevantZonesPattern) => - `// This file is generated with script: -// yarn run timezones ./iana-2019b.json -// -// Note: iana-2019b.json file is downloaded from moment-timezone Github repository: -// https://github.com/moment/moment-timezone/tree/develop/data/unpacked -// -// Timezones are picked with RegExp: -// ${relevantZonesPattern.toString()} -// -// You could find the latest IANA timezone source file (in JSON format) -// from moment-timezone Github repository: -// https://raw.githubusercontent.com/moment/moment-timezone/develop/data/unpacked/latest.json - -const ianaTimezoneKeys = ${stringifiedZoneNames} - -export default ianaTimezoneKeys; -`; - -/** - * Prints path to saved export containing IANA timezone keys. - * - * @param pathToFile export file. - */ -const targetFileSaved = pathToFile => ` -IANA timezone keys are saved to file: -${chalk.cyan.bold(pathToFile)} - -You should move this file to the component directory: FieldTimeZoneInput - and use it there. - -`; - -/** - * Reads a file with JSON content and returns it. - * We expect that the provided file exists and can be parsed to JSON. - * - * @param sourceFile JSON file to be read. - */ -const readFileToJSON = sourceFile => { - const rawdata = fs.readFileSync(sourceFile); - return JSON.parse(rawdata); -}; - -/** - * Creates target file name for the generated file. - * a JS object. - * - * @param fileName - * @param revision the current revision of the exported file. - */ -const targetFileName = (fileName, revision = 0) => { - const fileNameWithoutExtension = fileName - .split('.') - .slice(0, -1) - .join('.'); - - const defaultExportFileName = `${fileNameWithoutExtension}-keys.js`; - const exportFileExists = fs.existsSync(path.resolve(process.cwd(), defaultExportFileName)); - - if (exportFileExists) { - const newRevision = revision + 1; - const exportFileNameWithRevision = `${fileNameWithoutExtension}-keys_(${newRevision}).js`; - const revisionedExportFileExists = fs.existsSync( - path.resolve(process.cwd(), exportFileNameWithRevision) - ); - - return revisionedExportFileExists - ? targetFileName(fileName, newRevision) - : exportFileNameWithRevision; - } else { - return defaultExportFileName; - } -}; - -/** - * Exit program with error message - * - * @param message Error message to be printed to console. - */ -const exitWithErrorMessage = message => { - process.on('exit', code => { - console.log(message); - }); - process.exit(1); -}; - -const run = () => { - const fileName = process.argv[2]; - - if (fileName) { - const pathToFile = path.resolve(process.cwd(), fileName); - - if (!fs.existsSync(pathToFile)) { - exitWithErrorMessage(sourceFileMissing(pathToFile)); - } else { - const source = readFileToJSON(pathToFile); - const zones = source.zones; - - if (!zones) { - exitWithErrorMessage(sourceFileHasUnknownStructure()); - } - - const relevantZonesPattern = new RegExp( - '^(Africa|America|Antarctica|Asia|Atlantic|Australia|Europe|Indian|Pacific)' - ); - const zoneNames = source.zones.map(z => z.name).filter(z => relevantZonesPattern.test(z)); - - const stringifiedZoneNames = JSON.stringify(zoneNames, null, 2); - const [cleanFileName] = fileName.split('/').slice(-1); - const pathToExport = path.resolve(process.cwd(), targetFileName(cleanFileName)); - - fs.writeFile( - pathToExport, - targetFileContent(stringifiedZoneNames, relevantZonesPattern), - error => { - if (error) { - return console.error(error); - } - console.log(targetFileSaved(pathToExport)); - } - ); - } - } else { - exitWithErrorMessage(sourceFileNotProvided()); - } -}; - -run(); diff --git a/src/components/FieldTimeZoneSelect/FieldTimeZoneSelect.js b/src/components/FieldTimeZoneSelect/FieldTimeZoneSelect.js index acb28c2cb..a87518ff2 100644 --- a/src/components/FieldTimeZoneSelect/FieldTimeZoneSelect.js +++ b/src/components/FieldTimeZoneSelect/FieldTimeZoneSelect.js @@ -1,20 +1,20 @@ import React from 'react'; -import { array, string } from 'prop-types'; +import { string } from 'prop-types'; +import { getTimeZoneNames } from '../../util/dates'; import { FieldSelect } from '../../components'; -// You can update timezone keys if needed by running timezone script (aka parse-iana-timezones.js). -// We have a script that can generate keys from moment-timezone data format -// https://github.com/moment/moment-timezone/tree/develop/data/unpacked -// Check the instructions from generated file: iana-2019b-keys.js -import timezones from './iana-2019b-keys.js'; - const FieldTimeZoneSelect = props => { + // IANA database contains irrelevant time zones too. + const relevantZonesPattern = new RegExp( + '^(Africa|America|Antarctica|Asia|Atlantic|Australia|Europe|Indian|Pacific)' + ); + return ( - {timezones.map(tz => ( + {getTimeZoneNames(relevantZonesPattern).map(tz => ( @@ -28,7 +28,6 @@ FieldTimeZoneSelect.defaultProps = { className: null, id: null, label: null, - timezones: timezones, }; FieldTimeZoneSelect.propTypes = { @@ -40,8 +39,6 @@ FieldTimeZoneSelect.propTypes = { id: string, label: string, name: string.isRequired, - - timezones: array, }; export default FieldTimeZoneSelect; diff --git a/src/components/FieldTimeZoneSelect/iana-2019b-keys.js b/src/components/FieldTimeZoneSelect/iana-2019b-keys.js deleted file mode 100644 index ef2242c25..000000000 --- a/src/components/FieldTimeZoneSelect/iana-2019b-keys.js +++ /dev/null @@ -1,500 +0,0 @@ -// This file is generated with script: -// yarn run timezones ./iana-2019b.json -// -// Note: iana-2019b.json file is downloaded from moment-timezone Github repository: -// https://github.com/moment/moment-timezone/tree/develop/data/unpacked -// -// Timezones are picked with RegExp: -// /^(Africa|America|Antarctica|Asia|Atlantic|Australia|Europe|Indian|Pacific)/ -// -// You could find the latest IANA timezone source file (in JSON format) -// from moment-timezone Github repository: -// https://raw.githubusercontent.com/moment/moment-timezone/develop/data/unpacked/latest.json - -const ianaTimezoneKeys = [ - 'Africa/Abidjan', - 'Africa/Accra', - 'Africa/Addis_Ababa', - 'Africa/Algiers', - 'Africa/Asmara', - 'Africa/Asmera', - 'Africa/Bamako', - 'Africa/Bangui', - 'Africa/Banjul', - 'Africa/Bissau', - 'Africa/Blantyre', - 'Africa/Brazzaville', - 'Africa/Bujumbura', - 'Africa/Cairo', - 'Africa/Casablanca', - 'Africa/Ceuta', - 'Africa/Conakry', - 'Africa/Dakar', - 'Africa/Dar_es_Salaam', - 'Africa/Djibouti', - 'Africa/Douala', - 'Africa/El_Aaiun', - 'Africa/Freetown', - 'Africa/Gaborone', - 'Africa/Harare', - 'Africa/Johannesburg', - 'Africa/Juba', - 'Africa/Kampala', - 'Africa/Khartoum', - 'Africa/Kigali', - 'Africa/Kinshasa', - 'Africa/Lagos', - 'Africa/Libreville', - 'Africa/Lome', - 'Africa/Luanda', - 'Africa/Lubumbashi', - 'Africa/Lusaka', - 'Africa/Malabo', - 'Africa/Maputo', - 'Africa/Maseru', - 'Africa/Mbabane', - 'Africa/Mogadishu', - 'Africa/Monrovia', - 'Africa/Nairobi', - 'Africa/Ndjamena', - 'Africa/Niamey', - 'Africa/Nouakchott', - 'Africa/Ouagadougou', - 'Africa/Porto-Novo', - 'Africa/Sao_Tome', - 'Africa/Timbuktu', - 'Africa/Tripoli', - 'Africa/Tunis', - 'Africa/Windhoek', - 'America/Adak', - 'America/Anchorage', - 'America/Anguilla', - 'America/Antigua', - 'America/Araguaina', - 'America/Argentina/Buenos_Aires', - 'America/Argentina/Catamarca', - 'America/Argentina/ComodRivadavia', - 'America/Argentina/Cordoba', - 'America/Argentina/Jujuy', - 'America/Argentina/La_Rioja', - 'America/Argentina/Mendoza', - 'America/Argentina/Rio_Gallegos', - 'America/Argentina/Salta', - 'America/Argentina/San_Juan', - 'America/Argentina/San_Luis', - 'America/Argentina/Tucuman', - 'America/Argentina/Ushuaia', - 'America/Aruba', - 'America/Asuncion', - 'America/Atikokan', - 'America/Atka', - 'America/Bahia_Banderas', - 'America/Bahia', - 'America/Barbados', - 'America/Belem', - 'America/Belize', - 'America/Blanc-Sablon', - 'America/Boa_Vista', - 'America/Bogota', - 'America/Boise', - 'America/Buenos_Aires', - 'America/Cambridge_Bay', - 'America/Campo_Grande', - 'America/Cancun', - 'America/Caracas', - 'America/Catamarca', - 'America/Cayenne', - 'America/Cayman', - 'America/Chicago', - 'America/Chihuahua', - 'America/Coral_Harbour', - 'America/Cordoba', - 'America/Costa_Rica', - 'America/Creston', - 'America/Cuiaba', - 'America/Curacao', - 'America/Danmarkshavn', - 'America/Dawson_Creek', - 'America/Dawson', - 'America/Denver', - 'America/Detroit', - 'America/Dominica', - 'America/Edmonton', - 'America/Eirunepe', - 'America/El_Salvador', - 'America/Ensenada', - 'America/Fort_Nelson', - 'America/Fort_Wayne', - 'America/Fortaleza', - 'America/Glace_Bay', - 'America/Godthab', - 'America/Goose_Bay', - 'America/Grand_Turk', - 'America/Grenada', - 'America/Guadeloupe', - 'America/Guatemala', - 'America/Guayaquil', - 'America/Guyana', - 'America/Halifax', - 'America/Havana', - 'America/Hermosillo', - 'America/Indiana/Indianapolis', - 'America/Indiana/Knox', - 'America/Indiana/Marengo', - 'America/Indiana/Petersburg', - 'America/Indiana/Tell_City', - 'America/Indiana/Vevay', - 'America/Indiana/Vincennes', - 'America/Indiana/Winamac', - 'America/Indianapolis', - 'America/Inuvik', - 'America/Iqaluit', - 'America/Jamaica', - 'America/Jujuy', - 'America/Juneau', - 'America/Kentucky/Louisville', - 'America/Kentucky/Monticello', - 'America/Knox_IN', - 'America/Kralendijk', - 'America/La_Paz', - 'America/Lima', - 'America/Los_Angeles', - 'America/Louisville', - 'America/Lower_Princes', - 'America/Maceio', - 'America/Managua', - 'America/Manaus', - 'America/Marigot', - 'America/Martinique', - 'America/Matamoros', - 'America/Mazatlan', - 'America/Mendoza', - 'America/Menominee', - 'America/Merida', - 'America/Metlakatla', - 'America/Mexico_City', - 'America/Miquelon', - 'America/Moncton', - 'America/Monterrey', - 'America/Montevideo', - 'America/Montreal', - 'America/Montserrat', - 'America/Nassau', - 'America/New_York', - 'America/Nipigon', - 'America/Nome', - 'America/Noronha', - 'America/North_Dakota/Beulah', - 'America/North_Dakota/Center', - 'America/North_Dakota/New_Salem', - 'America/Ojinaga', - 'America/Panama', - 'America/Pangnirtung', - 'America/Paramaribo', - 'America/Phoenix', - 'America/Port_of_Spain', - 'America/Port-au-Prince', - 'America/Porto_Acre', - 'America/Porto_Velho', - 'America/Puerto_Rico', - 'America/Punta_Arenas', - 'America/Rainy_River', - 'America/Rankin_Inlet', - 'America/Recife', - 'America/Regina', - 'America/Resolute', - 'America/Rio_Branco', - 'America/Rosario', - 'America/Santa_Isabel', - 'America/Santarem', - 'America/Santiago', - 'America/Santo_Domingo', - 'America/Sao_Paulo', - 'America/Scoresbysund', - 'America/Shiprock', - 'America/Sitka', - 'America/St_Barthelemy', - 'America/St_Johns', - 'America/St_Kitts', - 'America/St_Lucia', - 'America/St_Thomas', - 'America/St_Vincent', - 'America/Swift_Current', - 'America/Tegucigalpa', - 'America/Thule', - 'America/Thunder_Bay', - 'America/Tijuana', - 'America/Toronto', - 'America/Tortola', - 'America/Vancouver', - 'America/Virgin', - 'America/Whitehorse', - 'America/Winnipeg', - 'America/Yakutat', - 'America/Yellowknife', - 'Antarctica/Casey', - 'Antarctica/Davis', - 'Antarctica/DumontDUrville', - 'Antarctica/Macquarie', - 'Antarctica/Mawson', - 'Antarctica/McMurdo', - 'Antarctica/Palmer', - 'Antarctica/Rothera', - 'Antarctica/South_Pole', - 'Antarctica/Syowa', - 'Antarctica/Troll', - 'Antarctica/Vostok', - 'Asia/Aden', - 'Asia/Almaty', - 'Asia/Amman', - 'Asia/Anadyr', - 'Asia/Aqtau', - 'Asia/Aqtobe', - 'Asia/Ashgabat', - 'Asia/Ashkhabad', - 'Asia/Atyrau', - 'Asia/Baghdad', - 'Asia/Bahrain', - 'Asia/Baku', - 'Asia/Bangkok', - 'Asia/Barnaul', - 'Asia/Beirut', - 'Asia/Bishkek', - 'Asia/Brunei', - 'Asia/Calcutta', - 'Asia/Chita', - 'Asia/Choibalsan', - 'Asia/Chongqing', - 'Asia/Chungking', - 'Asia/Colombo', - 'Asia/Dacca', - 'Asia/Damascus', - 'Asia/Dhaka', - 'Asia/Dili', - 'Asia/Dubai', - 'Asia/Dushanbe', - 'Asia/Famagusta', - 'Asia/Gaza', - 'Asia/Harbin', - 'Asia/Hebron', - 'Asia/Ho_Chi_Minh', - 'Asia/Hong_Kong', - 'Asia/Hovd', - 'Asia/Irkutsk', - 'Asia/Istanbul', - 'Asia/Jakarta', - 'Asia/Jayapura', - 'Asia/Jerusalem', - 'Asia/Kabul', - 'Asia/Kamchatka', - 'Asia/Karachi', - 'Asia/Kashgar', - 'Asia/Kathmandu', - 'Asia/Katmandu', - 'Asia/Khandyga', - 'Asia/Kolkata', - 'Asia/Krasnoyarsk', - 'Asia/Kuala_Lumpur', - 'Asia/Kuching', - 'Asia/Kuwait', - 'Asia/Macao', - 'Asia/Macau', - 'Asia/Magadan', - 'Asia/Makassar', - 'Asia/Manila', - 'Asia/Muscat', - 'Asia/Nicosia', - 'Asia/Novokuznetsk', - 'Asia/Novosibirsk', - 'Asia/Omsk', - 'Asia/Oral', - 'Asia/Phnom_Penh', - 'Asia/Pontianak', - 'Asia/Pyongyang', - 'Asia/Qatar', - 'Asia/Qostanay', - 'Asia/Qyzylorda', - 'Asia/Rangoon', - 'Asia/Riyadh', - 'Asia/Saigon', - 'Asia/Sakhalin', - 'Asia/Samarkand', - 'Asia/Seoul', - 'Asia/Shanghai', - 'Asia/Singapore', - 'Asia/Srednekolymsk', - 'Asia/Taipei', - 'Asia/Tashkent', - 'Asia/Tbilisi', - 'Asia/Tehran', - 'Asia/Tel_Aviv', - 'Asia/Thimbu', - 'Asia/Thimphu', - 'Asia/Tokyo', - 'Asia/Tomsk', - 'Asia/Ujung_Pandang', - 'Asia/Ulaanbaatar', - 'Asia/Ulan_Bator', - 'Asia/Urumqi', - 'Asia/Ust-Nera', - 'Asia/Vientiane', - 'Asia/Vladivostok', - 'Asia/Yakutsk', - 'Asia/Yangon', - 'Asia/Yekaterinburg', - 'Asia/Yerevan', - 'Atlantic/Azores', - 'Atlantic/Bermuda', - 'Atlantic/Canary', - 'Atlantic/Cape_Verde', - 'Atlantic/Faeroe', - 'Atlantic/Faroe', - 'Atlantic/Jan_Mayen', - 'Atlantic/Madeira', - 'Atlantic/Reykjavik', - 'Atlantic/South_Georgia', - 'Atlantic/St_Helena', - 'Atlantic/Stanley', - 'Australia/ACT', - 'Australia/Adelaide', - 'Australia/Brisbane', - 'Australia/Broken_Hill', - 'Australia/Canberra', - 'Australia/Currie', - 'Australia/Darwin', - 'Australia/Eucla', - 'Australia/Hobart', - 'Australia/LHI', - 'Australia/Lindeman', - 'Australia/Lord_Howe', - 'Australia/Melbourne', - 'Australia/North', - 'Australia/NSW', - 'Australia/Perth', - 'Australia/Queensland', - 'Australia/South', - 'Australia/Sydney', - 'Australia/Tasmania', - 'Australia/Victoria', - 'Australia/West', - 'Australia/Yancowinna', - 'Europe/Amsterdam', - 'Europe/Andorra', - 'Europe/Astrakhan', - 'Europe/Athens', - 'Europe/Belfast', - 'Europe/Belgrade', - 'Europe/Berlin', - 'Europe/Bratislava', - 'Europe/Brussels', - 'Europe/Bucharest', - 'Europe/Budapest', - 'Europe/Busingen', - 'Europe/Chisinau', - 'Europe/Copenhagen', - 'Europe/Dublin', - 'Europe/Gibraltar', - 'Europe/Guernsey', - 'Europe/Helsinki', - 'Europe/Isle_of_Man', - 'Europe/Istanbul', - 'Europe/Jersey', - 'Europe/Kaliningrad', - 'Europe/Kiev', - 'Europe/Kirov', - 'Europe/Lisbon', - 'Europe/Ljubljana', - 'Europe/London', - 'Europe/Luxembourg', - 'Europe/Madrid', - 'Europe/Malta', - 'Europe/Mariehamn', - 'Europe/Minsk', - 'Europe/Monaco', - 'Europe/Moscow', - 'Europe/Nicosia', - 'Europe/Oslo', - 'Europe/Paris', - 'Europe/Podgorica', - 'Europe/Prague', - 'Europe/Riga', - 'Europe/Rome', - 'Europe/Samara', - 'Europe/San_Marino', - 'Europe/Sarajevo', - 'Europe/Saratov', - 'Europe/Simferopol', - 'Europe/Skopje', - 'Europe/Sofia', - 'Europe/Stockholm', - 'Europe/Tallinn', - 'Europe/Tirane', - 'Europe/Tiraspol', - 'Europe/Ulyanovsk', - 'Europe/Uzhgorod', - 'Europe/Vaduz', - 'Europe/Vatican', - 'Europe/Vienna', - 'Europe/Vilnius', - 'Europe/Volgograd', - 'Europe/Warsaw', - 'Europe/Zagreb', - 'Europe/Zaporozhye', - 'Europe/Zurich', - 'Indian/Antananarivo', - 'Indian/Chagos', - 'Indian/Christmas', - 'Indian/Cocos', - 'Indian/Comoro', - 'Indian/Kerguelen', - 'Indian/Mahe', - 'Indian/Maldives', - 'Indian/Mauritius', - 'Indian/Mayotte', - 'Indian/Reunion', - 'Pacific/Apia', - 'Pacific/Auckland', - 'Pacific/Bougainville', - 'Pacific/Chatham', - 'Pacific/Chuuk', - 'Pacific/Easter', - 'Pacific/Efate', - 'Pacific/Enderbury', - 'Pacific/Fakaofo', - 'Pacific/Fiji', - 'Pacific/Funafuti', - 'Pacific/Galapagos', - 'Pacific/Gambier', - 'Pacific/Guadalcanal', - 'Pacific/Guam', - 'Pacific/Honolulu', - 'Pacific/Johnston', - 'Pacific/Kiritimati', - 'Pacific/Kosrae', - 'Pacific/Kwajalein', - 'Pacific/Majuro', - 'Pacific/Marquesas', - 'Pacific/Midway', - 'Pacific/Nauru', - 'Pacific/Niue', - 'Pacific/Norfolk', - 'Pacific/Noumea', - 'Pacific/Pago_Pago', - 'Pacific/Palau', - 'Pacific/Pitcairn', - 'Pacific/Pohnpei', - 'Pacific/Ponape', - 'Pacific/Port_Moresby', - 'Pacific/Rarotonga', - 'Pacific/Saipan', - 'Pacific/Samoa', - 'Pacific/Tahiti', - 'Pacific/Tarawa', - 'Pacific/Tongatapu', - 'Pacific/Truk', - 'Pacific/Wake', - 'Pacific/Wallis', - 'Pacific/Yap', -]; - -export default ianaTimezoneKeys; diff --git a/src/util/dates.js b/src/util/dates.js index 2970a373c..0a7996564 100644 --- a/src/util/dates.js +++ b/src/util/dates.js @@ -90,6 +90,18 @@ export const isValidTimeZone = timeZone => { } }; +/** + * Return the names of the time zones according to IANA timezone db. + * + * @param {RegExp} relevantZonesRegExp is pattern to filter returned time zones. + * + * @returns {Array} an array of relevant time zones. + */ +export const getTimeZoneNames = relevantZonesRegExp => { + const allTimeZones = moment.tz.names(); + return relevantZonesRegExp ? allTimeZones.filter(z => relevantZonesRegExp.test(z)) : allTimeZones; +}; + /** * Format date instance to string and localized it to given time zone. * Default formatting shows date and hours and minutes in 24 hour format: