--------------------------------------------------------------- -- Copyright (c) 2014, Enzo Haussecker. All rights reserved. -- --------------------------------------------------------------- {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RecordWildCards #-} {-# OPTIONS -Wall #-} {-# OPTIONS -fno-warn-type-defaults #-} -- | Location and time zone constructors and functions. module Data.Time.Exts.Zone ( -- ** Locations City(..) , cities -- ** Olson Database , getOlsonFile , olsonFiles -- ** Time Zones , TimeZone(..) , utc , getUTCOffset , utcOffsets -- ** Abbreviations , TimeZoneAbbr(..) , abbreviate , unabbreviate , abbreviations ) where import Control.Arrow (first) import Data.Aeson (FromJSON, ToJSON) import Data.Map.Strict (Map, (!), fromDistinctAscList) import Data.Typeable (Typeable) import GHC.Generics (Generic) import System.Random (Random(..)) -- | Cities from around the world. data City = Aden -- ^ Yemeni Republic | Amman -- ^ Hashemite Kingdom of Jordan | Anchorage -- ^ United States of America | Auckland -- ^ New Zealand | Baghdad -- ^ Republic of Iraq | Berlin -- ^ Federal Republic of Germany | Brussels -- ^ Kingdom of Belgium | Bujumbura -- ^ Republic of Burundi | Cairo -- ^ Arab Republic of Egypt | Chicago -- ^ United States of America | Damascus -- ^ Syrian Arab Republic | Denver -- ^ United States of America | Doha -- ^ State of Qatar | Gaborone -- ^ Republic of Botswana | Hong_Kong -- ^ People's Republic of China | Honolulu -- ^ United States of America | Johannesburg -- ^ Republic of South Africa | Kabul -- ^ Islamic Republic of Afghanistan | Karachi -- ^ Islamic Republic of Pakistan | Kinshasa -- ^ Democratic Republic of the Congo | Kolkata -- ^ Republic of India | Kuwait_City -- ^ State of Kuwait | London -- ^ United Kingdom of Great Britain and Northern Ireland | Los_Angeles -- ^ United States of America | Luanda -- ^ Republic of Angola | Manama -- ^ Kingdom of Bahrain | Minsk -- ^ Republic of Belarus | Mogadishu -- ^ Federal Republic of Somalia | Moscow -- ^ Russian Federation | New_York -- ^ United States of America | Oslo -- ^ Kingdom of Norway | Ouagadougou -- ^ Burkina Faso | Paris -- ^ French Republic | Pyongyang -- ^ Democratic People's Republic of Korea | Riyadh -- ^ Kingdom of Saudi Arabia | Sao_Paulo -- ^ Federative Republic of Brazil | Sarajevo -- ^ Bosnia and Herzegovina | Seoul -- ^ Republic of Korea | Shanghai -- ^ People's Republic of China | Singapore -- ^ Republic of Singapore | Sofia -- ^ Republic of Bulgaria | Stockholm -- ^ Kingdom of Sweden | Tehran -- ^ Islamic Republic of Iran | Tel_Aviv -- ^ State of Israel | Tirana -- ^ Republic of Albania | Tokyo -- ^ Japan | Toronto -- ^ Canada | Universal -- ^ International Territory | Vienna -- ^ Republic of Austria | Zurich -- ^ Swiss Confederation deriving (Eq,Enum,Generic,Ord,Read,Show,Typeable) instance Bounded City where minBound = Aden maxBound = Zurich instance FromJSON City instance Random City where random = first toEnum . randomR (fromEnum (minBound::City), fromEnum (maxBound::City)) randomR (a,b) = first toEnum . randomR (fromEnum a, fromEnum b) instance ToJSON City -- | A list of cities in alphabetical order. 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 ] -- | Get the Olson file associated with the given city. getOlsonFile :: City -> FilePath getOlsonFile = (!) olsonFiles -- | A map from cities to Olson file paths. olsonFiles :: Map City FilePath olsonFiles = fromDistinctAscList [ (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") , (Kolkata,"/usr/share/zoneinfo/Asia/Kolkata") , (Kuwait_City,"/usr/share/zoneinfo/Asia/Kuwait") , (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") ] -- | Time zones from around the world. 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,Ord,Read,Show,Typeable) instance Bounded TimeZone where minBound = Afghanistan_Time maxBound = Yukon_Standard_Time instance FromJSON TimeZone instance Random TimeZone where random = first toEnum . randomR (fromEnum (minBound::TimeZone), fromEnum (maxBound::TimeZone)) randomR (a,b) = first toEnum . randomR (fromEnum a, fromEnum b) instance ToJSON TimeZone -- | The UTC time zone. utc :: TimeZone utc = Coordinated_Universal_Time -- | Get the UTC offset (in minutes) for the given time zone. getUTCOffset :: Num a => TimeZone -> a getUTCOffset = (!) utcOffsets -- | A map from time zones to UTC offsets (in minutes). utcOffsets :: Num a => Map TimeZone a utcOffsets = fromDistinctAscList [ (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,60) , (Central_Africa_Time,120) , (Central_Daylight_Time,-300) , (Central_European_Summer_Time,120) , (Central_European_Time,60) , (Central_Standard_Time,-360) , (China_Daylight_Time,540) , (China_Standard_Time,480) , (Coordinated_Universal_Time,0) , (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,0) , (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,60) , (Yukon_Standard_Time,-540) ] -- | A time zone abbreviation. data TimeZoneAbbr = TimeZoneAbbr { abbr_city :: City -- ^ reference location , abbr_str :: String -- ^ time zone abbreviation string } deriving (Eq,Generic,Typeable) instance FromJSON TimeZoneAbbr instance Show TimeZoneAbbr where show TimeZoneAbbr{abbr_str} = abbr_str instance ToJSON TimeZoneAbbr -- | Abbreviate a time zone. abbreviate :: TimeZone -> TimeZoneAbbr abbreviate = (!) abbreviations -- | Unabbreviate a time zone. unabbreviate :: TimeZoneAbbr -> TimeZone unabbreviate 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 ++ "'" -- | A map from time zones to time zone abbreviations. abbreviations :: Map TimeZone TimeZoneAbbr abbreviations = fromDistinctAscList [ (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_Summer_Time,TimeZoneAbbr Hong_Kong "HKST") , (Hong_Kong_Time,TimeZoneAbbr Hong_Kong "HKT") , (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") ]