time-exts-1.0.0: src/Data/Time/Exts/Zone.hs
---------------------------------------------------------------
-- Copyright (c) 2013, Enzo Haussecker. All rights reserved. --
---------------------------------------------------------------
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RecordWildCards #-}
{-# OPTIONS -Wall #-}
{-# OPTIONS -fno-warn-type-defaults #-}
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 -- ^ 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 -- ^ Tnternational Territory
| Vienna -- ^ Republic of Austria
| Zurich -- ^ Swiss Confederation
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 -- ^ Reference location
, abbr_str :: String -- ^ Time zone abbreviation 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
-- | 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
]
-- | Returns the Olson file associated with the given city.
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"
-- | Returns the offset (in minutes) for the given time zone.
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