module Data.Time.Exts.Base (
Human(..)
, Math(..)
, Calendar(..)
, Epoch(..)
, Era
, Year(..)
, Month(..)
, Day(..)
, DayOfWeek(..)
, Hour(..)
, Minute(..)
, Second(..)
, Millis(..)
, Micros(..)
, Nanos(..)
, Picos(..)
, DateStruct(..)
, TimeStruct(..)
, DateTimeStruct(..)
, LocalDateStruct(..)
, LocalTimeStruct(..)
, LocalDateTimeStruct(..)
, properFracMillis
, properFracMicros
, properFracNanos
, properFracPicos
) where
import Control.DeepSeq (NFData(..))
import Data.Data (Data, Typeable)
import Data.Int (Int32, Int64)
import Data.Time (TimeZone)
import GHC.Generics (Generic)
import Text.Printf (PrintfArg)
class Human x where
type Components x :: *
pack :: Components x -> x
unpack :: x -> Components x
class Math x c where
duration :: x -> x -> c
plus :: x -> c -> x
data Calendar =
Chinese
| Gregorian
| Hebrew
| Islamic
| Julian
deriving (Bounded, Data, Enum, Eq, Generic, Ord, Read, Show, Typeable)
instance NFData Calendar
data Epoch =
Unix
deriving (Bounded, Data, Enum, Eq, Generic, Ord, Read, Show, Typeable)
instance NFData Epoch
data family Era (cal :: Calendar) :: *
data instance Era 'Gregorian =
BeforeChrist
| AnnoDomini
deriving (Bounded, Data, Enum, Eq, Generic, Ord, Read, Show, Typeable)
instance NFData (Era 'Gregorian)
newtype Year = Year {getYear :: Int32}
deriving (Bounded, Data, Enum, Eq, Generic, Integral, NFData, Num, Ord, PrintfArg, Read, Real, Typeable)
instance Show Year where
show Year {..} = show getYear
data family Month (cal :: Calendar) :: *
data instance Month 'Gregorian =
January
| February
| March
| April
| May
| June
| July
| August
| September
| October
| November
| December
deriving (Bounded, Data, Eq, Generic, Ord, Read, Show, Typeable)
instance Enum (Month 'Gregorian) where
fromEnum January = 01
fromEnum February = 02
fromEnum March = 03
fromEnum April = 04
fromEnum May = 05
fromEnum June = 06
fromEnum July = 07
fromEnum August = 08
fromEnum September = 09
fromEnum October = 10
fromEnum November = 11
fromEnum December = 12
toEnum 01 = January
toEnum 02 = February
toEnum 03 = March
toEnum 04 = April
toEnum 05 = May
toEnum 06 = June
toEnum 07 = July
toEnum 08 = August
toEnum 09 = September
toEnum 10 = October
toEnum 11 = November
toEnum 12 = December
toEnum __ = error "toEnum{Month 'Gregorian}: out of range"
instance NFData (Month 'Gregorian)
newtype Day = Day {getDay :: Int32}
deriving (Bounded, Data, Enum, Eq, Generic, Integral, NFData, Num, Ord, PrintfArg, Read, Real, Typeable)
instance Show Day where
show Day {..} = show getDay
data family DayOfWeek (cal :: Calendar) :: *
data instance DayOfWeek 'Gregorian =
Sunday
| Monday
| Tuesday
| Wednesday
| Thursday
| Friday
| Saturday
deriving (Bounded, Data, Eq, Generic, Ord, Read, Show, Typeable)
instance Enum (DayOfWeek 'Gregorian) where
fromEnum Sunday = 1
fromEnum Monday = 2
fromEnum Tuesday = 3
fromEnum Wednesday = 4
fromEnum Thursday = 5
fromEnum Friday = 6
fromEnum Saturday = 7
toEnum 1 = Sunday
toEnum 2 = Monday
toEnum 3 = Tuesday
toEnum 4 = Wednesday
toEnum 5 = Thursday
toEnum 6 = Friday
toEnum 7 = Saturday
toEnum _ = error "toEnum{DayOfWeek 'Gregorian}: out of range"
instance NFData (DayOfWeek 'Gregorian)
newtype Hour = Hour {getHour :: Int64}
deriving (Bounded, Data, Enum, Eq, Generic, Integral, NFData, Num, Ord, PrintfArg, Read, Real, Typeable)
instance Show Hour where
show Hour {..} = show getHour
newtype Minute = Minute {getMinute :: Int64}
deriving (Bounded, Data, Enum, Eq, Generic, Integral, NFData, Num, Ord, PrintfArg, Read, Real, Typeable)
instance Show Minute where
show Minute {..} = show getMinute
newtype Second = Second {getSecond :: Int64}
deriving (Bounded, Data, Enum, Eq, Generic, Integral, NFData, Num, Ord, PrintfArg, Read, Real, Typeable)
instance Show Second where
show Second {..} = show getSecond
newtype Millis = Millis {getMillis :: Int64}
deriving (Bounded, Data, Enum, Eq, Generic, Integral, NFData, Num, Ord, PrintfArg, Read, Real, Typeable)
instance Show Millis where
show Millis {..} = show getMillis
newtype Micros = Micros {getMicros :: Int64}
deriving (Bounded, Data, Enum, Eq, Generic, Integral, NFData, Num, Ord, PrintfArg, Read, Real, Typeable)
instance Show Micros where
show Micros {..} = show getMicros
newtype Nanos = Nanos {getNanos :: Int64}
deriving (Bounded, Data, Enum, Eq, Generic, Integral, NFData, Num, Ord, PrintfArg, Read, Real, Typeable)
instance Show Nanos where
show Nanos {..} = show getNanos
newtype Picos = Picos {getPicos :: Int64}
deriving (Bounded, Data, Enum, Eq, Generic, Integral, NFData, Num, Ord, PrintfArg, Read, Real, Typeable)
instance Show Picos where
show Picos {..} = show getPicos
data DateStruct (cal :: Calendar) =
DateStruct
{ _d_year :: !Year
, _d_mon :: !(Month cal)
, _d_mday :: !Day
, _d_wday :: !(DayOfWeek cal)
} deriving (Generic, Typeable)
data TimeStruct =
TimeStruct
{ _t_hour :: !Hour
, _t_min :: !Minute
, _t_sec :: !Double
} deriving (Data, Eq, Generic, Show, Typeable)
data DateTimeStruct (cal :: Calendar) =
DateTimeStruct
{ _dt_year :: !Year
, _dt_mon :: !(Month cal)
, _dt_mday :: !Day
, _dt_wday :: !(DayOfWeek cal)
, _dt_hour :: !Hour
, _dt_min :: !Minute
, _dt_sec :: !Double
} deriving (Generic, Typeable)
data LocalDateStruct (cal :: Calendar) =
LocalDateStruct
{ _ld_year :: !Year
, _ld_mon :: !(Month cal)
, _ld_mday :: !Day
, _ld_wday :: !(DayOfWeek cal)
, _ld_zone :: !TimeZone
} deriving (Generic, Typeable)
data LocalTimeStruct =
LocalTimeStruct
{ _lt_hour :: !Hour
, _lt_min :: !Minute
, _lt_sec :: !Double
, _lt_zone :: !TimeZone
} deriving (Data, Eq, Generic, Show, Typeable)
data LocalDateTimeStruct (cal :: Calendar) =
LocalDateTimeStruct
{ _ldt_year :: !Year
, _ldt_mon :: !(Month cal)
, _ldt_mday :: !Day
, _ldt_wday :: !(DayOfWeek cal)
, _ldt_hour :: !Hour
, _ldt_min :: !Minute
, _ldt_sec :: !Double
, _ldt_zone :: !TimeZone
} deriving (Generic, Typeable)
deriving instance (Data (Month cal), Data (DayOfWeek cal), Typeable cal) => Data (DateStruct cal)
deriving instance (Data (Month cal), Data (DayOfWeek cal), Typeable cal) => Data (DateTimeStruct cal)
deriving instance (Data (Month cal), Data (DayOfWeek cal), Typeable cal) => Data (LocalDateStruct cal)
deriving instance (Data (Month cal), Data (DayOfWeek cal), Typeable cal) => Data (LocalDateTimeStruct cal)
deriving instance (Eq (Month cal), Eq (DayOfWeek cal)) => Eq (DateStruct cal)
deriving instance (Eq (Month cal), Eq (DayOfWeek cal)) => Eq (DateTimeStruct cal)
deriving instance (Eq (Month cal), Eq (DayOfWeek cal)) => Eq (LocalDateStruct cal)
deriving instance (Eq (Month cal), Eq (DayOfWeek cal)) => Eq (LocalDateTimeStruct cal)
deriving instance (Show (Month cal), Show (DayOfWeek cal)) => Show (DateStruct cal)
deriving instance (Show (Month cal), Show (DayOfWeek cal)) => Show (DateTimeStruct cal)
deriving instance (Show (Month cal), Show (DayOfWeek cal)) => Show (LocalDateStruct cal)
deriving instance (Show (Month cal), Show (DayOfWeek cal)) => Show (LocalDateTimeStruct cal)
instance (NFData (Month cal), NFData (DayOfWeek cal)) => NFData (DateStruct cal)
instance (NFData (Month cal), NFData (DayOfWeek cal)) => NFData (DateTimeStruct cal)
instance (NFData (Month cal), NFData (DayOfWeek cal)) => NFData (LocalDateStruct cal)
instance (NFData (Month cal), NFData (DayOfWeek cal)) => NFData (LocalDateTimeStruct cal)
instance NFData TimeStruct
instance NFData LocalTimeStruct
properFracMillis :: RealFrac a => a -> (Second, Millis)
properFracMillis frac = if millis == 1000 then (sec + 1, 0) else res
where res@(sec, millis) = fmap (round . (*) 1000) $ properFraction frac
properFracMicros :: RealFrac a => a -> (Second, Micros)
properFracMicros frac = if micros == 1000000 then (sec + 1, 0) else res
where res@(sec, micros) = fmap (round . (*) 1000000) $ properFraction frac
properFracNanos :: RealFrac a => a -> (Second, Nanos)
properFracNanos frac = if nanos == 1000000000 then (sec + 1, 0) else res
where res@(sec, nanos) = fmap (round . (*) 1000000000) $ properFraction frac
properFracPicos :: RealFrac a => a -> (Second, Picos)
properFracPicos frac = if picos == 1000000000000 then (sec + 1, 0) else res
where res@(sec, picos) = fmap (round . (*) 1000000000000) $ properFraction frac