{-# LANGUAGE CPP #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
-- |
-- Module      : Data.Hashable.Time
-- Description : Hashable instances for Data.Time types
-- License     : BSD3
-- Maintainer  : Alexey Karakulov <ankarakulov@gmail.com>
module Data.Hashable.Time (Hashable(..)) where

import Data.Fixed
import Data.Hashable (Hashable(..))
import Data.Time

#if !MIN_VERSION_time(1,5,0)
import System.Locale
#endif

-- Dependencies

-- ! (>=1.2.4) ~ <1.2.4 ~ <= 1.2.3
#if !MIN_VERSION_hashable(1,2,4)
-- https://github.com/tibbe/hashable/pull/101
instance Hashable (Fixed a) where
   hashWithSalt salt (MkFixed i) = hashWithSalt salt i
#endif

-- Data.Time.Clock

instance Hashable UniversalTime where
  hashWithSalt :: Int -> UniversalTime -> Int
hashWithSalt salt :: Int
salt = Int -> Rational -> Int
forall a. Hashable a => Int -> a -> Int
hashWithSalt Int
salt (Rational -> Int)
-> (UniversalTime -> Rational) -> UniversalTime -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UniversalTime -> Rational
getModJulianDate

instance Hashable DiffTime where
  hashWithSalt :: Int -> DiffTime -> Int
hashWithSalt salt :: Int
salt = Int -> Rational -> Int
forall a. Hashable a => Int -> a -> Int
hashWithSalt Int
salt (Rational -> Int) -> (DiffTime -> Rational) -> DiffTime -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DiffTime -> Rational
forall a. Real a => a -> Rational
toRational

instance Hashable UTCTime where
  hashWithSalt :: Int -> UTCTime -> Int
hashWithSalt salt :: Int
salt (UTCTime d :: Day
d dt :: DiffTime
dt) =
    Int
salt Int -> Day -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Day
d Int -> DiffTime -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` DiffTime
dt

instance Hashable NominalDiffTime where
  hashWithSalt :: Int -> NominalDiffTime -> Int
hashWithSalt salt :: Int
salt = Int -> Rational -> Int
forall a. Hashable a => Int -> a -> Int
hashWithSalt Int
salt (Rational -> Int)
-> (NominalDiffTime -> Rational) -> NominalDiffTime -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NominalDiffTime -> Rational
forall a. Real a => a -> Rational
toRational

-- Data.Time.Calendar

instance Hashable Day where
  hashWithSalt :: Int -> Day -> Int
hashWithSalt salt :: Int
salt (ModifiedJulianDay d :: Integer
d) = Int -> Integer -> Int
forall a. Hashable a => Int -> a -> Int
hashWithSalt Int
salt Integer
d

-- Data.Time.LocalTime

instance Hashable TimeZone where
  hashWithSalt :: Int -> TimeZone -> Int
hashWithSalt salt :: Int
salt (TimeZone m :: Int
m s :: Bool
s n :: String
n) =
    Int
salt Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Int
m Int -> Bool -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Bool
s Int -> String -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` String
n

instance Hashable TimeOfDay where
  hashWithSalt :: Int -> TimeOfDay -> Int
hashWithSalt salt :: Int
salt (TimeOfDay h :: Int
h m :: Int
m s :: Pico
s) =
    Int
salt Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Int
h Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Int
m Int -> Pico -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Pico
s

instance Hashable LocalTime where
  hashWithSalt :: Int -> LocalTime -> Int
hashWithSalt salt :: Int
salt (LocalTime d :: Day
d tod :: TimeOfDay
tod) =
    Int
salt Int -> Day -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Day
d Int -> TimeOfDay -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` TimeOfDay
tod

instance Hashable ZonedTime where
  hashWithSalt :: Int -> ZonedTime -> Int
hashWithSalt salt :: Int
salt (ZonedTime lt :: LocalTime
lt tz :: TimeZone
tz) =
    Int
salt Int -> LocalTime -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` LocalTime
lt Int -> TimeZone -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` TimeZone
tz

-- Data.Time.Locale / System.Locale

instance Hashable TimeLocale where
  hashWithSalt :: Int -> TimeLocale -> Int
hashWithSalt salt :: Int
salt (TimeLocale a :: [(String, String)]
a b :: [(String, String)]
b c :: (String, String)
c d :: String
d e :: String
e f :: String
f g :: String
g h :: [TimeZone]
h) =
    Int
salt Int -> [(String, String)] -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` [(String, String)]
a
         Int -> [(String, String)] -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` [(String, String)]
b
         Int -> (String, String) -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (String, String)
c
         Int -> String -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` String
d
         Int -> String -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` String
e
         Int -> String -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` String
f
         Int -> String -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` String
g
         Int -> [TimeZone] -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` [TimeZone]
h