{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

-- | This module provides compatibility instances and wrappers for the
-- things that @thyme@ does differently from @time@, and allows it to be
-- used as a drop-in replacement for the latter, with the exceptions noted
-- below:
--
--   * When constructing an 'UTCTime' or 'UniversalTime', use 'mkUTCTime' or
--   'mkModJulianDate' in place of @UTCTime@ or @ModJulianDate@.
--
--   * Instead of pattern matching on @UTCTime@, use 'unUTCTime' to get
--   a 'UTCView', which has a constructor @UTCTime@ with the same fields.
--   For @ModJulianDate@, use 'getModJulianDate'. @ViewPatterns@ may make
--   the transition more seamless.
--
--   * Where a third party library uses @time@, you can use 'toThyme' and
--   'fromThyme' to convert between the corresponding types.
--
--   * 'Year's are 'Int's, not 'Integer's: you may need 'fromIntegral'.
--
-- You shouldn't need to use @lens@ or @vector-space@ directly if you don't
-- want to. However if you do use @vector-space@ and wish to avoid the
-- 'RealFrac' instances for 'DiffTime' and 'NominalDiffTime', import
-- "Data.Thyme.Time.Core" instead.
--
-- Anything else is probably not intentional, and you should either contact
-- me via IRC or file an issue at <https://github.com/liyang/thyme/issues>.

module Data.Thyme.Time
    ( module Data.Thyme.Time.Core
    {- instance RealFrac {,Nominal}DiffTime -}
    ) where

import Prelude
import Data.Thyme.Internal.Micro
import Data.Ratio
import Data.Thyme
import Data.Thyme.Clock.Internal
import Data.Thyme.Time.Core

instance Num Micro where
    {-# INLINE (+) #-}
    {-# INLINE (-) #-}
    {-# INLINE (*) #-}
    {-# INLINE negate #-}
    {-# INLINE abs #-}
    {-# INLINE signum #-}
    {-# INLINE fromInteger #-}
    Micro a :: Int64
a + :: Micro -> Micro -> Micro
+ Micro b :: Int64
b = Int64 -> Micro
Micro (Int64
a Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int64
b)
    Micro a :: Int64
a - :: Micro -> Micro -> Micro
- Micro b :: Int64
b = Int64 -> Micro
Micro (Int64
a Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
- Int64
b)
    Micro a :: Int64
a * :: Micro -> Micro -> Micro
* Micro b :: Int64
b = Int64 -> Micro
Micro (Int64 -> Int64 -> Int64
forall a. Integral a => a -> a -> a
quot Int64
a 1000 Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
* Int64 -> Int64 -> Int64
forall a. Integral a => a -> a -> a
quot Int64
b 1000)
    negate :: Micro -> Micro
negate (Micro a :: Int64
a) = Int64 -> Micro
Micro (Int64 -> Int64
forall a. Num a => a -> a
negate Int64
a)
    abs :: Micro -> Micro
abs (Micro a :: Int64
a) = Int64 -> Micro
Micro (Int64 -> Int64
forall a. Num a => a -> a
abs Int64
a)
    signum :: Micro -> Micro
signum (Micro a :: Int64
a) = Int64 -> Micro
Micro (Int64 -> Int64
forall a. Num a => a -> a
signum Int64
a Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
* 1000000)
    fromInteger :: Integer -> Micro
fromInteger a :: Integer
a = Int64 -> Micro
Micro (Integer -> Int64
forall a. Num a => Integer -> a
fromInteger Integer
a Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
* 1000000)

instance Real Micro where
    {-# INLINE toRational #-}
    toRational :: Micro -> Rational
toRational (Micro a :: Int64
a) = Int64 -> Integer
forall a. Integral a => a -> Integer
toInteger Int64
a Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% 1000000

instance Fractional Micro where
    {-# INLINE (/) #-}
    {-# INLINE recip #-}
    {-# INLINE fromRational #-}
    Micro a :: Int64
a / :: Micro -> Micro -> Micro
/ Micro b :: Int64
b = Int64 -> Micro
Micro (Int64 -> Int64 -> Int64
forall a. Integral a => a -> a -> a
quot (Int64
a Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
* 1000) (Int64
b Int64 -> Int64 -> Int64
forall a. Integral a => a -> a -> a
`quot` 1000))
    recip :: Micro -> Micro
recip (Micro a :: Int64
a) = Int64 -> Micro
Micro (Int64 -> Int64 -> Int64
forall a. Integral a => a -> a -> a
quot 1000000 Int64
a)
    fromRational :: Rational -> Micro
fromRational r :: Rational
r = Int64 -> Micro
Micro (Rational -> Int64
forall a b. (RealFrac a, Integral b) => a -> b
round (Rational -> Int64) -> Rational -> Int64
forall a b. (a -> b) -> a -> b
$ Rational
r Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* 1000000)

instance RealFrac Micro where
    {-# INLINE properFraction #-}
    properFraction :: Micro -> (b, Micro)
properFraction a :: Micro
a = (Int64 -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
q, Micro
r) where
        (q :: Int64
q, r :: Micro
r) = Micro -> Micro -> (Int64, Micro)
microQuotRem Micro
a (Int64 -> Micro
Micro 1000000)

deriving instance Num DiffTime
deriving instance Real DiffTime
deriving instance Fractional DiffTime
deriving instance RealFrac DiffTime

deriving instance Num NominalDiffTime
deriving instance Real NominalDiffTime
deriving instance Fractional NominalDiffTime
deriving instance RealFrac NominalDiffTime

{-# RULES

"realToFrac/DiffTime-NominalDiffTime"
    realToFrac = \ (DiffTime d) -> NominalDiffTime d
"realToFrac/NominalDiffTime-DiffTime"
    realToFrac = \ (NominalDiffTime d) -> DiffTime d

"realToFrac/DiffTime-Fractional"
    realToFrac = toSeconds :: (Fractional n) => DiffTime -> n
"realToFrac/NominalDiffTime-Fractional"
    realToFrac = toSeconds :: (Fractional n) => NominalDiffTime -> n

"realToFrac/Real-DiffTime"
    realToFrac = fromSeconds :: (Real n) => n -> DiffTime
"realToFrac/Real-NominalDiffTime"
    realToFrac = fromSeconds :: (Real n) => n -> NominalDiffTime #-}