PageRenderTime 16ms CodeModel.GetById 13ms app.highlight 2ms RepoModel.GetById 0ms app.codeStats 1ms

/Data/Time/LocalTime/TimeZone.hs

http://github.com/takano-akio/time
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