-- | -- Module : Data.Hourglass.Local -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : unknown -- -- Local time = global time + timezone -- {-# LANGUAGE FlexibleInstances #-} module Data.Hourglass.Local ( -- * Local time -- ** Local time type LocalTime -- ** Local time creation and manipulation , localTime , localTimeUnwrap , localTimeToGlobal , localTimeFromGlobal , localTimeGetTimezone , localTimeSetTimezone , localTimeConvert ) where import Data.Hourglass.Types import Data.Hourglass.Time import Data.Hourglass.Diff -- | Local time representation -- -- this is a time representation augmented by a timezone -- to get back to a global time, the timezoneOffset needed to be added to the local time. -- data LocalTime t = LocalTime { localTimeUnwrap :: t -- ^ unwrap the LocalTime value. the time value is local. , localTimeGetTimezone :: TimezoneOffset -- ^ get the timezone associated with LocalTime } -- FIXME add instance Read too. instance Show t => Show (LocalTime t) where show (LocalTime t tz) = show t ++ show tz instance Eq t => Eq (LocalTime t) where LocalTime t1 tz1 == LocalTime t2 tz2 = tz1 == tz2 && t1 == t2 instance (Ord t, Time t) => Ord (LocalTime t) where compare l1@(LocalTime g1 tz1) l2@(LocalTime g2 tz2) = case compare tz1 tz2 of EQ -> compare g1 g2 _ -> let t1 = localTimeToGlobal l1 t2 = localTimeToGlobal l2 in compare t1 t2 instance Functor LocalTime where fmap f (LocalTime t tz) = LocalTime (f t) tz -- | Create a local time type from a timezone and a time type. -- -- The time value is assumed to be local to the timezone offset set, -- so no transformation is done. localTime :: Time t => TimezoneOffset -> t -> LocalTime t localTime tz t = LocalTime t tz -- | Get back a global time value localTimeToGlobal :: Time t => LocalTime t -> t localTimeToGlobal (LocalTime local tz) | tz == TimezoneOffset 0 = local | otherwise = timeConvert $ elapsedTimeAddSecondsP (timeGetElapsedP local) tzSecs where tzSecs = negate $ timezoneOffsetToSeconds tz -- | create a local time value from a global one localTimeFromGlobal :: Time t => t -> LocalTime t localTimeFromGlobal = localTime (TimezoneOffset 0) -- | Change the timezone, and adjust the local value to represent the new local value. localTimeSetTimezone :: Time t => TimezoneOffset -> LocalTime t -> LocalTime t localTimeSetTimezone tz currentLocal@(LocalTime t currentTz) | diffTz == 0 = currentLocal | otherwise = LocalTime (timeConvert t') tz where t' = elapsedTimeAddSecondsP (timeGetElapsedP t) diffTz diffTz = timezoneOffsetToSeconds tz - timezoneOffsetToSeconds currentTz -- | convert the local time representation to another time representation determined by context. localTimeConvert :: (Time t1, Time t2) => LocalTime t1 -> LocalTime t2 localTimeConvert = fmap timeConvert