{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

#include "thyme.h"

module Data.Thyme.LocalTime where

import Prelude hiding ((.))
import Control.Applicative
import Control.Arrow
import Control.Category hiding (id)
import Control.DeepSeq
import Control.Lens
import Control.Monad
import Data.AffineSpace
import Data.Bits
import Data.Data
import Data.Int
import Data.Thyme.Internal.Micro
import Data.Thyme.Calendar
import Data.Thyme.Calendar.Internal
import Data.Thyme.Clock
import Data.Thyme.Clock.Internal
import Data.Thyme.Format.Internal
import qualified Data.Time as T
#if __GLASGOW_HASKELL__ == 704
import qualified Data.Vector.Generic
import qualified Data.Vector.Generic.Mutable
#endif
import Data.Vector.Unboxed.Deriving
import Data.VectorSpace
import GHC.Generics (Generic)
import System.Random
import Test.QuickCheck hiding ((.&.))

type Minutes = Int
type Hours = Int

------------------------------------------------------------------------
-- * Time zones

data TimeZone = TimeZone
    { TimeZone -> Minutes
timeZoneMinutes :: {-# UNPACK #-}!Minutes
    , TimeZone -> Bool
timeZoneSummerOnly :: !Bool
    , TimeZone -> String
timeZoneName :: String
    } deriving (INSTANCES_USUAL)

instance NFData TimeZone

#if SHOW_INTERNAL
deriving instance Show TimeZone
#else
instance Show TimeZone where
    show :: TimeZone -> String
show tz :: TimeZone
tz@TimeZone {..} = if String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
timeZoneName
        then TimeZone -> String
timeZoneOffsetString TimeZone
tz else String
timeZoneName
#endif

instance Bounded TimeZone where
    minBound :: TimeZone
minBound = Minutes -> Bool -> String -> TimeZone
TimeZone (-12 Minutes -> Minutes -> Minutes
forall a. Num a => a -> a -> a
* 60) Bool
forall a. Bounded a => a
minBound "AAAA"
    maxBound :: TimeZone
maxBound = Minutes -> Bool -> String -> TimeZone
TimeZone (13 Minutes -> Minutes -> Minutes
forall a. Num a => a -> a -> a
* 60) Bool
forall a. Bounded a => a
maxBound "ZZZZ"

instance Random TimeZone where
    randomR :: (TimeZone, TimeZone) -> g -> (TimeZone, g)
randomR (l :: TimeZone
l, u :: TimeZone
u) g0 :: g
g0 = (Minutes -> Bool -> String -> TimeZone
TimeZone Minutes
minutes Bool
summer String
name, g
g3) where
        (minutes :: Minutes
minutes, g1 :: g
g1) = (Minutes, Minutes) -> g -> (Minutes, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (TimeZone -> Minutes
timeZoneMinutes TimeZone
l, TimeZone -> Minutes
timeZoneMinutes TimeZone
u) g
g0
        (summer :: Bool
summer, g2 :: g
g2) = (Bool, Bool) -> g -> (Bool, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (TimeZone -> Bool
timeZoneSummerOnly TimeZone
l, TimeZone -> Bool
timeZoneSummerOnly TimeZone
u) g
g1
        -- slightly dubious interpretation of ‘range’
        (name :: String
name, g3 :: g
g3) = ((Char, Char) -> (String, g) -> (String, g))
-> (String, g) -> [(Char, Char)] -> (String, g)
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Char, Char) -> (String, g) -> (String, g)
forall a g.
(Random a, RandomGen g) =>
(a, a) -> ([a], g) -> ([a], g)
randChar ([], g
g2) ([(Char, Char)] -> (String, g))
-> ([(Char, Char)] -> [(Char, Char)])
-> [(Char, Char)]
-> (String, g)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Minutes -> [(Char, Char)] -> [(Char, Char)]
forall a. Minutes -> [a] -> [a]
take 4 ([(Char, Char)] -> (String, g)) -> [(Char, Char)] -> (String, g)
forall a b. (a -> b) -> a -> b
$ String -> String -> [(Char, Char)]
forall a b. [a] -> [b] -> [(a, b)]
zip
            (TimeZone -> String
timeZoneName TimeZone
l String -> ShowS
forall a. [a] -> [a] -> [a]
++ "AAAA") (TimeZone -> String
timeZoneName TimeZone
u String -> ShowS
forall a. [a] -> [a] -> [a]
++ "ZZZZ")
        randChar :: (a, a) -> ([a], g) -> ([a], g)
randChar nR :: (a, a)
nR (ns :: [a]
ns, g :: g
g) = (a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
ns) (a -> [a]) -> (a, g) -> ([a], g)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
`first` (a, a) -> g -> (a, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (a, a)
nR g
g
    random :: g -> (TimeZone, g)
random = (TimeZone, TimeZone) -> g -> (TimeZone, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (TimeZone
forall a. Bounded a => a
minBound, TimeZone
forall a. Bounded a => a
maxBound)

instance Arbitrary TimeZone where
    arbitrary :: Gen TimeZone
arbitrary = (TimeZone, TimeZone) -> Gen TimeZone
forall a. Random a => (a, a) -> Gen a
choose (TimeZone
forall a. Bounded a => a
minBound, TimeZone
forall a. Bounded a => a
maxBound)
    shrink :: TimeZone -> [TimeZone]
shrink tz :: TimeZone
tz@TimeZone {..}
        = [ TimeZone
tz {timeZoneSummerOnly :: Bool
timeZoneSummerOnly = Bool
s} | Bool
s <- Bool -> [Bool]
forall a. Arbitrary a => a -> [a]
shrink Bool
timeZoneSummerOnly ]
        [TimeZone] -> [TimeZone] -> [TimeZone]
forall a. [a] -> [a] -> [a]
++ [ TimeZone
tz {timeZoneMinutes :: Minutes
timeZoneMinutes = Minutes
m} | Minutes
m <- Minutes -> [Minutes]
forall a. Arbitrary a => a -> [a]
shrink Minutes
timeZoneMinutes ]
        [TimeZone] -> [TimeZone] -> [TimeZone]
forall a. [a] -> [a] -> [a]
++ [ TimeZone
tz {timeZoneName :: String
timeZoneName = String
n} | String
n <- String -> [String]
forall a. Arbitrary a => a -> [a]
shrink String
timeZoneName ]

instance CoArbitrary TimeZone where
    coarbitrary :: TimeZone -> Gen b -> Gen b
coarbitrary (TimeZone m :: Minutes
m s :: Bool
s n :: String
n)
        = Minutes -> Gen b -> Gen b
forall a b. CoArbitrary a => a -> Gen b -> Gen b
coarbitrary Minutes
m (Gen b -> Gen b) -> (Gen b -> Gen b) -> Gen b -> Gen b
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Bool -> Gen b -> Gen b
forall a b. CoArbitrary a => a -> Gen b -> Gen b
coarbitrary Bool
s (Gen b -> Gen b) -> (Gen b -> Gen b) -> Gen b -> Gen b
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> Gen b -> Gen b
forall a b. CoArbitrary a => a -> Gen b -> Gen b
coarbitrary String
n

-- | Text representing the offset of this timezone, e.g. \"-0800\" or
-- \"+0400\" (like %z in 'formatTime')
{-# INLINEABLE timeZoneOffsetString #-}
timeZoneOffsetString :: TimeZone -> String
timeZoneOffsetString :: TimeZone -> String
timeZoneOffsetString TimeZone {..} = Char
sign Char -> ShowS
forall a. a -> [a] -> [a]
: (Minutes -> ShowS
shows02 Minutes
h ShowS -> ShowS -> ShowS
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Minutes -> ShowS
shows02 Minutes
m) "" where
    (h :: Minutes
h, m :: Minutes
m) = Minutes -> Minutes -> (Minutes, Minutes)
forall a. Integral a => a -> a -> (a, a)
divMod Minutes
offset 60
    (sign :: Char
sign, offset :: Minutes
offset) = if Minutes
timeZoneMinutes Minutes -> Minutes -> Bool
forall a. Ord a => a -> a -> Bool
< 0
        then ('-', Minutes -> Minutes
forall a. Num a => a -> a
negate Minutes
timeZoneMinutes) else ('+', Minutes
timeZoneMinutes)

-- | Create a nameless non-summer timezone for this number of minutes
minutesToTimeZone :: Minutes -> TimeZone
minutesToTimeZone :: Minutes -> TimeZone
minutesToTimeZone m :: Minutes
m = Minutes -> Bool -> String -> TimeZone
TimeZone Minutes
m Bool
False ""

-- | Create a nameless non-summer timezone for this number of hours
hoursToTimeZone :: Hours -> TimeZone
hoursToTimeZone :: Minutes -> TimeZone
hoursToTimeZone i :: Minutes
i = Minutes -> TimeZone
minutesToTimeZone (60 Minutes -> Minutes -> Minutes
forall a. Num a => a -> a -> a
* Minutes
i)

utc :: TimeZone
utc :: TimeZone
utc = Minutes -> Bool -> String -> TimeZone
TimeZone 0 Bool
False "UTC"

{-# INLINEABLE getTimeZone #-}
getTimeZone :: UTCTime -> IO TimeZone
getTimeZone :: UTCTime -> IO TimeZone
getTimeZone t :: UTCTime
t = TimeZone -> TimeZone
thyme (TimeZone -> TimeZone) -> IO TimeZone -> IO TimeZone
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` UTCTime -> IO TimeZone
T.getTimeZone (Day -> DiffTime -> UTCTime
T.UTCTime Day
day (DiffTime -> UTCTime) -> DiffTime -> UTCTime
forall a b. (a -> b) -> a -> b
$ DiffTime -> DiffTime
forall t n. (TimeDiff t, Fractional n) => t -> n
toSeconds DiffTime
dt) where
    day :: Day
day = Integer -> Day
T.ModifiedJulianDay (Minutes -> Integer
forall a. Integral a => a -> Integer
toInteger Minutes
mjd)
    UTCTime (ModifiedJulianDay mjd :: Minutes
mjd) dt :: DiffTime
dt = UTCTime
t UTCTime -> Getting UTCView UTCTime UTCView -> UTCView
forall s a. s -> Getting a s a -> a
^. Getting UTCView UTCTime UTCView
Iso' UTCTime UTCView
utcTime
    thyme :: TimeZone -> TimeZone
thyme T.TimeZone {..} = $WTimeZone :: Minutes -> Bool -> String -> TimeZone
TimeZone {..}

{-# INLINE getCurrentTimeZone #-}
getCurrentTimeZone :: IO TimeZone
getCurrentTimeZone :: IO TimeZone
getCurrentTimeZone = IO UTCTime
getCurrentTime IO UTCTime -> (UTCTime -> IO TimeZone) -> IO TimeZone
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= UTCTime -> IO TimeZone
getTimeZone

------------------------------------------------------------------------
-- * Time of day

type Hour = Int
type Minute = Int
data TimeOfDay = TimeOfDay
    { TimeOfDay -> Minutes
todHour :: {-# UNPACK #-}!Hour
    , TimeOfDay -> Minutes
todMin :: {-# UNPACK #-}!Minute
    , TimeOfDay -> DiffTime
todSec :: {-# UNPACK #-}!DiffTime
    } deriving (INSTANCES_USUAL)

derivingUnbox "TimeOfDay" [t| TimeOfDay -> Int64 |]
    [| \ TimeOfDay {..} -> fromIntegral (todHour .|. shiftL todMin 8)
        .|. shiftL (todSec ^. microseconds) 16 |]
    [| \ n -> TimeOfDay (fromIntegral $ n .&. 0xff)
        (fromIntegral $ shiftR n 8 .&. 0xff) (microseconds # shiftR n 16) |]

instance NFData TimeOfDay

#if SHOW_INTERNAL
deriving instance Show TimeOfDay
#else
instance Show TimeOfDay where
    showsPrec :: Minutes -> TimeOfDay -> ShowS
showsPrec _ (TimeOfDay h :: Minutes
h m :: Minutes
m (DiffTime s :: Micro
s))
            = Minutes -> ShowS
shows02 Minutes
h ShowS -> ShowS -> ShowS
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (:) ':' ShowS -> ShowS -> ShowS
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Minutes -> ShowS
shows02 Minutes
m ShowS -> ShowS -> ShowS
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (:) ':'
            ShowS -> ShowS -> ShowS
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Minutes -> ShowS
shows02 (Int64 -> Minutes
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
si) ShowS -> ShowS -> ShowS
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ShowS
frac where
        (si :: Int64
si, Micro su :: Int64
su) = Micro -> Micro -> (Int64, Micro)
microQuotRem Micro
s (Int64 -> Micro
Micro 1000000)
        frac :: ShowS
frac = if Int64
su Int64 -> Int64 -> Bool
forall a. Eq a => a -> a -> Bool
== 0 then ShowS
forall a. a -> a
id else (:) '.' ShowS -> ShowS -> ShowS
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int64 -> ShowS
fills06 Int64
su ShowS -> ShowS -> ShowS
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int64 -> ShowS
drops0 Int64
su
#endif

instance Bounded TimeOfDay where
    minBound :: TimeOfDay
minBound = Minutes -> Minutes -> DiffTime -> TimeOfDay
TimeOfDay 0 0 DiffTime
forall v. AdditiveGroup v => v
zeroV
    maxBound :: TimeOfDay
maxBound = Minutes -> Minutes -> DiffTime -> TimeOfDay
TimeOfDay 23 59 (Overloaded Reviewed Identity DiffTime DiffTime Int64 Int64
forall t. TimeDiff t => Iso' t Int64
microseconds Overloaded Reviewed Identity DiffTime DiffTime Int64 Int64
-> Int64 -> DiffTime
forall s t a b. AReview s t a b -> b -> t
# 60999999)

instance Random TimeOfDay where
    randomR :: (TimeOfDay, TimeOfDay) -> g -> (TimeOfDay, g)
randomR = Iso' DiffTime TimeOfDay
-> (TimeOfDay, TimeOfDay) -> g -> (TimeOfDay, g)
forall s g a.
(Random s, RandomGen g) =>
Iso' s a -> (a, a) -> g -> (a, g)
randomIsoR Iso' DiffTime TimeOfDay
timeOfDay
    random :: g -> (TimeOfDay, g)
random = (DiffTime -> TimeOfDay) -> (DiffTime, g) -> (TimeOfDay, g)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (DiffTime -> Getting TimeOfDay DiffTime TimeOfDay -> TimeOfDay
forall s a. s -> Getting a s a -> a
^. Getting TimeOfDay DiffTime TimeOfDay
Iso' DiffTime TimeOfDay
timeOfDay) ((DiffTime, g) -> (TimeOfDay, g))
-> (g -> (DiffTime, g)) -> g -> (TimeOfDay, g)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. g -> (DiffTime, g)
forall a g. (Random a, RandomGen g) => g -> (a, g)
random

instance Arbitrary TimeOfDay where
    arbitrary :: Gen TimeOfDay
arbitrary = do
        Minutes
h <- (Minutes, Minutes) -> Gen Minutes
forall a. Random a => (a, a) -> Gen a
choose (0, 23)
        Minutes
m <- (Minutes, Minutes) -> Gen Minutes
forall a. Random a => (a, a) -> Gen a
choose (0, 59)
        let DiffTime ml :: Micro
ml = Minutes -> Minutes -> DiffTime
minuteLength Minutes
h Minutes
m
        Minutes -> Minutes -> DiffTime -> TimeOfDay
TimeOfDay Minutes
h Minutes
m (DiffTime -> TimeOfDay)
-> (Micro -> DiffTime) -> Micro -> TimeOfDay
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Micro -> DiffTime
DiffTime (Micro -> TimeOfDay) -> Gen Micro -> Gen TimeOfDay
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Micro, Micro) -> Gen Micro
forall a. Random a => (a, a) -> Gen a
choose (Micro
forall v. AdditiveGroup v => v
zeroV, Micro -> Micro
forall a. Enum a => a -> a
pred Micro
ml)
    shrink :: TimeOfDay -> [TimeOfDay]
shrink tod :: TimeOfDay
tod = Getting TimeOfDay DiffTime TimeOfDay -> DiffTime -> TimeOfDay
forall a s. Getting a s a -> s -> a
view Getting TimeOfDay DiffTime TimeOfDay
Iso' DiffTime TimeOfDay
timeOfDay (DiffTime -> TimeOfDay)
-> (DiffTime -> DiffTime) -> DiffTime -> TimeOfDay
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. DiffTime -> DiffTime -> DiffTime
forall v. AdditiveGroup v => v -> v -> v
(^+^) DiffTime
noon
            (DiffTime -> TimeOfDay) -> [DiffTime] -> [TimeOfDay]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DiffTime -> [DiffTime]
forall a. Arbitrary a => a -> [a]
shrink (Overloaded Reviewed Identity DiffTime DiffTime TimeOfDay TimeOfDay
Iso' DiffTime TimeOfDay
timeOfDay Overloaded Reviewed Identity DiffTime DiffTime TimeOfDay TimeOfDay
-> TimeOfDay -> DiffTime
forall s t a b. AReview s t a b -> b -> t
# TimeOfDay
tod DiffTime -> DiffTime -> DiffTime
forall v. AdditiveGroup v => v -> v -> v
^-^ DiffTime
noon) where
        noon :: DiffTime
noon = Overloaded Reviewed Identity DiffTime DiffTime TimeOfDay TimeOfDay
Iso' DiffTime TimeOfDay
timeOfDay Overloaded Reviewed Identity DiffTime DiffTime TimeOfDay TimeOfDay
-> TimeOfDay -> DiffTime
forall s t a b. AReview s t a b -> b -> t
# TimeOfDay
midday -- shrink towards midday

instance CoArbitrary TimeOfDay where
    coarbitrary :: TimeOfDay -> Gen b -> Gen b
coarbitrary (TimeOfDay h :: Minutes
h m :: Minutes
m s :: DiffTime
s)
        = Minutes -> Gen b -> Gen b
forall a b. CoArbitrary a => a -> Gen b -> Gen b
coarbitrary Minutes
h (Gen b -> Gen b) -> (Gen b -> Gen b) -> Gen b -> Gen b
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Minutes -> Gen b -> Gen b
forall a b. CoArbitrary a => a -> Gen b -> Gen b
coarbitrary Minutes
m (Gen b -> Gen b) -> (Gen b -> Gen b) -> Gen b -> Gen b
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. DiffTime -> Gen b -> Gen b
forall a b. CoArbitrary a => a -> Gen b -> Gen b
coarbitrary DiffTime
s

{-# INLINE minuteLength #-}
minuteLength :: Hour -> Minute -> DiffTime
minuteLength :: Minutes -> Minutes -> DiffTime
minuteLength h :: Minutes
h m :: Minutes
m = Rational -> DiffTime
forall t. TimeDiff t => Rational -> t
fromSeconds' (Rational -> DiffTime) -> Rational -> DiffTime
forall a b. (a -> b) -> a -> b
$ if Minutes
h Minutes -> Minutes -> Bool
forall a. Eq a => a -> a -> Bool
== 23 Bool -> Bool -> Bool
&& Minutes
m Minutes -> Minutes -> Bool
forall a. Eq a => a -> a -> Bool
== 59 then 61 else 60

-- | Hour zero
midnight :: TimeOfDay
midnight :: TimeOfDay
midnight = Minutes -> Minutes -> DiffTime -> TimeOfDay
TimeOfDay 0 0 DiffTime
forall v. AdditiveGroup v => v
zeroV

-- | Hour twelve
midday :: TimeOfDay
midday :: TimeOfDay
midday = Minutes -> Minutes -> DiffTime -> TimeOfDay
TimeOfDay 12 0 DiffTime
forall v. AdditiveGroup v => v
zeroV

{-# INLINE makeTimeOfDayValid #-}
makeTimeOfDayValid :: Hour -> Minute -> DiffTime -> Maybe TimeOfDay
makeTimeOfDayValid :: Minutes -> Minutes -> DiffTime -> Maybe TimeOfDay
makeTimeOfDayValid h :: Minutes
h m :: Minutes
m s :: DiffTime
s = Minutes -> Minutes -> DiffTime -> TimeOfDay
TimeOfDay Minutes
h Minutes
m DiffTime
s
    TimeOfDay -> Maybe () -> Maybe TimeOfDay
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (0 Minutes -> Minutes -> Bool
forall a. Ord a => a -> a -> Bool
<= Minutes
h Bool -> Bool -> Bool
&& Minutes
h Minutes -> Minutes -> Bool
forall a. Ord a => a -> a -> Bool
<= 23 Bool -> Bool -> Bool
&& 0 Minutes -> Minutes -> Bool
forall a. Ord a => a -> a -> Bool
<= Minutes
m Bool -> Bool -> Bool
&& Minutes
m Minutes -> Minutes -> Bool
forall a. Ord a => a -> a -> Bool
<= 59)
    Maybe TimeOfDay -> Maybe () -> Maybe TimeOfDay
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (DiffTime
forall v. AdditiveGroup v => v
zeroV DiffTime -> DiffTime -> Bool
forall a. Ord a => a -> a -> Bool
<= DiffTime
s Bool -> Bool -> Bool
&& DiffTime
s DiffTime -> DiffTime -> Bool
forall a. Ord a => a -> a -> Bool
< Minutes -> Minutes -> DiffTime
minuteLength Minutes
h Minutes
m)

{-# INLINE timeOfDay #-}
timeOfDay :: Iso' DiffTime TimeOfDay
timeOfDay :: Overloaded p f DiffTime DiffTime TimeOfDay TimeOfDay
timeOfDay = (DiffTime -> TimeOfDay)
-> (TimeOfDay -> DiffTime) -> Iso' DiffTime TimeOfDay
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso DiffTime -> TimeOfDay
fromDiff TimeOfDay -> DiffTime
toDiff where

    {-# INLINEABLE fromDiff #-}
    fromDiff :: DiffTime -> TimeOfDay
    fromDiff :: DiffTime -> TimeOfDay
fromDiff (DiffTime t :: Micro
t) = Minutes -> Minutes -> DiffTime -> TimeOfDay
TimeOfDay
            (Int64 -> Minutes
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
h) (Int64 -> Minutes
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
m) (Micro -> DiffTime
DiffTime Micro
s) where
        (h :: Int64
h, ms :: Micro
ms) = Micro -> Micro -> (Int64, Micro)
microQuotRem Micro
t (Int64 -> Micro
Micro 3600000000)
        (m :: Int64
m, s :: Micro
s) = Micro -> Micro -> (Int64, Micro)
microQuotRem Micro
ms (Int64 -> Micro
Micro 60000000)

    {-# INLINEABLE toDiff #-}
    toDiff :: TimeOfDay -> DiffTime
    toDiff :: TimeOfDay -> DiffTime
toDiff (TimeOfDay h :: Minutes
h m :: Minutes
m s :: DiffTime
s) = DiffTime
s
        DiffTime -> DiffTime -> DiffTime
forall v. AdditiveGroup v => v -> v -> v
^+^ Minutes -> Rational
forall a b. (Integral a, Num b) => a -> b
fromIntegral Minutes
m Scalar DiffTime -> DiffTime -> DiffTime
forall v. VectorSpace v => Scalar v -> v -> v
*^ Micro -> DiffTime
DiffTime (Int64 -> Micro
Micro 60000000)
        DiffTime -> DiffTime -> DiffTime
forall v. AdditiveGroup v => v -> v -> v
^+^ Minutes -> Rational
forall a b. (Integral a, Num b) => a -> b
fromIntegral Minutes
h Scalar DiffTime -> DiffTime -> DiffTime
forall v. VectorSpace v => Scalar v -> v -> v
*^ Micro -> DiffTime
DiffTime (Int64 -> Micro
Micro 3600000000)

-- | Add some minutes to a 'TimeOfDay'; result comes with a day adjustment.
{-# INLINE addMinutes #-}
addMinutes :: Minutes -> TimeOfDay -> (Days, TimeOfDay)
addMinutes :: Minutes -> TimeOfDay -> (Minutes, TimeOfDay)
addMinutes dm :: Minutes
dm (TimeOfDay h :: Minutes
h m :: Minutes
m s :: DiffTime
s) = (Minutes
dd, Minutes -> Minutes -> DiffTime -> TimeOfDay
TimeOfDay Minutes
h' Minutes
m' DiffTime
s) where
    (dd :: Minutes
dd, h' :: Minutes
h') = Minutes -> Minutes -> (Minutes, Minutes)
forall a. Integral a => a -> a -> (a, a)
divMod (Minutes
h Minutes -> Minutes -> Minutes
forall a. Num a => a -> a -> a
+ Minutes
dh) 24
    (dh :: Minutes
dh, m' :: Minutes
m') = Minutes -> Minutes -> (Minutes, Minutes)
forall a. Integral a => a -> a -> (a, a)
divMod (Minutes
m Minutes -> Minutes -> Minutes
forall a. Num a => a -> a -> a
+ Minutes
dm) 60

{-# INLINE dayFraction #-}
dayFraction :: Iso' TimeOfDay Rational
dayFraction :: Overloaded p f TimeOfDay TimeOfDay Rational Rational
dayFraction = AnIso DiffTime DiffTime TimeOfDay TimeOfDay
-> Iso TimeOfDay TimeOfDay DiffTime DiffTime
forall s t a b. AnIso s t a b -> Iso b a t s
from AnIso DiffTime DiffTime TimeOfDay TimeOfDay
Iso' DiffTime TimeOfDay
timeOfDay Overloaded p f TimeOfDay TimeOfDay DiffTime DiffTime
-> (p Rational (f Rational) -> p DiffTime (f DiffTime))
-> Overloaded p f TimeOfDay TimeOfDay Rational Rational
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (DiffTime -> Rational)
-> (Rational -> DiffTime)
-> Iso DiffTime DiffTime Rational Rational
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso DiffTime -> Rational
toRatio Rational -> DiffTime
fromRatio where

    {-# INLINEABLE toRatio #-}
    toRatio :: DiffTime -> Rational
    toRatio :: DiffTime -> Rational
toRatio t :: DiffTime
t = DiffTime -> Rational
forall t n. (TimeDiff t, Fractional n) => t -> n
toSeconds DiffTime
t Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ NominalDiffTime -> Rational
forall t n. (TimeDiff t, Fractional n) => t -> n
toSeconds NominalDiffTime
posixDayLength

    {-# INLINEABLE fromRatio #-}
    fromRatio :: Rational -> DiffTime
    fromRatio :: Rational -> DiffTime
fromRatio ((Scalar NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall v. VectorSpace v => Scalar v -> v -> v
*^ NominalDiffTime
posixDayLength) -> NominalDiffTime r :: Micro
r) = Micro -> DiffTime
DiffTime Micro
r

------------------------------------------------------------------------
-- * Local Time

data LocalTime = LocalTime
    { LocalTime -> Day
localDay :: {-# UNPACK #-}!Day
    , LocalTime -> TimeOfDay
localTimeOfDay :: {-only 3 words…-} {-# UNPACK #-}!TimeOfDay
    } deriving (INSTANCES_USUAL)

derivingUnbox "LocalTime" [t| LocalTime -> (Day, TimeOfDay) |]
    [| \ LocalTime {..} -> (localDay, localTimeOfDay) |]
    [| \ (localDay, localTimeOfDay) -> LocalTime {..} |]

instance NFData LocalTime

#if SHOW_INTERNAL
deriving instance Show LocalTime
#else
instance Show LocalTime where
    showsPrec :: Minutes -> LocalTime -> ShowS
showsPrec p :: Minutes
p (LocalTime d :: Day
d t :: TimeOfDay
t) = Minutes -> Day -> ShowS
forall a. Show a => Minutes -> a -> ShowS
showsPrec Minutes
p Day
d ShowS -> ShowS -> ShowS
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (:) ' ' ShowS -> ShowS -> ShowS
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Minutes -> TimeOfDay -> ShowS
forall a. Show a => Minutes -> a -> ShowS
showsPrec Minutes
p TimeOfDay
t
#endif

instance Bounded LocalTime where
    minBound :: LocalTime
minBound = UTCTime
forall a. Bounded a => a
minBound UTCTime -> Getting LocalTime UTCTime LocalTime -> LocalTime
forall s a. s -> Getting a s a -> a
^. TimeZone -> Iso' UTCTime LocalTime
utcLocalTime TimeZone
forall a. Bounded a => a
maxBound
    maxBound :: LocalTime
maxBound = UTCTime
forall a. Bounded a => a
maxBound UTCTime -> Getting LocalTime UTCTime LocalTime -> LocalTime
forall s a. s -> Getting a s a -> a
^. TimeZone -> Iso' UTCTime LocalTime
utcLocalTime TimeZone
forall a. Bounded a => a
minBound

instance Random LocalTime where
    randomR :: (LocalTime, LocalTime) -> g -> (LocalTime, g)
randomR = Iso' UTCTime LocalTime
-> (LocalTime, LocalTime) -> g -> (LocalTime, g)
forall s g a.
(Random s, RandomGen g) =>
Iso' s a -> (a, a) -> g -> (a, g)
randomIsoR (TimeZone -> Iso' UTCTime LocalTime
utcLocalTime TimeZone
utc)
    random :: g -> (LocalTime, g)
random = (LocalTime, LocalTime) -> g -> (LocalTime, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (LocalTime
forall a. Bounded a => a
minBound, LocalTime
forall a. Bounded a => a
maxBound)

instance Arbitrary LocalTime where
    arbitrary :: Gen LocalTime
arbitrary = (LocalTime, LocalTime) -> Gen LocalTime
forall a. Random a => (a, a) -> Gen a
choose (LocalTime
forall a. Bounded a => a
minBound, LocalTime
forall a. Bounded a => a
maxBound)
    shrink :: LocalTime -> [LocalTime]
shrink lt :: LocalTime
lt@LocalTime {..}
        = [ LocalTime
lt {localDay :: Day
localDay = Day
d} | Day
d <- Day -> [Day]
forall a. Arbitrary a => a -> [a]
shrink Day
localDay ]
        [LocalTime] -> [LocalTime] -> [LocalTime]
forall a. [a] -> [a] -> [a]
++ [ LocalTime
lt {localTimeOfDay :: TimeOfDay
localTimeOfDay = TimeOfDay
d} | TimeOfDay
d <- TimeOfDay -> [TimeOfDay]
forall a. Arbitrary a => a -> [a]
shrink TimeOfDay
localTimeOfDay ]

instance CoArbitrary LocalTime where
    coarbitrary :: LocalTime -> Gen b -> Gen b
coarbitrary (LocalTime d :: Day
d t :: TimeOfDay
t) = Day -> Gen b -> Gen b
forall a b. CoArbitrary a => a -> Gen b -> Gen b
coarbitrary Day
d (Gen b -> Gen b) -> (Gen b -> Gen b) -> Gen b -> Gen b
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. TimeOfDay -> Gen b -> Gen b
forall a b. CoArbitrary a => a -> Gen b -> Gen b
coarbitrary TimeOfDay
t

{-# INLINE utcLocalTime #-}
utcLocalTime :: TimeZone -> Iso' UTCTime LocalTime
utcLocalTime :: TimeZone -> Iso' UTCTime LocalTime
utcLocalTime TimeZone {..} = Overloaded p f UTCTime UTCTime UTCView UTCView
Iso' UTCTime UTCView
utcTime Overloaded p f UTCTime UTCTime UTCView UTCView
-> (p LocalTime (f LocalTime) -> p UTCView (f UTCView))
-> p LocalTime (f LocalTime)
-> p UTCTime (f UTCTime)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (UTCView -> LocalTime)
-> (LocalTime -> UTCView)
-> Iso UTCView UTCView LocalTime LocalTime
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso UTCView -> LocalTime
localise LocalTime -> UTCView
globalise where

    {-# INLINEABLE localise #-}
    localise :: UTCView -> LocalTime
    localise :: UTCView -> LocalTime
localise (UTCTime day :: Day
day dt :: DiffTime
dt) = Day -> TimeOfDay -> LocalTime
LocalTime (Day
day Day -> Diff Day -> Day
forall p. AffineSpace p => p -> Diff p -> p
.+^ Minutes
Diff Day
dd) TimeOfDay
tod where
        (dd :: Minutes
dd, tod :: TimeOfDay
tod) = Minutes -> TimeOfDay -> (Minutes, TimeOfDay)
addMinutes Minutes
timeZoneMinutes (DiffTime
dt DiffTime -> Getting TimeOfDay DiffTime TimeOfDay -> TimeOfDay
forall s a. s -> Getting a s a -> a
^. Getting TimeOfDay DiffTime TimeOfDay
Iso' DiffTime TimeOfDay
timeOfDay)

    {-# INLINEABLE globalise #-}
    globalise :: LocalTime -> UTCView
    globalise :: LocalTime -> UTCView
globalise (LocalTime day :: Day
day tod :: TimeOfDay
tod) = Day -> DiffTime -> UTCView
UTCTime (Day
day Day -> Diff Day -> Day
forall p. AffineSpace p => p -> Diff p -> p
.+^ Minutes
Diff Day
dd)
            (Overloaded Reviewed Identity DiffTime DiffTime TimeOfDay TimeOfDay
Iso' DiffTime TimeOfDay
timeOfDay Overloaded Reviewed Identity DiffTime DiffTime TimeOfDay TimeOfDay
-> TimeOfDay -> DiffTime
forall s t a b. AReview s t a b -> b -> t
# TimeOfDay
utcToD) where
        (dd :: Minutes
dd, utcToD :: TimeOfDay
utcToD) = Minutes -> TimeOfDay -> (Minutes, TimeOfDay)
addMinutes (Minutes -> Minutes
forall a. Num a => a -> a
negate Minutes
timeZoneMinutes) TimeOfDay
tod

{-# INLINE ut1LocalTime #-}
ut1LocalTime :: Rational -> Iso' UniversalTime LocalTime
ut1LocalTime :: Rational -> Iso' UniversalTime LocalTime
ut1LocalTime long :: Rational
long = (UniversalTime -> LocalTime)
-> (LocalTime -> UniversalTime) -> Iso' UniversalTime LocalTime
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso UniversalTime -> LocalTime
localise LocalTime -> UniversalTime
globalise where
    NominalDiffTime posixDay :: Micro
posixDay@(Micro usDay :: Int64
usDay) = NominalDiffTime
posixDayLength

    {-# INLINEABLE localise #-}
    localise :: UniversalTime -> LocalTime
    localise :: UniversalTime -> LocalTime
localise (UniversalRep (NominalDiffTime t :: Micro
t)) = Day -> TimeOfDay -> LocalTime
LocalTime
            (Minutes -> Day
ModifiedJulianDay (Minutes -> Day) -> Minutes -> Day
forall a b. (a -> b) -> a -> b
$ Int64 -> Minutes
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
day)
            (Micro -> DiffTime
DiffTime Micro
dt DiffTime -> Getting TimeOfDay DiffTime TimeOfDay -> TimeOfDay
forall s a. s -> Getting a s a -> a
^. Getting TimeOfDay DiffTime TimeOfDay
Iso' DiffTime TimeOfDay
timeOfDay) where
        (day :: Int64
day, dt :: Micro
dt) = Micro -> Micro -> (Int64, Micro)
microDivMod (Micro
t Micro -> Micro -> Micro
forall v. AdditiveGroup v => v -> v -> v
^+^ (Rational
long Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ 360) Scalar Micro -> Micro -> Micro
forall v. VectorSpace v => Scalar v -> v -> v
*^ Micro
posixDay) Micro
posixDay

    {-# INLINEABLE globalise #-}
    globalise :: LocalTime -> UniversalTime
    globalise :: LocalTime -> UniversalTime
globalise (LocalTime day :: Day
day tod :: TimeOfDay
tod) = NominalDiffTime -> UniversalTime
UniversalRep (NominalDiffTime -> UniversalTime)
-> (Micro -> NominalDiffTime) -> Micro -> UniversalTime
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Micro -> NominalDiffTime
NominalDiffTime (Micro -> UniversalTime) -> Micro -> UniversalTime
forall a b. (a -> b) -> a -> b
$
            Int64 -> Micro
Micro (Int64
mjd Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
* Int64
usDay) Micro -> Micro -> Micro
forall v. AdditiveGroup v => v -> v -> v
^+^ Micro
dt Micro -> Micro -> Micro
forall v. AdditiveGroup v => v -> v -> v
^-^ (Rational
long Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ 360) Scalar Micro -> Micro -> Micro
forall v. VectorSpace v => Scalar v -> v -> v
*^ Micro
posixDay where
        ModifiedJulianDay (Minutes -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral -> Int64
mjd) = Day
day
        DiffTime dt :: Micro
dt = Overloaded Reviewed Identity DiffTime DiffTime TimeOfDay TimeOfDay
Iso' DiffTime TimeOfDay
timeOfDay Overloaded Reviewed Identity DiffTime DiffTime TimeOfDay TimeOfDay
-> TimeOfDay -> DiffTime
forall s t a b. AReview s t a b -> b -> t
# TimeOfDay
tod

------------------------------------------------------------------------
-- * Zoned Time

data ZonedTime = ZonedTime
    { ZonedTime -> LocalTime
zonedTimeToLocalTime :: {-only 4 words…-} {-# UNPACK #-}!LocalTime
    , ZonedTime -> TimeZone
zonedTimeZone :: !TimeZone
    } deriving (INSTANCES_USUAL)

instance NFData ZonedTime where
    rnf :: ZonedTime -> ()
rnf ZonedTime {..} = TimeZone -> ()
forall a. NFData a => a -> ()
rnf TimeZone
zonedTimeZone

instance Bounded ZonedTime where
    minBound :: ZonedTime
minBound = LocalTime -> TimeZone -> ZonedTime
ZonedTime LocalTime
forall a. Bounded a => a
minBound TimeZone
forall a. Bounded a => a
maxBound
    maxBound :: ZonedTime
maxBound = LocalTime -> TimeZone -> ZonedTime
ZonedTime LocalTime
forall a. Bounded a => a
maxBound TimeZone
forall a. Bounded a => a
minBound

instance Random ZonedTime where
    randomR :: (ZonedTime, ZonedTime) -> g -> (ZonedTime, g)
randomR (l :: ZonedTime
l, u :: ZonedTime
u) g0 :: g
g0 = (Getting ZonedTime (TimeZone, UTCTime) ZonedTime
-> (TimeZone, UTCTime) -> ZonedTime
forall a s. Getting a s a -> s -> a
view Getting ZonedTime (TimeZone, UTCTime) ZonedTime
Iso' (TimeZone, UTCTime) ZonedTime
zonedTime ((TimeZone, UTCTime) -> ZonedTime)
-> (UTCTime -> (TimeZone, UTCTime)) -> UTCTime -> ZonedTime
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (,) TimeZone
tz)
            (UTCTime -> ZonedTime) -> (UTCTime, g) -> (ZonedTime, g)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
`first` (UTCTime, UTCTime) -> g -> (UTCTime, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (UTCTime
l', UTCTime
u') g
g1 where
        (tz :: TimeZone
tz, g1 :: g
g1) = g -> (TimeZone, g)
forall a g. (Random a, RandomGen g) => g -> (a, g)
random g
g0 -- ignore TimeZone from l and u
        l' :: UTCTime
l' = (TimeZone, UTCTime) -> UTCTime
forall a b. (a, b) -> b
snd ((TimeZone, UTCTime) -> UTCTime) -> (TimeZone, UTCTime) -> UTCTime
forall a b. (a -> b) -> a -> b
$ Overloaded
  Reviewed
  Identity
  (TimeZone, UTCTime)
  (TimeZone, UTCTime)
  ZonedTime
  ZonedTime
Iso' (TimeZone, UTCTime) ZonedTime
zonedTime Overloaded
  Reviewed
  Identity
  (TimeZone, UTCTime)
  (TimeZone, UTCTime)
  ZonedTime
  ZonedTime
-> ZonedTime -> (TimeZone, UTCTime)
forall s t a b. AReview s t a b -> b -> t
# ZonedTime
l
        u' :: UTCTime
u' = (TimeZone, UTCTime) -> UTCTime
forall a b. (a, b) -> b
snd ((TimeZone, UTCTime) -> UTCTime) -> (TimeZone, UTCTime) -> UTCTime
forall a b. (a -> b) -> a -> b
$ Overloaded
  Reviewed
  Identity
  (TimeZone, UTCTime)
  (TimeZone, UTCTime)
  ZonedTime
  ZonedTime
Iso' (TimeZone, UTCTime) ZonedTime
zonedTime Overloaded
  Reviewed
  Identity
  (TimeZone, UTCTime)
  (TimeZone, UTCTime)
  ZonedTime
  ZonedTime
-> ZonedTime -> (TimeZone, UTCTime)
forall s t a b. AReview s t a b -> b -> t
# ZonedTime
u
    random :: g -> (ZonedTime, g)
random = (ZonedTime, ZonedTime) -> g -> (ZonedTime, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (ZonedTime
forall a. Bounded a => a
minBound, ZonedTime
forall a. Bounded a => a
maxBound)

instance Arbitrary ZonedTime where
    arbitrary :: Gen ZonedTime
arbitrary = (ZonedTime, ZonedTime) -> Gen ZonedTime
forall a. Random a => (a, a) -> Gen a
choose (ZonedTime
forall a. Bounded a => a
minBound, ZonedTime
forall a. Bounded a => a
maxBound)
    shrink :: ZonedTime -> [ZonedTime]
shrink zt :: ZonedTime
zt@ZonedTime {..}
        = [ ZonedTime
zt {zonedTimeToLocalTime :: LocalTime
zonedTimeToLocalTime = LocalTime
lt} | LocalTime
lt <- LocalTime -> [LocalTime]
forall a. Arbitrary a => a -> [a]
shrink LocalTime
zonedTimeToLocalTime ]
        [ZonedTime] -> [ZonedTime] -> [ZonedTime]
forall a. [a] -> [a] -> [a]
++ [ ZonedTime
zt {zonedTimeZone :: TimeZone
zonedTimeZone = TimeZone
tz} | TimeZone
tz <- TimeZone -> [TimeZone]
forall a. Arbitrary a => a -> [a]
shrink TimeZone
zonedTimeZone ]

instance CoArbitrary ZonedTime where
    coarbitrary :: ZonedTime -> Gen b -> Gen b
coarbitrary (ZonedTime lt :: LocalTime
lt tz :: TimeZone
tz) = LocalTime -> Gen b -> Gen b
forall a b. CoArbitrary a => a -> Gen b -> Gen b
coarbitrary LocalTime
lt (Gen b -> Gen b) -> (Gen b -> Gen b) -> Gen b -> Gen b
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. TimeZone -> Gen b -> Gen b
forall a b. CoArbitrary a => a -> Gen b -> Gen b
coarbitrary TimeZone
tz

{-# INLINE zonedTime #-}
zonedTime :: Iso' (TimeZone, UTCTime) ZonedTime
zonedTime :: Overloaded
  p f (TimeZone, UTCTime) (TimeZone, UTCTime) ZonedTime ZonedTime
zonedTime = ((TimeZone, UTCTime) -> ZonedTime)
-> (ZonedTime -> (TimeZone, UTCTime))
-> Iso' (TimeZone, UTCTime) ZonedTime
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso (TimeZone, UTCTime) -> ZonedTime
toZoned ZonedTime -> (TimeZone, UTCTime)
fromZoned where

    {-# INLINE toZoned #-}
    toZoned :: (TimeZone, UTCTime) -> ZonedTime
    toZoned :: (TimeZone, UTCTime) -> ZonedTime
toZoned (tz :: TimeZone
tz, time :: UTCTime
time) = LocalTime -> TimeZone -> ZonedTime
ZonedTime (UTCTime
time UTCTime -> Getting LocalTime UTCTime LocalTime -> LocalTime
forall s a. s -> Getting a s a -> a
^. TimeZone -> Iso' UTCTime LocalTime
utcLocalTime TimeZone
tz) TimeZone
tz

    {-# INLINE fromZoned #-}
    fromZoned :: ZonedTime -> (TimeZone, UTCTime)
    fromZoned :: ZonedTime -> (TimeZone, UTCTime)
fromZoned (ZonedTime lt :: LocalTime
lt tz :: TimeZone
tz) = (TimeZone
tz, TimeZone -> Iso' UTCTime LocalTime
utcLocalTime TimeZone
tz Overloaded Reviewed Identity UTCTime UTCTime LocalTime LocalTime
-> LocalTime -> UTCTime
forall s t a b. AReview s t a b -> b -> t
# LocalTime
lt)

#if SHOW_INTERNAL
deriving instance Show ZonedTime
instance Show UTCTime where
    showsPrec p = showsPrec p . view utcTime
#else
instance Show ZonedTime where
    showsPrec :: Minutes -> ZonedTime -> ShowS
showsPrec p :: Minutes
p (ZonedTime lt :: LocalTime
lt tz :: TimeZone
tz) = Minutes -> LocalTime -> ShowS
forall a. Show a => Minutes -> a -> ShowS
showsPrec Minutes
p LocalTime
lt ShowS -> ShowS -> ShowS
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (:) ' ' ShowS -> ShowS -> ShowS
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Minutes -> TimeZone -> ShowS
forall a. Show a => Minutes -> a -> ShowS
showsPrec Minutes
p TimeZone
tz
instance Show UTCTime where
    showsPrec :: Minutes -> UTCTime -> ShowS
showsPrec p :: Minutes
p = Minutes -> ZonedTime -> ShowS
forall a. Show a => Minutes -> a -> ShowS
showsPrec Minutes
p (ZonedTime -> ShowS) -> (UTCTime -> ZonedTime) -> UTCTime -> ShowS
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Getting ZonedTime (TimeZone, UTCTime) ZonedTime
-> (TimeZone, UTCTime) -> ZonedTime
forall a s. Getting a s a -> s -> a
view Getting ZonedTime (TimeZone, UTCTime) ZonedTime
Iso' (TimeZone, UTCTime) ZonedTime
zonedTime ((TimeZone, UTCTime) -> ZonedTime)
-> (UTCTime -> (TimeZone, UTCTime)) -> UTCTime -> ZonedTime
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (,) TimeZone
utc
#endif

{-# INLINE getZonedTime #-}
getZonedTime :: IO ZonedTime
getZonedTime :: IO ZonedTime
getZonedTime = UTCTime -> IO ZonedTime
utcToLocalZonedTime (UTCTime -> IO ZonedTime) -> IO UTCTime -> IO ZonedTime
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO UTCTime
getCurrentTime

{-# INLINEABLE utcToLocalZonedTime #-}
utcToLocalZonedTime :: UTCTime -> IO ZonedTime
utcToLocalZonedTime :: UTCTime -> IO ZonedTime
utcToLocalZonedTime time :: UTCTime
time = do
    TimeZone
tz <- UTCTime -> IO TimeZone
getTimeZone UTCTime
time
    ZonedTime -> IO ZonedTime
forall (m :: * -> *) a. Monad m => a -> m a
return (ZonedTime -> IO ZonedTime) -> ZonedTime -> IO ZonedTime
forall a b. (a -> b) -> a -> b
$ (TimeZone
tz, UTCTime
time) (TimeZone, UTCTime)
-> Getting ZonedTime (TimeZone, UTCTime) ZonedTime -> ZonedTime
forall s a. s -> Getting a s a -> a
^. Getting ZonedTime (TimeZone, UTCTime) ZonedTime
Iso' (TimeZone, UTCTime) ZonedTime
zonedTime

-- * Lenses

LENS(TimeZone,timeZoneMinutes,Minutes)
LENS(TimeZone,timeZoneSummerOnly,Bool)
LENS(TimeZone,timeZoneName,String)

LENS(TimeOfDay,todHour,Hour)
LENS(TimeOfDay,todMin,Minute)
LENS(TimeOfDay,todSec,DiffTime)

LENS(LocalTime,localDay,Day)
LENS(LocalTime,localTimeOfDay,TimeOfDay)

LENS(ZonedTime,zonedTimeToLocalTime,LocalTime)
LENS(ZonedTime,zonedTimeZone,TimeZone)