    -- |
    -- Module      : Data.Hourglass.Zone
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : unknown
    --
    -- Timezone utility
    --
    {-# LANGUAGE ExistentialQuantification #-}
    module Data.Hourglass.Zone
        ( Timezone(..)
        , UTC(..)
        , TimezoneMinutes(..)
        ) where

    -- | standard representation for timezone
    class Timezone tz where
        -- | offset in minutes from UTC. valid values should be between -12*60 to +14*60
        timezoneOffset :: tz -> Int
        -- | the name of the timezone. by default will be +-HH:MM encoding.
        timezoneName :: tz -> String
        timezoneName = Int -> String
    tzMinutesPrint (Int -> String) -> (tz -> Int) -> tz -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . tz -> Int
    forall tz. Timezone tz => tz -> Int
    timezoneOffset

    -- | Simple timezone containing the number of minutes difference
    -- with UTC.
    --
    -- Valid values should be between -12*60 to +14*60
    newtype TimezoneMinutes = TimezoneMinutes Int
        deriving (Int -> TimezoneMinutes -> ShowS
    [TimezoneMinutes] -> ShowS
    TimezoneMinutes -> String
    (Int -> TimezoneMinutes -> ShowS)
    -> (TimezoneMinutes -> String)
    -> ([TimezoneMinutes] -> ShowS)
    -> Show TimezoneMinutes
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [TimezoneMinutes] -> ShowS
    $cshowList :: [TimezoneMinutes] -> ShowS
    show :: TimezoneMinutes -> String
    $cshow :: TimezoneMinutes -> String
    showsPrec :: Int -> TimezoneMinutes -> ShowS
    $cshowsPrec :: Int -> TimezoneMinutes -> ShowS
    Show,TimezoneMinutes -> TimezoneMinutes -> Bool
    (TimezoneMinutes -> TimezoneMinutes -> Bool)
    -> (TimezoneMinutes -> TimezoneMinutes -> Bool)
    -> Eq TimezoneMinutes
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: TimezoneMinutes -> TimezoneMinutes -> Bool
    $c/= :: TimezoneMinutes -> TimezoneMinutes -> Bool
    == :: TimezoneMinutes -> TimezoneMinutes -> Bool
    $c== :: TimezoneMinutes -> TimezoneMinutes -> Bool
    Eq,Eq TimezoneMinutes
    Eq TimezoneMinutes =>
    (TimezoneMinutes -> TimezoneMinutes -> Ordering)
    -> (TimezoneMinutes -> TimezoneMinutes -> Bool)
    -> (TimezoneMinutes -> TimezoneMinutes -> Bool)
    -> (TimezoneMinutes -> TimezoneMinutes -> Bool)
    -> (TimezoneMinutes -> TimezoneMinutes -> Bool)
    -> (TimezoneMinutes -> TimezoneMinutes -> TimezoneMinutes)
    -> (TimezoneMinutes -> TimezoneMinutes -> TimezoneMinutes)
    -> Ord TimezoneMinutes
    TimezoneMinutes -> TimezoneMinutes -> Bool
    TimezoneMinutes -> TimezoneMinutes -> Ordering
    TimezoneMinutes -> TimezoneMinutes -> TimezoneMinutes
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    min :: TimezoneMinutes -> TimezoneMinutes -> TimezoneMinutes
    $cmin :: TimezoneMinutes -> TimezoneMinutes -> TimezoneMinutes
    max :: TimezoneMinutes -> TimezoneMinutes -> TimezoneMinutes
    $cmax :: TimezoneMinutes -> TimezoneMinutes -> TimezoneMinutes
    >= :: TimezoneMinutes -> TimezoneMinutes -> Bool
    $c>= :: TimezoneMinutes -> TimezoneMinutes -> Bool
    > :: TimezoneMinutes -> TimezoneMinutes -> Bool
    $c> :: TimezoneMinutes -> TimezoneMinutes -> Bool
    <= :: TimezoneMinutes -> TimezoneMinutes -> Bool
    $c<= :: TimezoneMinutes -> TimezoneMinutes -> Bool
    < :: TimezoneMinutes -> TimezoneMinutes -> Bool
    $c< :: TimezoneMinutes -> TimezoneMinutes -> Bool
    compare :: TimezoneMinutes -> TimezoneMinutes -> Ordering
    $ccompare :: TimezoneMinutes -> TimezoneMinutes -> Ordering
    $cp1Ord :: Eq TimezoneMinutes
    Ord)

    -- | Universal Time Coordinated. The generic computer "timezone".
    data UTC = UTC
        deriving (Int -> UTC -> ShowS
    [UTC] -> ShowS
    UTC -> String
    (Int -> UTC -> ShowS)
    -> (UTC -> String) -> ([UTC] -> ShowS) -> Show UTC
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [UTC] -> ShowS
    $cshowList :: [UTC] -> ShowS
    show :: UTC -> String
    $cshow :: UTC -> String
    showsPrec :: Int -> UTC -> ShowS
    $cshowsPrec :: Int -> UTC -> ShowS
    Show,UTC -> UTC -> Bool
    (UTC -> UTC -> Bool) -> (UTC -> UTC -> Bool) -> Eq UTC
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: UTC -> UTC -> Bool
    $c/= :: UTC -> UTC -> Bool
    == :: UTC -> UTC -> Bool
    $c== :: UTC -> UTC -> Bool
    Eq,Eq UTC
    Eq UTC =>
    (UTC -> UTC -> Ordering)
    -> (UTC -> UTC -> Bool)
    -> (UTC -> UTC -> Bool)
    -> (UTC -> UTC -> Bool)
    -> (UTC -> UTC -> Bool)
    -> (UTC -> UTC -> UTC)
    -> (UTC -> UTC -> UTC)
    -> Ord UTC
    UTC -> UTC -> Bool
    UTC -> UTC -> Ordering
    UTC -> UTC -> UTC
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    min :: UTC -> UTC -> UTC
    $cmin :: UTC -> UTC -> UTC
    max :: UTC -> UTC -> UTC
    $cmax :: UTC -> UTC -> UTC
    >= :: UTC -> UTC -> Bool
    $c>= :: UTC -> UTC -> Bool
    > :: UTC -> UTC -> Bool
    $c> :: UTC -> UTC -> Bool
    <= :: UTC -> UTC -> Bool
    $c<= :: UTC -> UTC -> Bool
    < :: UTC -> UTC -> Bool
    $c< :: UTC -> UTC -> Bool
    compare :: UTC -> UTC -> Ordering
    $ccompare :: UTC -> UTC -> Ordering
    $cp1Ord :: Eq UTC
    Ord)

    instance Timezone UTC where
        timezoneOffset :: UTC -> Int
    timezoneOffset _ = 0
        timezoneName :: UTC -> String
    timezoneName _   = "UTC"

    instance Timezone TimezoneMinutes where
        timezoneOffset :: TimezoneMinutes -> Int
    timezoneOffset (TimezoneMinutes minutes :: Int
    minutes) = Int
    minutes

    -- | print a minute offset in format:
    -- (+-)HH:MM
    tzMinutesPrint :: Int -> String
    tzMinutesPrint :: Int -> String
    tzMinutesPrint offset :: Int
    offset =
          (if Int
    offset Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > 0 then '+' else '-')
        Char -> ShowS
    forall a. a -> [a] -> [a]
    : (Int -> String
    forall a. (Ord a, Num a, Show a) => a -> String
    pad0 Int
    h String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ":" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Int -> String
    forall a. (Ord a, Num a, Show a) => a -> String
    pad0 Int
    m)
      where (h :: Int
    h,m :: Int
    m)  = Int -> Int
    forall a. Num a => a -> a
    abs Int
    offset Int -> Int -> (Int, Int)
    forall a. Integral a => a -> a -> (a, a)
    `divMod` 60
            pad0 :: a -> String
    pad0 v :: a
    v
                | a
    v a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    < 10    = '0'Char -> ShowS
    forall a. a -> [a] -> [a]
    :a -> String
    forall a. Show a => a -> String
    show a
    v
                | Bool
    otherwise = a -> String
    forall a. Show a => a -> String
    show a
    v