import angular from 'angular' import _ from 'lodash' import { DateTime } from 'luxon' angular.module('app').factory('dateTimeZoneFactory', function dateTimeZoneFactory() { const timeZones = [ { value: -12, zone: 'IDLW - Internation Date Line West', display: 'IDLW' }, { value: -11, zone: 'SST - Samoa Standard Time', display: 'SST' }, { value: -10, zone: 'HST - Hawaiian Standard Time', display: 'HST' }, { value: -9, zone: 'AKST - Alaska Standard Time', display: 'AKST' }, { value: -8, zone: 'PT - Pacific Time', display: 'PT' }, { value: -7, zone: 'MT - Mountain Time', display: 'MT' }, { value: -6, zone: 'CT - Central Time', display: 'CT' }, { value: -5, zone: 'ET - Eastern Time', display: 'ET' }, { value: -4, zone: 'AST - Atlantic Standard Time', display: 'AST' }, { value: -3.5, zone: 'NST - Newfoundland Standard Time', display: 'NST' }, { value: -3, zone: 'BRA - Brazil Standard Time', display: 'BRA' }, { value: -2, zone: 'FDT - Fernando de Noronha Standard Time (Brazil)', display: 'FDT' }, { value: -1, zone: 'CVT - Cape Verde Time', display: 'CVT' }, { value: 0, zone: 'GMT - Greenwich Mean Time', display: 'GMT' }, { value: 1, zone: 'CET - Central Europe Time (Madrid, Paris)', display: 'CET' }, { value: 2, zone: 'EET - Eastern European Time (South Africa)', display: 'EET' }, { value: 3, zone: 'EAT - East Africa Time', display: 'EAT' }, { value: 3.5, zone: 'IRST - Iran Standard Time', display: 'IRST' }, { value: 4, zone: 'MSK - Moscow Time', display: 'MSK' }, { value: 4.5, zone: 'AFT - Afghanistan Time', display: 'AFT' }, { value: 5, zone: 'PKT - Pakistan Standard Time', display: 'PKT' }, { value: 5.5, zone: 'IST - India Standard Time', display: 'IST' }, { value: 5.75, zone: 'NPT - Nepal Time', display: 'NPT' }, { value: 6, zone: 'BST - Bangladesh Standard Time', display: 'BST' }, { value: 7, zone: 'ICT - Indochina Time (Bangkok, Hanoi)', display: 'ICT' }, { value: 8, zone: 'HKT - China Standard Time (Beijing, Hong Kong)', display: 'HKT' }, { value: 9, zone: 'JST - Japan Standard Time', display: 'JST' }, { value: 9.5, zone: 'ACST - Australian Central Standard Time', display: 'ACST' }, { value: 10, zone: 'AEST - Australian Eastern Standard Time', display: 'AEST' }, { value: 11, zone: 'SBT - Solomon Islands Time', display: 'SBT' }, { value: 12, zone: 'NZST - New Zealand Standard Time', display: 'NZST' } ] // using string validate on the datepicker gives us more control with luxon's parsing const validDateFormats = [ // Full month name formats (MMMM) 'd-MMMM-yyyy', 'd-MM-yyyy', 'd-M-yyyy', 'MMMM-d-yyyy', 'MM-d-yyyy', 'M-d-yyyy', 'd/MMMM/yyyy', 'd/MM/yyyy', 'd/M/yyyy', 'MMMM/d/yyyy', 'MM/d/yyyy', 'M/d/yyyy', 'd.MMMM.yyyy', 'd.MM.yyyy', 'd.M.yyyy', 'MMMM.d.yyyy', 'MM.d.yyyy', 'M.d.yyyy', 'd-MMMM-yy', 'd-MM-yy', 'd-M-yy', 'MMMM-d-yy', 'MM-d-yy', 'M-d-yy', 'd/MMMM/yy', 'd/MM/yy', 'd/M/yy', 'MMMM/d/yy', 'MM/d/yy', 'M/d/yy', 'd.MMMM.yy', 'd.MM.yy', 'd.M.yy', 'MMMM.d.yy', 'MM.d.yy', 'M.d.yy', // Abbreviated month name formats (MMM) 'd-MMM-yyyy', 'MMM-d-yyyy', 'd/MMM/yyyy', 'MMM/d/yyyy', 'd.MMM.yyyy', 'MMM.d.yyyy', 'd-MMM-yy', 'MMM-d-yy', 'd/MMM/yy', 'MMM/d/yy', 'd.MMM.yy', 'MMM.d.yy' ] return { timeZones, validDateFormats, getTimeZone(dateTime) { if (dateTime && dateTime.isValid) { // Get the timezone offset in hours and adjust the sign let zoneOffset = dateTime.offset / 60 // consider a shift for DST // create a fresh DateTime to check if DST is in effect const isDST = DateTime.fromISO(dateTime.toISO()).isInDST // at this point zoneOffset is our true offset from UTC 0 // so for example if we are UTC -6 AND we are DST, then our dateTime is really "Mountain Time" which is -7 // during the winter but is -6 during DST -- if we want to consistently show the label 'MST' for this date // we need to select -7 although the offset is -6 (or subtracting 1 from our actual utc output) zoneOffset = (isDST) ? zoneOffset - 1 : zoneOffset // NOTE: The above DST adjustment is somewhat arbitrary. // isDST() cannot be globally accurate as it works purely off a date and an offset. // No actual timezone information is used except for assumptions made from the users current locale. // Recommendation to switch to luxon's timezone handling in the future. return this.getTimeZoneByOffset(zoneOffset) } return null }, getTimeZoneByOffset(offset) { return _.find(timeZones, { value: offset }) } } })