module Data.Time.Hora.Type (-- * DatePart DatePart(..), -- * DatePartSmall DatePartSmall(Day, Min, Ms, Time, DatePartSmall, Day', Min', Ms', Error), toSpan, negate, isNegative, ErrorDetail(..), -- * UTCTimeBin UTCTimeBin(..), -- * Tz Tz(..), Tz'(..), -- * TimeSpan TimeSpan(..), TwoInt(..)) where import Data.Binary import Data.Time.Clock import Data.Time.Hora.Internal.DatePartSmall import Data.Time.Hora.Internal.Span import Data.Time.LocalTime import Data.Time.LocalTime.TimeZone.Series import GHC.Generics import Prelude hiding (negate) {- | serializeable structure for essential Date, Time parts may also be used to construct 'UTCTime' see "Data.Time.Hora.Part" for conversion between 'UTCTime' and 'DatePart' -} data DatePart a = DatePart { year::a, month::a, day::a, hour::a, minute::a, second::a, pico::a -- ^ excludes seconds. Just fraction as Integral } deriving (Show, Generic) instance Functor DatePart where fmap f0 d0 = d0 { day = f0 (day d0), month = f0 (month d0), year = f0 (year d0), hour = f0 (hour d0), minute = f0 (minute d0), second = f0 (second d0), pico = f0 (pico d0) } -- ^ for ease of conversion instance Binary (DatePart Int) -- ^ serializeable instance Binary (DatePart Integer) -- ^ serializeable instance Binary (DatePart String) -- ^ serializeable deriving instance Eq a => Eq (DatePart a) instance Ord a => Ord (DatePart a) where (<=) a0 b0 = let y1 = (year a0, year b0) m1 = (month a0, month b0) d1 = (day a0, day b0) h1 = (hour a0, hour b0) min1 = (minute a0, minute b0) s1 = (second a0, second b0) p1 = (pico a0, pico b0) l1 = [y1,m1,d1,h1,min1,s1,p1] f1 (Stop bo1) _ = Stop bo1 f1 Continue (a1, b1) | a1 < b1 = Stop True | a1 == b1 = Continue | a1 > b1 = Stop False res2 = foldl f1 Continue l1 in case res2 of Continue -> True (Stop b2) -> b2 -- private data Ord_ = Stop Bool | Continue {- | 'UTCTimeBin' closely mimicks 'UTCTime' without loss of precision 'UTCTimeBin' has 'Binary' instance. The only purpose of 'UTCTimeBin' is to offer faster conversion from / to 'UTCTime' and more compact serialization compared with 'DatePart'. see "Data.Time.Hora.Part" for conversion between 'UTCTime' and 'UTCTimeBin' -} data UTCTimeBin = UTCTimeBin { modifiedJulianDay::Integer, -- ^ The Modified Julian Day is a standard count of days, with zero being the day 1858-11-17 diffTimeAsPicoseconds::Integer -- ^ 'DiffTime' expressed as picoseconds } deriving (Eq, Show, Generic) instance Binary UTCTimeBin -- ^ serializeable {-| 'Tz' ('DatePart' a) parts show local date & time for conversions between timezones see "Data.Time.Hora.Zone" -} data Tz a = Tz TimeZone a deriving (Show,Functor) deriving instance Eq a => Eq (Tz a) deriving instance Ord a => Ord (Tz a) -- | 'TimeZone' | 'TimeZoneSeries' class Tz' tz where tz'::tz -> UTCTime -> TimeZone instance Tz' TimeZone where tz' tz0 _ = tz0 instance Tz' TimeZoneSeries where tz' = timeZoneFromSeries {- ^ see "Data.Time.Hora.Zone" re: 'TimeZoneSeries' use of 'TimeZoneSeries' is preferred when converting from 'UTCTime' to 'DatePart' -} {- | ! fromInteger returns 'Pico'. assumes the value is Pico seconds >>> Milli 397100 + (Sec 2) + 37891470000 Pico 399137891470000 >>> Milli 397100 + (Sec 2) + (Pico 37891470000) Pico 399137891470000 >>> 3 * (Sec 10) == (Sec 30) True >>> 3 * (Pico 10) == (Pico 30) True >>> 300 * (Milli 1000) == (Milli 300000) True -} instance Integral a => Num (TimeSpan a) where (+) = withPico (+) (*) = withPico (*) abs a0 = if a0 > Pico 0 then a0 else - a0 signum a0 | a0 > Pico 0 = 1 | a0 < Pico 0 = - 1 | otherwise = 0 fromInteger i0 = Pico $ fromIntegral i0 (-) = withPico (-) {- | >>> Sec 1 == Milli 1000 True -} instance (Eq a, Integral a) => Eq (TimeSpan a) where (==) (Sec a0) (Sec b0) = a0 == b0 (==) (Milli a0) (Milli b0) = a0 == b0 (==) (Pico a0) (Pico b0) = a0 == b0 (==) a0 b0 = a1 == b1 where a1 = toPico a0::Integer b1 = toPico b0::Integer {- | >>> Sec 1 > Milli 500 True -} instance (Ord a, Integral a) => Ord (TimeSpan a) where (<=) (Sec a0) (Sec b0) = a0 <= b0 (<=) (Milli a0) (Milli b0) = a0 <= b0 (<=) (Pico a0) (Pico b0) = a0 <= b0 (<=) a0 b0 = a1 <= b1 where a1 = toPico a0::Integer b1 = toPico b0::Integer