/Data/Time/LocalTime/TimeZone.hs
Haskell | 99 lines | 63 code | 18 blank | 18 comment | 1 complexity | 1b328d2f5b8108407d73500a1d6620d0 MD5 | raw file
Possible License(s): BSD-3-Clause
1{-# OPTIONS -fno-warn-unused-imports #-} 2{-# LANGUAGE ForeignFunctionInterface #-} 3#include "HsConfigure.h" 4 5-- #hide 6module Data.Time.LocalTime.TimeZone 7( 8 -- * Time zones 9 TimeZone(..),timeZoneOffsetString,timeZoneOffsetString',minutesToTimeZone,hoursToTimeZone,utc, 10 11 -- getting the locale time zone 12 getTimeZone,getCurrentTimeZone 13) where 14 15--import System.Time.Calendar.Format 16import Data.Time.Calendar.Private 17import Data.Time.Clock 18import Data.Time.Clock.POSIX 19 20import Foreign 21import Foreign.C 22import Control.DeepSeq 23import Data.Typeable 24#if LANGUAGE_Rank2Types 25import Data.Data 26#endif 27 28-- | A TimeZone is a whole number of minutes offset from UTC, together with a name and a \"just for summer\" flag. 29data TimeZone = TimeZone { 30 -- | The number of minutes offset from UTC. Positive means local time will be later in the day than UTC. 31 timeZoneMinutes :: Int, 32 -- | Is this time zone just persisting for the summer? 33 timeZoneSummerOnly :: Bool, 34 -- | The name of the zone, typically a three- or four-letter acronym. 35 timeZoneName :: String 36} deriving (Eq,Ord 37#if LANGUAGE_DeriveDataTypeable 38#if LANGUAGE_Rank2Types 39 ,Data 40#endif 41#endif 42 ) 43 44instance NFData TimeZone where 45 rnf (TimeZone m so n) = m `deepseq` so `deepseq` n `deepseq` () 46 47instance Typeable TimeZone where 48 typeOf _ = mkTyConApp (mkTyCon "Data.Time.LocalTime.TimeZone.TimeZone") [] 49 50-- | Create a nameless non-summer timezone for this number of minutes 51minutesToTimeZone :: Int -> TimeZone 52minutesToTimeZone m = TimeZone m False "" 53 54-- | Create a nameless non-summer timezone for this number of hours 55hoursToTimeZone :: Int -> TimeZone 56hoursToTimeZone i = minutesToTimeZone (60 * i) 57 58showT :: NumericPadOption -> Int -> String 59showT opt t = show4 opt ((div t 60) * 100 + (mod t 60)) 60 61-- | Text representing the offset of this timezone, such as \"-0800\" or \"+0400\" (like %z in formatTime), with arbitrary padding 62timeZoneOffsetString' :: NumericPadOption -> TimeZone -> String 63timeZoneOffsetString' opt (TimeZone t _ _) | t < 0 = '-':(showT opt (negate t)) 64timeZoneOffsetString' opt (TimeZone t _ _) = '+':(showT opt t) 65 66-- | Text representing the offset of this timezone, such as \"-0800\" or \"+0400\" (like %z in formatTime) 67timeZoneOffsetString :: TimeZone -> String 68timeZoneOffsetString = timeZoneOffsetString' (Just '0') 69 70instance Show TimeZone where 71 show zone@(TimeZone _ _ "") = timeZoneOffsetString zone 72 show (TimeZone _ _ name) = name 73 74-- | The UTC time zone 75utc :: TimeZone 76utc = TimeZone 0 False "UTC" 77 78{-# CFILES cbits/HsTime.c #-} 79foreign import ccall unsafe "HsTime.h get_current_timezone_seconds" get_current_timezone_seconds :: CTime -> Ptr CInt -> Ptr CString -> IO CLong 80 81posixToCTime :: POSIXTime -> CTime 82posixToCTime = fromInteger . floor 83 84-- | Get the local time-zone for a given time (varying as per summertime adjustments) 85getTimeZone :: UTCTime -> IO TimeZone 86getTimeZone time = with 0 (\pdst -> with nullPtr (\pcname -> do 87 secs <- get_current_timezone_seconds (posixToCTime (utcTimeToPOSIXSeconds time)) pdst pcname 88 case secs of 89 0x80000000 -> fail "localtime_r failed" 90 _ -> do 91 dst <- peek pdst 92 cname <- peek pcname 93 name <- peekCString cname 94 return (TimeZone (div (fromIntegral secs) 60) (dst == 1) name) 95 )) 96 97-- | Get the current time-zone 98getCurrentTimeZone :: IO TimeZone 99getCurrentTimeZone = getCurrentTime >>= getTimeZone