diff --git a/.gitignore b/.gitignore index d1ece36..1fcd342 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ ebin/ _build/ *~ +src/tz_index.erl +*.sw? +rebar3 diff --git a/Makefile b/Makefile index 6b97d11..152df64 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,26 @@ -all: include/tz_index.hrl +all: rebar3 ./rebar3 compile -check: +check: rebar3 ./rebar3 eunit -include/tz_index.hrl: src/ibuild.erl include/tz_database.hrl - cd include && ln -s ../src/ibuild.erl && escript ibuild.erl; EV=$$?; rm ibuild.erl; exit $$EV +test: check +dialyzer: rebar3 + ./rebar3 dialyzer + +publish: rebar3 + ./rebar3 hex publish + +rebar3: + @(echo "Building rebar3...") + @(rm -fr tmp) + @(mkdir -p tmp) + @(cd tmp && \ + git clone https://github.com/erlang/rebar3 && \ + cd rebar3 && \ + ./bootstrap) + @(echo "Moving rebar3 executable locally (NOT installing system-wide)") + @(mv tmp/rebar3/rebar3 .) + @(echo "Cleaning up rebar3 remnants") + @(rm -fr tmp) diff --git a/README.md b/README.md index 19144ca..6e69541 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,21 @@ ## NOTE -This is a fork of -[erlang_localtime](https://github.com/dmitryme/erlang_localtime), modified -specifically for compatibility with +This is a fork of the excellent library, +[erlang_localtime](https://github.com/dmitryme/erlang_localtime). The purpose +of this fork is specifically for compatibility with [qdate](https://github.com/choptastic/qdate). The two are mostly compatible, -but have diverged a bit over the years. The qdate tests will not pass if the -original erlang_localtime dependency is used due to some subtle differences to -attempt to make qdate a little bit smarter. +but have diverged slightly over the years. The qdate tests will not pass if the +original `erlang_localtime dependency` is used due to some subtle differences +to attempt to make qdate a little bit smarter. #### Public exports -* utc_to_local(DateTime, Timezone) - converts UTC time to local according to specified Timezone -* local_to_utc(DateTime, Timezone) - converts local time to UTC -* local_to_local(DateTime, TimezoneFrom, TimezoneTo) - converts local time to local -* tz_name(DateTime, Timezone) - returns a timezone name (E.g. MSK, MSD, etc) -* tz_shift(DateTime, Timezone) - returns time difference between local datetime and GMT -* tz_shift(DateTime, TimezoneFrom, TimezoneTo) - returns time difference between local datetime and required timezone +* `utc_to_local(DateTime, Timezone)` - converts UTC time to local according to specified Timezone +* `local_to_utc(DateTime, Timezone)` - converts local time to UTC +* `local_to_local(DateTime, TimezoneFrom, TimezoneTo)` - converts local time to local +* `tz_name(DateTime, Timezone)` - returns a timezone name (E.g. MSK, MSD, etc) +* `tz_shift(DateTime, Timezone)` - returns time difference between local datetime and GMT +* `tz_shift(DateTime, TimezoneFrom, TimezoneTo)` - returns time difference between local datetime and required timezone Where DateTime = {date(), time()} TimeZone(To, From) = String(). E.g. “Europe/Moscow”, “America/NewYork”. Or abbreviations "MSK", "MSD", etc. Note: diff --git a/include/tz_database.hrl b/include/tz_database.hrl index 155b4b6..bbde520 100644 --- a/include/tz_database.hrl +++ b/include/tz_database.hrl @@ -35,6 +35,7 @@ %% Discarded excess rules for Zone Africa/El_Aaiun. %% Moving rule to beginning of day for Zone America/Godthab. %% Moving rule to beginning of day for Zone America/Godthab. + %% Removed DST from Iran and Asia/Tehran {"Africa/Abidjan",{"GMT","GMT"},undef,0,0,undef,{0,0},undef,{0,0}}, {"Africa/Accra",{"GMT","GMT"},undef,0,0,undef,{0,0},undef,{0,0}}, @@ -346,7 +347,7 @@ {"Asia/Taipei",{"CST","CST"},undef,480,0,undef,{0,0},undef,{0,0}}, {"Asia/Tashkent",{"UZT","UZT"},undef,300,0,undef,{0,0},undef,{0,0}}, {"Asia/Tbilisi",{"GET","GET"},undef,240,0,undef,{0,0},undef,{0,0}}, - {"Asia/Tehran",{"IRST","IRST"},{"IRDT","IRDT"},210,60,undef,{0,0},undef,{0,0}}, + {"Asia/Tehran",{"IRST","IRST"},undef,210,0,undef,{0,0},undef,{0,0}}, {"Asia/Tel_Aviv",{"IST","IST"},{"IDT","IDT"},120,60,{4,fri,mar},{2,0},{last,sun,oct},{2,0}}, {"Asia/Thimbu",{"BTT","BTT"},undef,360,0,undef,{0,0},undef,{0,0}}, {"Asia/Thimphu",{"BTT","BTT"},undef,360,0,undef,{0,0},undef,{0,0}}, @@ -534,7 +535,7 @@ {"Indian/Mauritius",{"MUT","MUT"},undef,240,0,undef,{0,0},undef,{0,0}}, {"Indian/Mayotte",{"EAT","EAT"},undef,180,0,undef,{0,0},undef,{0,0}}, {"Indian/Reunion",{"RET","RET"},undef,240,0,undef,{0,0},undef,{0,0}}, - {"Iran",{"IRST","IRST"},{"IRDT","IRDT"},210,60,undef,{0,0},undef,{0,0}}, + {"Iran",{"IRST","IRST"},undef,210,0,undef,{0,0},undef,{0,0}}, {"Israel",{"IST","IST"},{"IDT","IDT"},120,60,{4,fri,mar},{2,0},{last,sun,oct},{2,0}}, {"Jamaica",{"EST","EST"},undef,-300,0,undef,{0,0},undef,{0,0}}, {"Japan",{"JST","JST"},undef,540,0,undef,{0,0},undef,{0,0}}, diff --git a/include/tz_index.hrl b/include/tz_index.hrl deleted file mode 100644 index 95bd35e..0000000 --- a/include/tz_index.hrl +++ /dev/null @@ -1,454 +0,0 @@ --define(tz_index, {dict,202,41,64,32,205,123, - {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}, - {{[["WGST","America/Godthab"],["GMT+2","Etc/GMT+2"]], - [["NPT","Asia/Kathmandu","Asia/Katmandu"], - ["ACWST","Australia/Eucla"], - ["CCT","Indian/Cocos"]], - [["DAVT","Antarctica/Davis"], - ["AZT","Asia/Baku"], - ["HKT","Asia/Hong_Kong","Hongkong"]], - [["MST","America/Boise","America/Cambridge_Bay", - "America/Chihuahua","America/Creston", - "America/Dawson_Creek","America/Denver", - "America/Edmonton","America/Fort_Nelson", - "America/Hermosillo","America/Inuvik", - "America/Mazatlan","America/Ojinaga", - "America/Phoenix","America/Shiprock", - "America/Yellowknife","Canada/Mountain","MST", - "MST7MDT","Mexico/BajaSur","Navajo","US/Arizona", - "US/Mountain"], - ["GMT-7","Etc/GMT-7"]], - [["ROTT","Antarctica/Rothera"], - ["GMT-13","Etc/GMT-13"], - ["GMT-4","Etc/GMT-4"], - ["GAMT","Pacific/Gambier"]], - [["SGT","Asia/Singapore","Singapore"], - ["GMT-1","Etc/GMT-1"], - ["GMT-10","Etc/GMT-10"]], - [["SAKT","Asia/Sakhalin"], - ["LHST","Australia/LHI","Australia/Lord_Howe"], - ["MSK","Europe/Minsk","Europe/Moscow", - "Europe/Simferopol","Europe/Volgograd","W-SU"], - ["PHOT","Pacific/Enderbury"], - ["PWT","Pacific/Palau"]], - [["HDT","America/Adak","America/Atka","US/Aleutian"], - ["AST","America/Anguilla","America/Antigua", - "America/Aruba","America/Barbados", - "America/Blanc-Sablon","America/Curacao", - "America/Dominica","America/Glace_Bay", - "America/Goose_Bay","America/Grand_Turk", - "America/Grenada","America/Guadeloupe", - "America/Halifax","America/Kralendijk", - "America/Lower_Princes","America/Marigot", - "America/Martinique","America/Moncton", - "America/Montserrat","America/Port_of_Spain", - "America/Puerto_Rico","America/Santo_Domingo", - "America/St_Barthelemy","America/St_Kitts", - "America/St_Lucia","America/St_Thomas", - "America/St_Vincent","America/Thule", - "America/Tortola","America/Virgin","Asia/Aden", - "Asia/Baghdad","Asia/Bahrain","Asia/Kuwait", - "Asia/Qatar","Asia/Riyadh","Atlantic/Bermuda", - "Canada/Atlantic"]], - [["NST","America/St_Johns","Canada/Newfoundland"], - ["YEKT","Asia/Yekaterinburg"]], - [["BDT","Asia/Dacca","Asia/Dhaka"], - ["GMT+7","Etc/GMT+7"], - ["CKT","Pacific/Rarotonga"]], - [["HST","America/Adak","America/Atka","HST", - "Pacific/Honolulu","Pacific/Johnston", - "US/Aleutian","US/Hawaii"], - ["PKT","Asia/Karachi"], - ["NOVT","Asia/Novosibirsk"], - ["GMT+4","Etc/GMT+4"], - ["MVT","Indian/Maldives"], - ["VUT","Pacific/Efate"], - ["LINT","Pacific/Kiritimati"]], - [["WAT","Africa/Bangui","Africa/Brazzaville", - "Africa/Douala","Africa/Kinshasa","Africa/Lagos", - "Africa/Libreville","Africa/Luanda", - "Africa/Malabo","Africa/Ndjamena","Africa/Niamey", - "Africa/Porto-Novo","Africa/Windhoek"], - ["ECT","America/Guayaquil"], - ["VOST","Antarctica/Vostok"], - ["BNT","Asia/Brunei"], - ["TLT","Asia/Dili"], - ["HOVST","Asia/Hovd"], - ["ACDT","Australia/Adelaide", - "Australia/Broken_Hill","Australia/South", - "Australia/Yancowinna"], - ["GMT+1","Etc/GMT+1"], - ["CHADT","NZ-CHAT","Pacific/Chatham"], - ["FJT","Pacific/Fiji"]], - [["EEST","Asia/Amman","Asia/Beirut","Asia/Damascus", - "Asia/Gaza","Asia/Hebron","Asia/Istanbul", - "Asia/Nicosia","EET","Europe/Athens", - "Europe/Bucharest","Europe/Chisinau", - "Europe/Helsinki","Europe/Istanbul","Europe/Kiev", - "Europe/Mariehamn","Europe/Nicosia","Europe/Riga", - "Europe/Sofia","Europe/Tallinn","Europe/Tiraspol", - "Europe/Uzhgorod","Europe/Vilnius", - "Europe/Zaporozhye","Turkey"], - ["IDT","Asia/Jerusalem","Asia/Tel_Aviv","Israel"], - ["BST","Europe/Belfast","Europe/Guernsey", - "Europe/Isle_of_Man","Europe/Jersey", - "Europe/London","GB","GB-Eire", - "Pacific/Bougainville"], - ["KOST","Pacific/Kosrae"], - ["WFT","Pacific/Wallis"]], - [["ALMT","Asia/Almaty"], - ["CHOT","Asia/Choibalsan"], - ["SRET","Asia/Srednekolymsk"], - ["AZOT","Atlantic/Azores"], - ["GMT-9","Etc/GMT-9"], - ["MET","MET"], - ["TVT","Pacific/Funafuti"]], - [["SAST","Africa/Johannesburg","Africa/Maseru", - "Africa/Mbabane"], - ["CDT","America/Bahia_Banderas","America/Chicago", - "America/Havana","America/Indiana/Knox", - "America/Indiana/Tell_City","America/Knox_IN", - "America/Matamoros","America/Menominee", - "America/Merida","America/Mexico_City", - "America/Monterrey","America/North_Dakota/Beulah", - "America/North_Dakota/Center", - "America/North_Dakota/New_Salem", - "America/Rainy_River","America/Rankin_Inlet", - "America/Resolute","America/Winnipeg","CST6CDT", - "Canada/Central","Cuba","Mexico/General", - "US/Central","US/Indiana-Starke"], - ["ACST","Australia/Adelaide", - "Australia/Broken_Hill","Australia/Darwin", - "Australia/North","Australia/South", - "Australia/Yancowinna"], - ["GMT-6","Etc/GMT-6"], - ["CHAST","NZ-CHAT","Pacific/Chatham"]], - [["PYST","America/Asuncion"], - ["PDT","America/Dawson","America/Ensenada", - "America/Los_Angeles","America/Santa_Isabel", - "America/Tijuana","America/Vancouver", - "America/Whitehorse","Canada/Pacific", - "Canada/Yukon","Mexico/BajaNorte","PST8PDT", - "US/Pacific"], - ["IST","Asia/Calcutta","Asia/Colombo", - "Asia/Jerusalem","Asia/Kolkata","Asia/Tel_Aviv", - "Eire","Europe/Dublin","Israel"], - ["GET","Asia/Tbilisi"], - ["GMT-12","Etc/GMT-12"], - ["GMT-3","Etc/GMT-3"]]}, - {[["PMDT","America/Miquelon"], - ["GMT+11","Etc/GMT+11"]], - [["EAT","Africa/Addis_Ababa","Africa/Asmara", - "Africa/Asmera","Africa/Dar_es_Salaam", - "Africa/Djibouti","Africa/Juba","Africa/Kampala", - "Africa/Khartoum","Africa/Mogadishu", - "Africa/Nairobi","Indian/Antananarivo", - "Indian/Comoro","Indian/Mayotte"], - ["CST","America/Bahia_Banderas","America/Belize", - "America/Chicago","America/Costa_Rica", - "America/El_Salvador","America/Guatemala", - "America/Havana","America/Indiana/Knox", - "America/Indiana/Tell_City","America/Knox_IN", - "America/Managua","America/Matamoros", - "America/Menominee","America/Merida", - "America/Mexico_City","America/Monterrey", - "America/North_Dakota/Beulah", - "America/North_Dakota/Center", - "America/North_Dakota/New_Salem", - "America/Rainy_River","America/Rankin_Inlet", - "America/Regina","America/Resolute", - "America/Swift_Current","America/Tegucigalpa", - "America/Winnipeg","Asia/Chongqing", - "Asia/Chungking","Asia/Harbin","Asia/Macao", - "Asia/Macau","Asia/Shanghai","Asia/Taipei", - "CST6CDT","Canada/Central", - "Canada/East-Saskatchewan","Canada/Saskatchewan", - "Cuba","Mexico/General","PRC","ROC","US/Central", - "US/Indiana-Starke"], - ["TJT","Asia/Dushanbe"], - ["KRAT","Asia/Krasnoyarsk","Asia/Novokuznetsk"], - ["MYT","Asia/Kuala_Lumpur","Asia/Kuching"], - ["SCT","Indian/Mahe"]], - [["CEST","Africa/Ceuta","Antarctica/Troll", - "Arctic/Longyearbyen","Atlantic/Jan_Mayen","CET", - "Europe/Amsterdam","Europe/Andorra", - "Europe/Belgrade","Europe/Berlin", - "Europe/Bratislava","Europe/Brussels", - "Europe/Budapest","Europe/Busingen", - "Europe/Copenhagen","Europe/Gibraltar", - "Europe/Ljubljana","Europe/Luxembourg", - "Europe/Madrid","Europe/Malta","Europe/Monaco", - "Europe/Oslo","Europe/Paris","Europe/Podgorica", - "Europe/Prague","Europe/Rome","Europe/San_Marino", - "Europe/Sarajevo","Europe/Skopje", - "Europe/Stockholm","Europe/Tirane","Europe/Vaduz", - "Europe/Vatican","Europe/Vienna","Europe/Warsaw", - "Europe/Zagreb","Europe/Zurich","Poland"], - ["PST","America/Dawson","America/Ensenada", - "America/Los_Angeles","America/Metlakatla", - "America/Santa_Isabel","America/Tijuana", - "America/Vancouver","America/Whitehorse", - "Canada/Pacific","Canada/Yukon", - "Mexico/BajaNorte","PST8PDT","Pacific/Pitcairn", - "US/Pacific"], - ["AWST","Antarctica/Casey","Australia/Perth", - "Australia/West"], - ["SYOT","Antarctica/Syowa"], - ["VLAT","Asia/Ust-Nera","Asia/Vladivostok"], - ["CXT","Indian/Christmas"], - ["TOT","Pacific/Tongatapu"]], - [["AKDT","America/Anchorage","America/Juneau", - "America/Nome","America/Sitka","America/Yakutat", - "US/Alaska"], - ["GYT","America/Guyana"], - ["PMST","America/Miquelon"], - ["UTC","Etc/UTC","Antarctica/Troll", - "Etc/Universal","Etc/Zulu","UTC","Universal", - "Zulu"], - ["WIT","Asia/Jayapura"], - ["GMT+9","Etc/GMT+9"], - ["MART","Pacific/Marquesas"]], - [["SRT","America/Paramaribo"], - ["MAWT","Antarctica/Mawson"], - ["CHOST","Asia/Choibalsan"], - ["YAKT","Asia/Khandyga","Asia/Yakutsk"], - ["JST","Asia/Tokyo","Japan"], - ["AZOST","Atlantic/Azores"], - ["GMT+6","Etc/GMT+6"], - ["MHT","Kwajalein","Pacific/Kwajalein", - "Pacific/Majuro"], - ["MEST","MET"]], - [["MMT","Asia/Rangoon"], - ["ULAT","Asia/Ulaanbaatar","Asia/Ulan_Bator"], - ["AEDT","Australia/ACT","Australia/Canberra", - "Australia/Currie","Australia/Hobart", - "Australia/Melbourne","Australia/NSW", - "Australia/Sydney","Australia/Tasmania", - "Australia/Victoria"], - ["GMT+3","Etc/GMT+3"]], - [["WEST","Africa/Casablanca","Africa/El_Aaiun", - "Atlantic/Canary","Atlantic/Faeroe", - "Atlantic/Faroe","Atlantic/Madeira", - "Europe/Lisbon","Portugal","WET"], - ["AKST","America/Anchorage","America/Juneau", - "America/Nome","America/Sitka","America/Yakutat", - "US/Alaska"], - ["CLT","America/Santiago","Antarctica/Palmer", - "Chile/Continental"], - ["BRST","America/Sao_Paulo","Brazil/East"], - ["EGST","America/Scoresbysund"], - ["OMST","Asia/Omsk"], - ["PGT","Pacific/Port_Moresby"]], - [["GMT","Africa/Abidjan","Africa/Accra", - "Africa/Bamako","Africa/Banjul","Africa/Bissau", - "Africa/Conakry","Africa/Dakar","Africa/Freetown", - "Africa/Lome","Africa/Monrovia", - "Africa/Nouakchott","Africa/Ouagadougou", - "Africa/Sao_Tome","Africa/Timbuktu", - "America/Danmarkshavn","Atlantic/Reykjavik", - "Atlantic/St_Helena","Eire","Etc/GMT","Etc/GMT+0", - "Etc/GMT-0","Etc/GMT0","Etc/Greenwich", - "Europe/Belfast","Europe/Dublin", - "Europe/Guernsey","Europe/Isle_of_Man", - "Europe/Jersey","Europe/London","GB","GB-Eire", - "GMT","GMT+0","GMT-0","GMT0","Greenwich", - "Iceland"], - ["ACT","America/Eirunepe","America/Porto_Acre", - "America/Rio_Branco","Brazil/Acre"], - ["NZDT","Antarctica/McMurdo", - "Antarctica/South_Pole","NZ","Pacific/Auckland"], - ["GALT","Pacific/Galapagos"]], - [["EDT","America/Cayman","America/Detroit", - "America/Fort_Wayne", - "America/Indiana/Indianapolis", - "America/Indiana/Marengo", - "America/Indiana/Petersburg", - "America/Indiana/Vevay", - "America/Indiana/Vincennes", - "America/Indiana/Winamac","America/Indianapolis", - "America/Iqaluit","America/Kentucky/Louisville", - "America/Kentucky/Monticello", - "America/Louisville","America/Montreal", - "America/Nassau","America/New_York", - "America/Nipigon","America/Pangnirtung", - "America/Port-au-Prince","America/Thunder_Bay", - "America/Toronto","Canada/Eastern","EST5EDT", - "US/East-Indiana","US/Eastern","US/Michigan"], - ["BOT","America/La_Paz"], - ["TMT","Asia/Ashgabat","Asia/Ashkhabad"], - ["PETT","Asia/Kamchatka"], - ["CVT","Atlantic/Cape_Verde"], - ["AEST","Australia/ACT","Australia/Brisbane", - "Australia/Canberra","Australia/Currie", - "Australia/Hobart","Australia/Lindeman", - "Australia/Melbourne","Australia/NSW", - "Australia/Queensland","Australia/Sydney", - "Australia/Tasmania","Australia/Victoria"], - ["EAST","Chile/EasterIsland","Pacific/Easter"], - ["GMT-8","Etc/GMT-8"], - ["NCT","Pacific/Noumea"]], - [["AMT","America/Boa_Vista","America/Campo_Grande", - "America/Cuiaba","America/Manaus", - "America/Porto_Velho","Asia/Yerevan", - "Brazil/West"], - ["WGT","America/Godthab"], - ["UYT","America/Montevideo"], - ["IRKT","Asia/Chita","Asia/Irkutsk"], - ["WIB","Asia/Jakarta","Asia/Pontianak"], - ["KST","Asia/Pyongyang","Asia/Seoul","ROK"], - ["BTT","Asia/Thimbu","Asia/Thimphu"], - ["GMT-14","Etc/GMT-14"], - ["GMT-5","Etc/GMT-5"], - ["WSDT","Pacific/Apia"]], - [["ART","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/Buenos_Aires","America/Catamarca", - "America/Cordoba","America/Jujuy", - "America/Mendoza","America/Rosario"], - ["VET","America/Caracas"], - ["NZST","Antarctica/McMurdo", - "Antarctica/South_Pole","NZ","Pacific/Auckland"], - ["GMT-11","Etc/GMT-11"], - ["GMT-2","Etc/GMT-2"], - ["WAKT","Pacific/Wake"]], - [["CET","Africa/Algiers","Africa/Ceuta", - "Africa/Tunis","Arctic/Longyearbyen", - "Atlantic/Jan_Mayen","CET","Europe/Amsterdam", - "Europe/Andorra","Europe/Belgrade", - "Europe/Berlin","Europe/Bratislava", - "Europe/Brussels","Europe/Budapest", - "Europe/Busingen","Europe/Copenhagen", - "Europe/Gibraltar","Europe/Ljubljana", - "Europe/Luxembourg","Europe/Madrid", - "Europe/Malta","Europe/Monaco","Europe/Oslo", - "Europe/Paris","Europe/Podgorica","Europe/Prague", - "Europe/Rome","Europe/San_Marino", - "Europe/Sarajevo","Europe/Skopje", - "Europe/Stockholm","Europe/Tirane","Europe/Vaduz", - "Europe/Vatican","Europe/Vienna","Europe/Warsaw", - "Europe/Zagreb","Europe/Zurich","Poland"], - ["EST","America/Atikokan","America/Cancun", - "America/Cayman","America/Coral_Harbour", - "America/Detroit","America/Fort_Wayne", - "America/Indiana/Indianapolis", - "America/Indiana/Marengo", - "America/Indiana/Petersburg", - "America/Indiana/Vevay", - "America/Indiana/Vincennes", - "America/Indiana/Winamac","America/Indianapolis", - "America/Iqaluit","America/Jamaica", - "America/Kentucky/Louisville", - "America/Kentucky/Monticello", - "America/Louisville","America/Montreal", - "America/Nassau","America/New_York", - "America/Nipigon","America/Panama", - "America/Pangnirtung","America/Port-au-Prince", - "America/Thunder_Bay","America/Toronto", - "Canada/Eastern","EST","EST5EDT","Jamaica", - "US/East-Indiana","US/Eastern","US/Michigan"], - ["ANAT","Asia/Anadyr"], - ["GMT+10","Etc/GMT+10"], - ["UCT","Etc/UCT","UCT"], - ["IOT","Indian/Chagos"], - ["CHUT","Pacific/Chuuk","Pacific/Truk", - "Pacific/Yap"], - ["NRT","Pacific/Nauru"]], - [["GFT","America/Cayenne"], - ["PET","America/Lima"], - ["HOVT","Asia/Hovd"], - ["ULAST","Asia/Ulaanbaatar","Asia/Ulan_Bator"], - ["WSST","Pacific/Apia"], - ["PONT","Pacific/Pohnpei","Pacific/Ponape"], - ["TAHT","Pacific/Tahiti"]], - [["COT","America/Bogota"], - ["KGT","Asia/Bishkek"], - ["TFT","Indian/Kerguelen"], - ["MUT","Indian/Mauritius"]], - [["AFT","Asia/Kabul"], - ["IRDT","Asia/Tehran","Iran"], - ["GMT+8","Etc/GMT+8"], - ["TKT","Pacific/Fakaofo"]], - [["WET","Africa/Casablanca","Africa/El_Aaiun", - "Atlantic/Canary","Atlantic/Faeroe", - "Atlantic/Faroe","Atlantic/Madeira", - "Europe/Lisbon","Portugal","WET"], - ["BRT","America/Araguaina","America/Bahia", - "America/Belem","America/Fortaleza", - "America/Maceio","America/Recife", - "America/Santarem","America/Sao_Paulo", - "Brazil/East"], - ["FNT","America/Noronha","Brazil/DeNoronha"], - ["EGT","America/Scoresbysund"], - ["ICT","Asia/Bangkok","Asia/Ho_Chi_Minh", - "Asia/Phnom_Penh","Asia/Saigon","Asia/Vientiane"], - ["GMT+5","Etc/GMT+5"], - ["NFT","Pacific/Norfolk"], - ["GILT","Pacific/Tarawa"]]}, - {[["PYT","America/Asuncion"], - ["MDT","America/Boise","America/Cambridge_Bay", - "America/Chihuahua","America/Denver", - "America/Edmonton","America/Inuvik", - "America/Mazatlan","America/Ojinaga", - "America/Shiprock","America/Yellowknife", - "Canada/Mountain","MST7MDT","Mexico/BajaSur", - "Navajo","US/Mountain"], - ["AMST","America/Campo_Grande","America/Cuiaba"], - ["SAMT","Europe/Samara"]], - [["AQTT","Asia/Aqtau","Asia/Aqtobe"], - ["AZST","Asia/Baku"], - ["IRST","Asia/Tehran","Iran"], - ["ChST","Pacific/Guam","Pacific/Saipan"], - ["SST","Pacific/Midway","Pacific/Pago_Pago", - "Pacific/Samoa","US/Samoa"]], - [["WAST","Africa/Windhoek"], - ["FJST","Pacific/Fiji"], - ["NUT","Pacific/Niue"]], - [["PHT","Asia/Manila"], - ["LHDT","Australia/LHI","Australia/Lord_Howe"]], - [["ADT","America/Glace_Bay","America/Goose_Bay", - "America/Halifax","America/Moncton", - "America/Thule","Atlantic/Bermuda", - "Canada/Atlantic"], - ["DDUT","Antarctica/DumontDUrville"], - ["MAGT","Asia/Magadan"], - ["SBT","Pacific/Guadalcanal"]], - [["EET","Africa/Cairo","Africa/Tripoli", - "Asia/Amman","Asia/Beirut","Asia/Damascus", - "Asia/Gaza","Asia/Hebron","Asia/Istanbul", - "Asia/Nicosia","EET","Egypt","Europe/Athens", - "Europe/Bucharest","Europe/Chisinau", - "Europe/Helsinki","Europe/Istanbul", - "Europe/Kaliningrad","Europe/Kiev", - "Europe/Mariehamn","Europe/Nicosia","Europe/Riga", - "Europe/Sofia","Europe/Tallinn","Europe/Tiraspol", - "Europe/Uzhgorod","Europe/Vilnius", - "Europe/Zaporozhye","Libya","Turkey"], - ["NDT","America/St_Johns","Canada/Newfoundland"], - ["GST","Asia/Dubai","Asia/Muscat", - "Atlantic/South_Georgia"], - ["XJT","Asia/Kashgar","Asia/Urumqi"], - ["ORAT","Asia/Oral"], - ["GMT+12","Etc/GMT+12"]], - [["UZT","Asia/Samarkand","Asia/Tashkent"], - ["RET","Indian/Reunion"]], - [["CAT","Africa/Blantyre","Africa/Bujumbura", - "Africa/Gaborone","Africa/Harare","Africa/Kigali", - "Africa/Lubumbashi","Africa/Lusaka", - "Africa/Maputo"], - ["QYZT","Asia/Qyzylorda"], - ["FKST","Atlantic/Stanley"]], - [["MIST","Antarctica/Macquarie"], - ["WITA","Asia/Makassar","Asia/Ujung_Pandang"]], - [],[],[],[],[],[],[]}, - {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}}}). diff --git a/priv/db/.gitignore b/priv/db/.gitignore new file mode 100644 index 0000000..badaa65 --- /dev/null +++ b/priv/db/.gitignore @@ -0,0 +1,3 @@ +tzout +tzdata/ +*.tar.gz diff --git a/db/Makefile b/priv/db/Makefile similarity index 82% rename from db/Makefile rename to priv/db/Makefile index 44071f0..dc2cb42 100644 --- a/db/Makefile +++ b/priv/db/Makefile @@ -3,7 +3,7 @@ TZ_FILES=$(addprefix $(TZDIR)/, africa antarctica asia australasia backward etce tzout: DATE := $(shell date +%F) tzout: $(TZ_FILES) - TZ_VERSION=`perl -n -e 'm/^VERSION\s*=\s*(\S+)/ and print $$1;' $(TZDIR)/Makefile`; \ + TZ_VERSION=`cat $(TZDIR)/version`; \ ./tz-erl --version $$TZ_VERSION --date $(DATE) -o $@ $^ $(TZ_FILES): $(TZDIR) @@ -14,4 +14,5 @@ $(TZDIR): tzdata-latest.tar.gz tzdata-latest.tar.gz: curl -O "ftp://ftp.iana.org/tz/tzdata-latest.tar.gz" - +clean: + @(rm -fr tzdata *.tar.gz tzout *~) diff --git a/db/tz-erl b/priv/db/tz-erl similarity index 95% rename from db/tz-erl rename to priv/db/tz-erl index 3f41e21..bcc743e 100755 --- a/db/tz-erl +++ b/priv/db/tz-erl @@ -459,11 +459,16 @@ sub on_to_day_of_month { my $day; if ($on =~ m/^\d+$/) { $day = $on; + print "Day extracted via regex to: $day\n"; } else { my ($desired_dow, $time_base); if ($on =~ m/^(\w+)>=(\d+)$/) { $desired_dow = $dow_from_name{$1}; my $desired_day = $2; $time_base = timelocal(0, 0, 0, $desired_day, $month, $year); + print "Regex: $on => desired_dow: $desired_dow. Time_base: $time_base\n"; + } elsif ($on =~ m/^(\w+)<=(\d+)$/) { + $desired_dow = $dow_from_name{$1}; my $desired_day = $2; + $time_base = timelocal(0, 0, 0, $desired_day, $month, $year); } elsif ($on =~ m/^last(\w+)$/) { $desired_dow = $dow_from_name{$1}; # One week before the beginning of the next month. @@ -472,7 +477,12 @@ sub on_to_day_of_month { die "match $on failed"; } ($day, my $dow) = (localtime($time_base))[3,6]; - if ($dow != $desired_dow) { $day += (DPW + $desired_dow - $dow) % DPW; } + print "Current Day: $day\n"; + print "Comparing $dow = $desired_dow\n"; + if ($dow != $desired_dow) { + $day += (DPW + $desired_dow - $dow) % DPW; + } + print "After comparison: Current Day: $day\n"; } return $day; @@ -511,6 +521,10 @@ sub last_active_epoch { } my $day = on_to_day_of_month($on, $year, $month); + print "On=$on, Year=$year, Month=$month ====> Day=$day\n"; + ## changing the below call to timelocal_nocheck stops the crash, but it feels wrong + ## especially since without it, it seems to produce a lot of "redundant" error messages + ## I don't have time to explore this now, but I'll come back to it return timelocal(0, 0, 0, $day, $month, $year); } diff --git a/priv/ibuild.escript b/priv/ibuild.escript new file mode 100755 index 0000000..7b7b39f --- /dev/null +++ b/priv/ibuild.escript @@ -0,0 +1,60 @@ +#!/usr/bin/env escript +%% @author Dmitry S. Melnikov (dmitryme@gmail.com) +%% @copyright 2010 Dmitry S. Melnikov + +-include("../include/tz_database.hrl"). +-define(out, "src/tz_index.erl"). + +build_tzlist(TzName, Name, Dict) -> + case dict:find(Name, Dict) of + error -> + dict:store(Name, [TzName], Dict); + {ok, TzNames} -> + dict:store(Name, TzNames ++ [TzName], Dict) + end. + +build_index() -> + F = fun({TzName,{Name,_},{DName,_},_,_,_,_,_,_}, Acc) -> + NewDict = build_tzlist(TzName, Name, Acc), + build_tzlist(TzName, DName, NewDict); + ({TzName,{Name,_},undef,_,_,_,_,_,_}, Acc) -> + build_tzlist(TzName, Name, Acc) + end, + I = lists:foldl(F, dict:new(), ?tz_database), + List = dict:to_list(I), + LookupFunction = build_function_clauses(List), + AllFunction = build_all_function(List), + Header = "-module(tz_index).\n-export([lookup/1, all/0]).", + Body = [Header, "\n\n", LookupFunction, "\n\n", AllFunction], + ok = file:write_file(?out, Body). + + +% {ok, File} = file:open("tz_index.hrl", [write]), +% io:fwrite(File, "-define(tz_index, ~p).\n", [I]). + + +build_function_clauses(List) -> + Clauses = lists:map(fun({K0, V0}) -> + {K, V} = hack_fix_utc({K0, V0}), + io_lib:format("lookup(~p) -> ~p", [K, V]) + end, List), + [lists:join(";\n", Clauses), ";\n", + "lookup(_) -> error."]. + + +hack_fix_utc({"UTC", TZs}) -> + MainTZ = "Etc/UTC", + NoMainTZ = TZs -- [MainTZ], + NewTZs = [MainTZ | NoMainTZ], + {"UTC", NewTZs}; +hack_fix_utc({K, V}) -> + {K, V}. + +build_all_function(List) -> + Keys = [K || {K, _} <- List], + io_lib:format("all() -> ~p.",[Keys]). + +%% So this can be run from escript: +main(_Args) -> + io:format("Generating qdate_localtime module: tz_index.erl\n"), + build_index(). diff --git a/rebar.config b/rebar.config index 0f5d40e..781bcf2 100644 --- a/rebar.config +++ b/rebar.config @@ -1 +1,11 @@ {erl_opts, [debug_info]}. + +{dialyzer, [ + {warnings, []} +]}. + +{pre_hooks,[ + {"linux|bsd|darwin|solaris", compile, "priv/ibuild.escript"}, + {"win32", compile, "escript.exe priv/ibuild.escript"} +]}. + diff --git a/rebar.lock b/rebar.lock deleted file mode 100644 index 57afcca..0000000 --- a/rebar.lock +++ /dev/null @@ -1 +0,0 @@ -[]. diff --git a/rebar3 b/rebar3 deleted file mode 100755 index d1dc07f..0000000 Binary files a/rebar3 and /dev/null differ diff --git a/src/ibuild.erl b/src/ibuild.erl deleted file mode 100755 index 2530004..0000000 --- a/src/ibuild.erl +++ /dev/null @@ -1,31 +0,0 @@ -%% @author Dmitry S. Melnikov (dmitryme@gmail.com) -%% @copyright 2010 Dmitry S. Melnikov - --module(ibuild). - --export([build_index/0, main/1]). - --include("tz_database.hrl"). - -build_tzlist(TzName, Name, Dict) -> - case dict:find(Name, Dict) of - error -> - dict:store(Name, [TzName], Dict); - {ok, TzNames} -> - dict:store(Name, TzNames ++ [TzName], Dict) - end. - -build_index() -> - F = fun({TzName,{Name,_},{DName,_},_,_,_,_,_,_}, Acc) -> - NewDict = build_tzlist(TzName, Name, Acc), - build_tzlist(TzName, DName, NewDict); - ({TzName,{Name,_},undef,_,_,_,_,_,_}, Acc) -> - build_tzlist(TzName, Name, Acc) - end, - I = lists:foldl(F, dict:new(), ?tz_database), - {ok, File} = file:open("tz_index.hrl", [write]), - io:fwrite(File, "-define(tz_index, ~p).\n", [I]). - -%% So this can be run from escript: -main(_Args) -> - build_index(). diff --git a/src/localtime.erl b/src/localtime.erl index d6f18ed..0bf952a 100644 --- a/src/localtime.erl +++ b/src/localtime.erl @@ -6,7 +6,6 @@ -author("Dmitry Melnikov "). -include("tz_database.hrl"). --include("tz_index.hrl"). -export( [ @@ -197,7 +196,7 @@ get_timezone(TimeZone) -> get_timezone_inner(TimeZone). list_timezones() -> - dict:fetch_keys(?tz_index). + tz_index:all(). % ======================================================================= % privates @@ -238,14 +237,14 @@ get_timezone_inner(TimeZone) when is_binary(TimeZone) -> get_timezone_inner(erlang:binary_to_list(TimeZone)); get_timezone_inner(TimeZone) when is_list(TimeZone) -> TimeZoneNoSpaces = tr_char(TimeZone, ?SPACE_CHAR, $_), - case dict:find(TimeZoneNoSpaces, ?tz_index) of + case tz_index:lookup(TimeZoneNoSpaces) of error -> - TimeZoneNoSpaces; - {ok, [TZName | _]} -> - TZName + TimeZoneNoSpaces; + [TZName | _] -> + TZName end; -get_timezone_inner(_) -> - throw({error, "Timezone should be string/binary"}). +get_timezone_inner(TZ) -> + throw({error, "Timezone should be string/binary", {provided_timezone, TZ}}). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). @@ -255,6 +254,14 @@ tr_char_test() -> ?assertEqual("AB_DE", tr_char("AB DE", ?SPACE_CHAR, $_)), ?assertEqual("A_C_E", tr_char("A C E", ?SPACE_CHAR, $_)). +tz_name_test() -> + ?assertEqual({"CET", "CET"}, tz_name({{2008,12,10},{15,30,0}}, "Europe/Amsterdam")), + %%% No DST in Iran + ?assertEqual({"IRST", "IRST"}, tz_name({{2008,12,10},{15,30,0}}, "Asia/Tehran")), + ?assertEqual({"IRST", "IRST"}, tz_name({{2020,5,4},{15,30,0}}, "Asia/Tehran")), + ?assertEqual({"IRST", "IRST"}, tz_name({{2008,12,10},{15,30,0}}, "Iran")), + ?assertEqual({"IRST", "IRST"}, tz_name({{2020,5,4},{15,30,0}}, "Iran")). + get_timezone_test() -> ?assertEqual("America/Los_Angeles", get_timezone("America/Los Angeles")). diff --git a/src/localtime_dst.erl b/src/localtime_dst.erl index ca4d3e6..2e73e24 100644 --- a/src/localtime_dst.erl +++ b/src/localtime_dst.erl @@ -6,7 +6,6 @@ -author("Dmitry Melnikov "). -include("tz_database.hrl"). --include("tz_index.hrl"). -export( [ diff --git a/src/qdate_localtime.app.src b/src/qdate_localtime.app.src index cd13a37..a7d9093 100644 --- a/src/qdate_localtime.app.src +++ b/src/qdate_localtime.app.src @@ -1,7 +1,7 @@ {application, 'qdate_localtime', [ {description, "Erlang library for conversion from one local time to another (forked specifically for qdate compatibility)"}, - {vsn, "1.1.0"}, + {vsn, "1.2.1"}, {applications, [kernel, stdlib]}, {modules, []}, {registered, []},