-----------------------------------------------------------------------------
-- |
-- Module      :  Data.HodaTime.Offset
-- Copyright   :  (C) 2016 Jason Johnson
-- License     :  BSD-style (see the file LICENSE)
-- Maintainer  :  Jason Johnson <jason.johnson.081@gmail.com>
-- Stability   :  experimental
-- Portability :  TBD
--
-- An 'Offset' is a period of time offset from UTC time.  This module contains constructors and functions for working with 'Offsets'.
--
-- === Clamping
--
-- An offset must be between 18 hours and -18 hours (inclusive).  If you go outside this range the functions will clamp to the nearest value.
----------------------------------------------------------------------------
module Data.HodaTime.Offset
(
  -- * Types
   Offset
  -- * Constructors
  ,empty
  ,fromSeconds
  ,fromMinutes
  ,fromHours
  -- * Lenses
  ,seconds
  ,minutes
  ,hours
  -- * Math
  ,addClamped
  ,minusClamped
)
where

import Data.HodaTime.Offset.Internal
import Data.HodaTime.Internal (secondsFromMinutes, secondsFromHours, clamp, hoursFromSecs, minutesFromSecs, secondsFromSecs)

-- Offset specific constants

minOffsetHours :: Num a => a
minOffsetHours :: forall a. Num a => a
minOffsetHours = a -> a
forall a. Num a => a -> a
negate a
forall a. Num a => a
maxOffsetHours

maxOffsetMinutes :: Num a => a
maxOffsetMinutes :: forall a. Num a => a
maxOffsetMinutes = a
forall a. Num a => a
maxOffsetHours a -> a -> a
forall a. Num a => a -> a -> a
* a
60

minOffsetMinutes :: Num a => a
minOffsetMinutes :: forall a. Num a => a
minOffsetMinutes = a -> a
forall a. Num a => a -> a
negate a
forall a. Num a => a
maxOffsetMinutes

-- | Create an 'Offset' of (clamped) m minutes.
fromMinutes :: Integral a => a -> Offset
fromMinutes :: forall a. Integral a => a -> Offset
fromMinutes = Int -> Offset
Offset (Int -> Offset) -> (a -> Int) -> a -> Offset
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Int
forall a b. (Integral a, Num b) => a -> b
secondsFromMinutes (a -> Int) -> (a -> a) -> a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a -> a -> a
forall a. Ord a => a -> a -> a -> a
clamp a
forall a. Num a => a
minOffsetMinutes a
forall a. Num a => a
maxOffsetMinutes

-- | Create an 'Offset' of (clamped) h hours.
fromHours :: Integral a => a -> Offset
fromHours :: forall a. Integral a => a -> Offset
fromHours = Int -> Offset
Offset (Int -> Offset) -> (a -> Int) -> a -> Offset
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Int
forall a b. (Integral a, Num b) => a -> b
secondsFromHours (a -> Int) -> (a -> a) -> a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a -> a -> a
forall a. Ord a => a -> a -> a -> a
clamp a
forall a. Num a => a
minOffsetHours a
forall a. Num a => a
maxOffsetHours

-- | Lens for the seconds component of the 'Offset'
seconds :: Functor f => (Int -> f Int) -> Offset -> f Offset
seconds :: forall (f :: * -> *).
Functor f =>
(Int -> f Int) -> Offset -> f Offset
seconds Int -> f Int
f (Offset Int
secs) = (Int -> Offset) -> (Int -> f Int) -> Int -> f Offset
forall (f :: * -> *) b a.
(Functor f, Num b, Integral b) =>
(b -> a) -> (Int -> f Int) -> b -> f a
secondsFromSecs Int -> Offset
forall a. Integral a => a -> Offset
fromSeconds Int -> f Int
f Int
secs
{-# INLINE seconds #-}

-- | Lens for the minutes component of the 'Offset'
minutes :: Functor f => (Int -> f Int) -> Offset -> f Offset
minutes :: forall (f :: * -> *).
Functor f =>
(Int -> f Int) -> Offset -> f Offset
minutes Int -> f Int
f (Offset Int
secs) = (Int -> Offset) -> (Int -> f Int) -> Int -> f Offset
forall (f :: * -> *) b a.
(Functor f, Num b, Integral b) =>
(b -> a) -> (Int -> f Int) -> b -> f a
minutesFromSecs Int -> Offset
forall a. Integral a => a -> Offset
fromSeconds Int -> f Int
f Int
secs
{-# INLINE minutes #-}

-- | Lens for the hours component of the 'Offset'
hours :: Functor f => (Int -> f Int) -> Offset -> f Offset
hours :: forall (f :: * -> *).
Functor f =>
(Int -> f Int) -> Offset -> f Offset
hours Int -> f Int
f (Offset Int
secs) = (Int -> Offset) -> (Int -> f Int) -> Int -> f Offset
forall (f :: * -> *) b a.
(Functor f, Num b, Integral b) =>
(b -> a) -> (Int -> f Int) -> b -> f a
hoursFromSecs Int -> Offset
forall a. Integral a => a -> Offset
fromSeconds Int -> f Int
f Int
secs
{-# INLINE hours #-}