module Data.Time.Exts.Zone where
import Control.Arrow (first)
import Data.Aeson (FromJSON, ToJSON)
import Data.Convertible (Convertible(..))
import Data.Ord (comparing)
import Data.Typeable (Typeable)
import GHC.Generics (Generic)
import System.Random (Random(..))
data City =
Aden
| Amman
| Anchorage
| Auckland
| Baghdad
| Berlin
| Brussels
| Bujumbura
| Cairo
| Chicago
| Damascus
| Denver
| Doha
| Gaborone
| Hong_Kong
| Honolulu
| Johannesburg
| Kabul
| Karachi
| Kinshasa
| Kolkata
| Kuwait_City
| London
| Los_Angeles
| Luanda
| Manama
| Minsk
| Mogadishu
| Moscow
| New_York
| Oslo
| Ouagadougou
| Paris
| Pyongyang
| Riyadh
| Sao_Paulo
| Sarajevo
| Seoul
| Shanghai
| Singapore
| Sofia
| Stockholm
| Tehran
| Tel_Aviv
| Tirana
| Tokyo
| Toronto
| Universal
| Vienna
| Zurich
deriving (Eq,Enum,Generic,Ord,Show,Typeable)
data TimeZone =
Afghanistan_Time
| Alaska_Daylight_Time
| Alaska_Hawaii_Daylight_Time
| Alaska_Hawaii_Standard_Time
| Alaska_Standard_Time
| Arabia_Daylight_Time
| Arabia_Standard_Time
| Brasilia_Summer_Time
| Brasilia_Time
| British_Summer_Time
| Central_Africa_Time
| Central_Daylight_Time
| Central_European_Summer_Time
| Central_European_Time
| Central_Standard_Time
| China_Daylight_Time
| China_Standard_Time
| Coordinated_Universal_Time
| East_Africa_Time
| Eastern_Daylight_Time
| Eastern_European_Summer_Time
| Eastern_European_Time
| Eastern_Standard_Time
| Further_Eastern_European_Time
| Greenwich_Mean_Time
| Gulf_Standard_Time
| Hawaii_Aleutian_Standard_Time
| Hong_Kong_Summer_Time
| Hong_Kong_Time
| India_Standard_Time
| Iran_Daylight_Time
| Iran_Standard_Time
| Israel_Daylight_Time
| Israel_Standard_Time
| Japan_Standard_Time
| Karachi_Time
| Korea_Daylight_Time
| Korea_Standard_Time
| Moscow_Daylight_Time
| Moscow_Standard_Time
| Mountain_Daylight_Time
| Mountain_Standard_Time
| New_Zealand_Daylight_Time
| New_Zealand_Standard_Time
| Pacific_Daylight_Time
| Pacific_Standard_Time
| Pakistan_Standard_Time
| Pakistan_Summer_Time
| Singapore_Time
| South_Africa_Standard_Time
| West_Africa_Time
| Yukon_Standard_Time
deriving (Eq,Enum,Generic,Show,Typeable)
data TimeZoneAbbr = TimeZoneAbbr {
abbr_city :: City
, abbr_str :: String
} deriving (Eq,Generic,Typeable)
instance Bounded City where
minBound = Aden
maxBound = Zurich
instance Bounded TimeZone where
minBound = Afghanistan_Time
maxBound = Yukon_Standard_Time
instance Convertible TimeZone TimeZoneAbbr where
safeConvert = Right . \ case
Afghanistan_Time -> TimeZoneAbbr Kabul "AFT"
Alaska_Daylight_Time -> TimeZoneAbbr Anchorage "AKDT"
Alaska_Hawaii_Daylight_Time -> TimeZoneAbbr Anchorage "AHDT"
Alaska_Hawaii_Standard_Time -> TimeZoneAbbr Anchorage "AHST"
Alaska_Standard_Time -> TimeZoneAbbr Anchorage "AKST"
Arabia_Daylight_Time -> TimeZoneAbbr Baghdad "ADT"
Arabia_Standard_Time -> TimeZoneAbbr Riyadh "AST"
Brasilia_Summer_Time -> TimeZoneAbbr Sao_Paulo "BRST"
Brasilia_Time -> TimeZoneAbbr Sao_Paulo "BRT"
British_Summer_Time -> TimeZoneAbbr London "BST"
Central_Africa_Time -> TimeZoneAbbr Gaborone "CAT"
Central_Daylight_Time -> TimeZoneAbbr Chicago "CDT"
Central_European_Summer_Time -> TimeZoneAbbr Paris "CEST"
Central_European_Time -> TimeZoneAbbr Paris "CET"
Central_Standard_Time -> TimeZoneAbbr Chicago "CST"
China_Daylight_Time -> TimeZoneAbbr Shanghai "CDT"
China_Standard_Time -> TimeZoneAbbr Shanghai "CST"
Coordinated_Universal_Time -> TimeZoneAbbr Universal "UTC"
East_Africa_Time -> TimeZoneAbbr Mogadishu "EAT"
Eastern_Daylight_Time -> TimeZoneAbbr New_York "EDT"
Eastern_European_Summer_Time -> TimeZoneAbbr Sofia "EEST"
Eastern_European_Time -> TimeZoneAbbr Sofia "EET"
Eastern_Standard_Time -> TimeZoneAbbr New_York "EST"
Further_Eastern_European_Time -> TimeZoneAbbr Minsk "FET"
Greenwich_Mean_Time -> TimeZoneAbbr London "GMT"
Gulf_Standard_Time -> TimeZoneAbbr Manama "GST"
Hawaii_Aleutian_Standard_Time -> TimeZoneAbbr Honolulu "HST"
Hong_Kong_Time -> TimeZoneAbbr Hong_Kong "HKT"
Hong_Kong_Summer_Time -> TimeZoneAbbr Hong_Kong "HKST"
India_Standard_Time -> TimeZoneAbbr Kolkata "IST"
Iran_Daylight_Time -> TimeZoneAbbr Tehran "IRDT"
Iran_Standard_Time -> TimeZoneAbbr Tehran "IRST"
Israel_Daylight_Time -> TimeZoneAbbr Tel_Aviv "IDT"
Israel_Standard_Time -> TimeZoneAbbr Tel_Aviv "IST"
Japan_Standard_Time -> TimeZoneAbbr Tokyo "JST"
Karachi_Time -> TimeZoneAbbr Karachi "KART"
Korea_Daylight_Time -> TimeZoneAbbr Seoul "KDT"
Korea_Standard_Time -> TimeZoneAbbr Seoul "KST"
Moscow_Daylight_Time -> TimeZoneAbbr Moscow "MSD"
Moscow_Standard_Time -> TimeZoneAbbr Moscow "MSK"
Mountain_Daylight_Time -> TimeZoneAbbr Denver "MDT"
Mountain_Standard_Time -> TimeZoneAbbr Denver "MST"
New_Zealand_Daylight_Time -> TimeZoneAbbr Auckland "NZDT"
New_Zealand_Standard_Time -> TimeZoneAbbr Auckland "NZST"
Pacific_Daylight_Time -> TimeZoneAbbr Los_Angeles "PDT"
Pacific_Standard_Time -> TimeZoneAbbr Los_Angeles "PST"
Pakistan_Standard_Time -> TimeZoneAbbr Karachi "PKT"
Pakistan_Summer_Time -> TimeZoneAbbr Karachi "PKST"
Singapore_Time -> TimeZoneAbbr Singapore "SGT"
South_Africa_Standard_Time -> TimeZoneAbbr Johannesburg "SAST"
West_Africa_Time -> TimeZoneAbbr Luanda "WAT"
Yukon_Standard_Time -> TimeZoneAbbr Anchorage "YST"
instance Convertible TimeZoneAbbr TimeZone where
safeConvert = Right . \ TimeZoneAbbr{..} ->
case abbr_str of
"AFT" -> Afghanistan_Time
"AHDT" -> Alaska_Hawaii_Daylight_Time
"AHST" -> Alaska_Hawaii_Standard_Time
"AKDT" -> Alaska_Daylight_Time
"AKST" -> Alaska_Standard_Time
"ADT" -> Arabia_Daylight_Time
"AST" -> Arabia_Standard_Time
"BRST" -> Brasilia_Summer_Time
"BRT" -> Brasilia_Time
"BST" -> British_Summer_Time
"CAT" -> Central_Africa_Time
"CDT" -> case abbr_city of
Chicago -> Central_Daylight_Time
Shanghai -> China_Daylight_Time
_ -> missing abbr_city
"CEST" -> Central_European_Summer_Time
"CET" -> Central_European_Time
"CST" -> case abbr_city of
Chicago -> Central_Standard_Time
Shanghai -> China_Standard_Time
_ -> missing abbr_city
"EAT" -> East_Africa_Time
"EDT" -> Eastern_Daylight_Time
"EEST" -> Eastern_European_Summer_Time
"EET" -> Eastern_European_Time
"EST" -> Eastern_Standard_Time
"FET" -> Further_Eastern_European_Time
"GMT" -> Greenwich_Mean_Time
"GST" -> Gulf_Standard_Time
"HST" -> Hawaii_Aleutian_Standard_Time
"HKST" -> Hong_Kong_Summer_Time
"HKT" -> Hong_Kong_Time
"IDT" -> Israel_Daylight_Time
"IRDT" -> Iran_Daylight_Time
"IRST" -> Iran_Standard_Time
"IST" -> case abbr_city of
Kolkata -> India_Standard_Time
Tel_Aviv -> Israel_Standard_Time
_ -> missing abbr_city
"JST" -> Japan_Standard_Time
"KART" -> Karachi_Time
"KDT" -> Korea_Daylight_Time
"KST" -> Korea_Standard_Time
"MDT" -> Mountain_Daylight_Time
"MSD" -> Moscow_Daylight_Time
"MSK" -> Moscow_Standard_Time
"MST" -> Mountain_Standard_Time
"NZDT" -> New_Zealand_Daylight_Time
"NZST" -> New_Zealand_Standard_Time
"PDT" -> Pacific_Daylight_Time
"PKST" -> Pakistan_Summer_Time
"PKT" -> Pakistan_Standard_Time
"PST" -> Pacific_Standard_Time
"SAST" -> South_Africa_Standard_Time
"SGT" -> Singapore_Time
"UTC" -> Coordinated_Universal_Time
"WAT" -> West_Africa_Time
"YST" -> Yukon_Standard_Time
_ -> error $ "safeConvert: missing time zone abbreviation `" ++ abbr_str ++ "'"
where missing city = error $ "safeConvert: missing reference location `" ++ show city ++ "'"
instance FromJSON City
instance FromJSON TimeZone
instance FromJSON TimeZoneAbbr
instance Ord TimeZone where
compare = comparing offset
instance Random City where
random = first toEnum . randomR (0, 49)
randomR (a,b) = first toEnum . randomR (fromEnum a, fromEnum b)
instance Random TimeZone where
random = first toEnum . randomR (0, 51)
randomR (a,b) = first toEnum . randomR (fromEnum a, fromEnum b)
instance Show TimeZoneAbbr where
show TimeZoneAbbr{abbr_str} = abbr_str
instance ToJSON City
instance ToJSON TimeZone
instance ToJSON TimeZoneAbbr
cities :: [City]
cities =
[ Aden
, Amman
, Anchorage
, Auckland
, Baghdad
, Berlin
, Brussels
, Bujumbura
, Cairo
, Chicago
, Damascus
, Denver
, Doha
, Gaborone
, Hong_Kong
, Honolulu
, Johannesburg
, Kabul
, Karachi
, Kinshasa
, Kolkata
, Kuwait_City
, London
, Los_Angeles
, Luanda
, Manama
, Minsk
, Mogadishu
, Moscow
, New_York
, Oslo
, Ouagadougou
, Paris
, Pyongyang
, Riyadh
, Sao_Paulo
, Sarajevo
, Seoul
, Shanghai
, Singapore
, Sofia
, Stockholm
, Tehran
, Tel_Aviv
, Tirana
, Tokyo
, Toronto
, Universal
, Vienna
, Zurich
]
getOlsonFile :: City -> FilePath
getOlsonFile = \ case
Aden -> "/usr/share/zoneinfo/Asia/Aden"
Amman -> "/usr/share/zoneinfo/Asia/Amman"
Anchorage -> "/usr/share/zoneinfo/America/Anchorage"
Auckland -> "/usr/share/zoneinfo/Pacific/Auckland"
Baghdad -> "/usr/share/zoneinfo/Asia/Baghdad"
Berlin -> "/usr/share/zoneinfo/Europe/Berlin"
Brussels -> "/usr/share/zoneinfo/Europe/Brussels"
Bujumbura -> "/usr/share/zoneinfo/Africa/Bujumbura"
Cairo -> "/usr/share/zoneinfo/Africa/Cairo"
Chicago -> "/usr/share/zoneinfo/America/Chicago"
Damascus -> "/usr/share/zoneinfo/Asia/Damascus"
Denver -> "/usr/share/zoneinfo/America/Denver"
Doha -> "/usr/share/zoneinfo/Asia/Qatar"
Gaborone -> "/usr/share/zoneinfo/Africa/Gaborone"
Hong_Kong -> "/usr/share/zoneinfo/Asia/Hong_Kong"
Honolulu -> "/usr/share/zoneinfo/Pacific/Honolulu"
Johannesburg -> "/usr/share/zoneinfo/Africa/Johannesburg"
Kabul -> "/usr/share/zoneinfo/Asia/Kabul"
Karachi -> "/usr/share/zoneinfo/Asia/Karachi"
Kinshasa -> "/usr/share/zoneinfo/Africa/Kinshasa"
Kuwait_City -> "/usr/share/zoneinfo/Asia/Kuwait"
Kolkata -> "/usr/share/zoneinfo/Asia/Kolkata"
London -> "/usr/share/zoneinfo/Europe/London"
Los_Angeles -> "/usr/share/zoneinfo/America/Los_Angeles"
Luanda -> "/usr/share/zoneinfo/Africa/Luanda"
Manama -> "/usr/share/zoneinfo/Asia/Bahrain"
Minsk -> "/usr/share/zoneinfo/Europe/Minsk"
Mogadishu -> "/usr/share/zoneinfo/Africa/Mogadishu"
Moscow -> "/usr/share/zoneinfo/Europe/Moscow"
New_York -> "/usr/share/zoneinfo/America/New_York"
Oslo -> "/usr/share/zoneinfo/Europe/Oslo"
Ouagadougou -> "/usr/share/zoneinfo/Africa/Ouagadougou"
Paris -> "/usr/share/zoneinfo/Europe/Paris"
Pyongyang -> "/usr/share/zoneinfo/Asia/Pyongyang"
Riyadh -> "/usr/share/zoneinfo/Asia/Riyadh"
Sao_Paulo -> "/usr/share/zoneinfo/America/Sao_Paulo"
Sarajevo -> "/usr/share/zoneinfo/Europe/Sarajevo"
Seoul -> "/usr/share/zoneinfo/Asia/Seoul"
Shanghai -> "/usr/share/zoneinfo/Asia/Shanghai"
Singapore -> "/usr/share/zoneinfo/Asia/Singapore"
Sofia -> "/usr/share/zoneinfo/Europe/Sofia"
Stockholm -> "/usr/share/zoneinfo/Europe/Stockholm"
Tehran -> "/usr/share/zoneinfo/Asia/Tehran"
Tel_Aviv -> "/usr/share/zoneinfo/Asia/Tel_Aviv"
Tirana -> "/usr/share/zoneinfo/Europe/Tirane"
Tokyo -> "/usr/share/zoneinfo/Asia/Tokyo"
Toronto -> "/usr/share/zoneinfo/America/Toronto"
Universal -> "/usr/share/zoneinfo/Universal"
Vienna -> "/usr/share/zoneinfo/Europe/Vienna"
Zurich -> "/usr/share/zoneinfo/Europe/Zurich"
offset :: Num a => TimeZone -> a
offset = \ case
Afghanistan_Time -> 270
Alaska_Daylight_Time -> 480
Alaska_Hawaii_Daylight_Time -> 540
Alaska_Hawaii_Standard_Time -> 600
Alaska_Standard_Time -> 540
Arabia_Daylight_Time -> 240
Arabia_Standard_Time -> 180
Brasilia_Summer_Time -> 120
Brasilia_Time -> 180
British_Summer_Time -> 060
Central_Africa_Time -> 120
Central_Daylight_Time -> 300
Central_European_Summer_Time -> 120
Central_European_Time -> 060
Central_Standard_Time -> 360
China_Daylight_Time -> 540
China_Standard_Time -> 480
Coordinated_Universal_Time -> 000
East_Africa_Time -> 180
Eastern_Daylight_Time -> 240
Eastern_European_Summer_Time -> 180
Eastern_European_Time -> 120
Eastern_Standard_Time -> 300
Further_Eastern_European_Time -> 180
Greenwich_Mean_Time -> 000
Gulf_Standard_Time -> 240
Hawaii_Aleutian_Standard_Time -> 600
Hong_Kong_Summer_Time -> 540
Hong_Kong_Time -> 480
India_Standard_Time -> 330
Iran_Daylight_Time -> 270
Iran_Standard_Time -> 210
Israel_Daylight_Time -> 180
Israel_Standard_Time -> 120
Japan_Standard_Time -> 540
Karachi_Time -> 300
Korea_Daylight_Time -> 600
Korea_Standard_Time -> 540
Moscow_Daylight_Time -> 240
Moscow_Standard_Time -> 240
Mountain_Daylight_Time -> 360
Mountain_Standard_Time -> 420
New_Zealand_Daylight_Time -> 780
New_Zealand_Standard_Time -> 720
Pacific_Daylight_Time -> 420
Pacific_Standard_Time -> 480
Pakistan_Standard_Time -> 300
Pakistan_Summer_Time -> 360
Singapore_Time -> 480
South_Africa_Standard_Time -> 120
West_Africa_Time -> 060
Yukon_Standard_Time -> 540