module Data.Thyme.LocalTime (
T.TimeZone (..)
, T.timeZoneOffsetString
, T.timeZoneOffsetString'
, T.minutesToTimeZone
, T.hoursToTimeZone
, T.utc
, T.getCurrentTimeZone
, module Data.Thyme.LocalTime
) where
import Prelude hiding ((.))
import Control.Applicative
import Control.Category
import Control.Lens
import Control.Monad
import Data.AffineSpace
import Data.Data
import Data.Micro
import qualified Data.Time as T
import Data.Thyme.Calendar.Internal
import Data.Thyme.Clock
import Data.Thyme.Clock.Scale
import Data.Thyme.Clock.UTC
import Data.Thyme.TH
import Data.VectorSpace
getTimeZone :: UTCTime -> IO T.TimeZone
getTimeZone time = T.getTimeZone (T.UTCTime day dayTime) where
day = T.ModifiedJulianDay (fromIntegral mjd)
dayTime = fromRational $ dt ^/^ DiffTime (toMicro 1)
UTCTime (ModifiedJulianDay mjd) dt = view utcTime time
type Hour = Int
type Minute = Int
data TimeOfDay = TimeOfDay
{ todHour :: !Hour
, todMin :: !Minute
, todSec :: !DiffTime
} deriving (Eq, Ord, Data, Typeable, Show)
makeTimeOfDayValid :: Hour -> Minute -> DiffTime -> Maybe TimeOfDay
makeTimeOfDayValid h m s@(DiffTime u) = TimeOfDay h m s
<$ guard (0 <= h && h <= 23 && 0 <= m && m <= 59)
<* guard (Micro 0 <= u && u < Micro 61000000)
timeOfDay :: Simple Iso DiffTime TimeOfDay
timeOfDay = iso fromDiff toDiff where
fromDiff :: DiffTime -> TimeOfDay
fromDiff (DiffTime t) = TimeOfDay
(fromIntegral h) (fromIntegral m) (DiffTime s) where
(h, ms) = microQuotRem t (toMicro 3600)
(m, s) = microQuotRem ms (toMicro 60)
toDiff :: TimeOfDay -> DiffTime
toDiff (TimeOfDay h m s) = s
^+^ fromIntegral m *^ DiffTime (toMicro 60)
^+^ fromIntegral h *^ DiffTime (toMicro 3600)
type Minutes = Int
type Days = Int
addMinutes :: Minutes -> TimeOfDay -> (Days, TimeOfDay)
addMinutes dm (TimeOfDay h m s) = (dd, TimeOfDay h' m' s) where
(dd, h') = divMod (h + dh) 24
(dh, m') = divMod (m + dm) 60
timeOfDayFraction :: Simple Iso Rational TimeOfDay
timeOfDayFraction = iso fromRatio toRatio . timeOfDay where
NominalDiffTime posixDay = posixDayLength
fromRatio :: Rational -> DiffTime
fromRatio r = DiffTime (r *^ posixDay) where
toRatio :: DiffTime -> Rational
toRatio (DiffTime t) = t ^/^ posixDay
data LocalTime = LocalTime
{ localDay :: !Day
, localTimeOfDay :: !TimeOfDay
} deriving (Eq, Ord, Data, Typeable, Show)
utcLocalTime :: T.TimeZone -> Simple Iso UTCTime LocalTime
utcLocalTime T.TimeZone {..} = utcTime . iso localise globalise where
localise :: UTCView -> LocalTime
localise (UTCTime day dt) = LocalTime (day .+^ dd) tod where
(dd, tod) = addMinutes timeZoneMinutes (view timeOfDay dt)
globalise :: LocalTime -> UTCView
globalise (LocalTime day tod) = UTCTime (day .+^ dd)
(review timeOfDay utcToD) where
(dd, utcToD) = addMinutes (negate timeZoneMinutes) tod
data ZonedTime = ZonedTime
{ zonedTimeToLocalTime :: !LocalTime
, zonedTimeZone :: !T.TimeZone
} deriving (Eq, Ord, Data, Typeable, Show)
zonedTime :: Simple Iso (T.TimeZone, UTCTime) ZonedTime
zonedTime = iso toZoned fromZoned where
toZoned :: (T.TimeZone, UTCTime) -> ZonedTime
toZoned (tz, time) = ZonedTime (view (utcLocalTime tz) time) tz
fromZoned :: ZonedTime -> (T.TimeZone, UTCTime)
fromZoned (ZonedTime lt tz) = (tz, review (utcLocalTime tz) lt)
getZonedTime :: IO ZonedTime
getZonedTime = utcToLocalZonedTime =<< getCurrentTime
utcToLocalZonedTime :: UTCTime -> IO ZonedTime
utcToLocalZonedTime time = do
tz <- getTimeZone time
return (view zonedTime (tz, time))
thymeLenses ''T.TimeZone
thymeLenses ''TimeOfDay
thymeLenses ''LocalTime
thymeLenses ''ZonedTime