{-# LANGUAGE OverloadedStrings #-}
module Data.Time.ISO8601.Interval (
  IntervalSpec (..)
, Interval     (..)
, interval
, isoTime
, parseInterval
, formatInterval
, formatIntervalB
) where

import Data.Time.ISO8601.Duration

import           Control.Applicative
import           Data.Attoparsec.ByteString.Char8 as AP
import           Data.ByteString.Lex.Integral (readDecimal)
import           Data.ByteString (ByteString)
import           Data.ByteString.Lazy (toStrict)
import           Data.ByteString.Builder
import           Data.String (IsString(..))
import           Data.Time
import           Data.Time.Calendar.WeekDate (fromWeekDateValid)


data IntervalSpec
  = StartEnd       UTCTime  UTCTime
  | StartDuration  UTCTime  Duration
  | DurationEnd    Duration UTCTime
  | JustDuration   Duration
  deriving ( IntervalSpec -> IntervalSpec -> Bool
(IntervalSpec -> IntervalSpec -> Bool)
-> (IntervalSpec -> IntervalSpec -> Bool) -> Eq IntervalSpec
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: IntervalSpec -> IntervalSpec -> Bool
== :: IntervalSpec -> IntervalSpec -> Bool
$c/= :: IntervalSpec -> IntervalSpec -> Bool
/= :: IntervalSpec -> IntervalSpec -> Bool
Eq, Int -> IntervalSpec -> ShowS
[IntervalSpec] -> ShowS
IntervalSpec -> String
(Int -> IntervalSpec -> ShowS)
-> (IntervalSpec -> String)
-> ([IntervalSpec] -> ShowS)
-> Show IntervalSpec
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> IntervalSpec -> ShowS
showsPrec :: Int -> IntervalSpec -> ShowS
$cshow :: IntervalSpec -> String
show :: IntervalSpec -> String
$cshowList :: [IntervalSpec] -> ShowS
showList :: [IntervalSpec] -> ShowS
Show )

data Interval
  = Interval          IntervalSpec
  | RecurringInterval IntervalSpec (Maybe Integer)
  deriving ( Interval -> Interval -> Bool
(Interval -> Interval -> Bool)
-> (Interval -> Interval -> Bool) -> Eq Interval
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Interval -> Interval -> Bool
== :: Interval -> Interval -> Bool
$c/= :: Interval -> Interval -> Bool
/= :: Interval -> Interval -> Bool
Eq, Int -> Interval -> ShowS
[Interval] -> ShowS
Interval -> String
(Int -> Interval -> ShowS)
-> (Interval -> String) -> ([Interval] -> ShowS) -> Show Interval
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Interval -> ShowS
showsPrec :: Int -> Interval -> ShowS
$cshow :: Interval -> String
show :: Interval -> String
$cshowList :: [Interval] -> ShowS
showList :: [Interval] -> ShowS
Show )

parseInterval :: ByteString -> Either String Interval
parseInterval :: ByteString -> Either String Interval
parseInterval = Parser Interval -> ByteString -> Either String Interval
forall a. Parser a -> ByteString -> Either String a
parseOnly (Parser Interval
interval Parser Interval -> Parser ByteString () -> Parser Interval
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ByteString ()
forall t. Chunk t => Parser t ()
endOfInput)


interval :: Parser Interval
interval :: Parser Interval
interval =  Parser Interval
recurringInterval
        Parser Interval -> Parser Interval -> Parser Interval
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Interval
simpleInterval
  where
    recurringInterval :: Parser Interval
recurringInterval =
      (IntervalSpec -> Maybe Integer -> Interval)
-> Maybe Integer -> IntervalSpec -> Interval
forall a b c. (a -> b -> c) -> b -> a -> c
flip IntervalSpec -> Maybe Integer -> Interval
RecurringInterval (Maybe Integer -> IntervalSpec -> Interval)
-> Parser ByteString (Maybe Integer)
-> Parser ByteString (IntervalSpec -> Interval)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Parser Char
char Char
'R' Parser Char
-> Parser ByteString (Maybe Integer)
-> Parser ByteString (Maybe Integer)
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString Integer -> Parser ByteString (Maybe Integer)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser ByteString Integer
forall a. Integral a => Parser a
decimal Parser ByteString (Maybe Integer)
-> Parser Char -> Parser ByteString (Maybe Integer)
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser Char
char Char
'/')
                             Parser ByteString (IntervalSpec -> Interval)
-> Parser ByteString IntervalSpec -> Parser Interval
forall a b.
Parser ByteString (a -> b)
-> Parser ByteString a -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser ByteString IntervalSpec
intervalSpec
    simpleInterval :: Parser Interval
simpleInterval = IntervalSpec -> Interval
Interval (IntervalSpec -> Interval)
-> Parser ByteString IntervalSpec -> Parser Interval
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString IntervalSpec
intervalSpec

intervalSpec :: Parser IntervalSpec
intervalSpec :: Parser ByteString IntervalSpec
intervalSpec = Parser ByteString IntervalSpec
startEnd
           Parser ByteString IntervalSpec
-> Parser ByteString IntervalSpec -> Parser ByteString IntervalSpec
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ByteString IntervalSpec
startDuration
           Parser ByteString IntervalSpec
-> Parser ByteString IntervalSpec -> Parser ByteString IntervalSpec
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ByteString IntervalSpec
durationEnd
           Parser ByteString IntervalSpec
-> Parser ByteString IntervalSpec -> Parser ByteString IntervalSpec
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ByteString IntervalSpec
justDuration
  where
    startEnd :: Parser ByteString IntervalSpec
startEnd      = UTCTime -> UTCTime -> IntervalSpec
StartEnd      (UTCTime -> UTCTime -> IntervalSpec)
-> Parser ByteString UTCTime
-> Parser ByteString (UTCTime -> IntervalSpec)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString UTCTime
isoTime  Parser ByteString (UTCTime -> IntervalSpec)
-> Parser ByteString UTCTime -> Parser ByteString IntervalSpec
forall a b.
Parser ByteString (a -> b)
-> Parser ByteString a -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Char -> Parser Char
char Char
'/' Parser Char
-> Parser ByteString UTCTime -> Parser ByteString UTCTime
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString UTCTime
isoTime)
    startDuration :: Parser ByteString IntervalSpec
startDuration = UTCTime -> Duration -> IntervalSpec
StartDuration (UTCTime -> Duration -> IntervalSpec)
-> Parser ByteString UTCTime
-> Parser ByteString (Duration -> IntervalSpec)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString UTCTime
isoTime  Parser ByteString (Duration -> IntervalSpec)
-> Parser ByteString Duration -> Parser ByteString IntervalSpec
forall a b.
Parser ByteString (a -> b)
-> Parser ByteString a -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Char -> Parser Char
char Char
'/' Parser Char
-> Parser ByteString Duration -> Parser ByteString Duration
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString Duration
duration)
    durationEnd :: Parser ByteString IntervalSpec
durationEnd   = Duration -> UTCTime -> IntervalSpec
DurationEnd   (Duration -> UTCTime -> IntervalSpec)
-> Parser ByteString Duration
-> Parser ByteString (UTCTime -> IntervalSpec)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString Duration
duration Parser ByteString (UTCTime -> IntervalSpec)
-> Parser ByteString UTCTime -> Parser ByteString IntervalSpec
forall a b.
Parser ByteString (a -> b)
-> Parser ByteString a -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Char -> Parser Char
char Char
'/' Parser Char
-> Parser ByteString UTCTime -> Parser ByteString UTCTime
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString UTCTime
isoTime)
    justDuration :: Parser ByteString IntervalSpec
justDuration  = Duration -> IntervalSpec
JustDuration  (Duration -> IntervalSpec)
-> Parser ByteString Duration -> Parser ByteString IntervalSpec
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString Duration
duration


isoTime :: Parser UTCTime
isoTime :: Parser ByteString UTCTime
isoTime = do
  Day
d <- Parser Day
dayWeek Parser Day -> Parser Day -> Parser Day
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Day
day
  DiffTime
dt <- DiffTime
-> Parser ByteString DiffTime -> Parser ByteString DiffTime
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option DiffTime
0 (Char -> Parser (Maybe Char)
oChar Char
'T' Parser (Maybe Char)
-> Parser ByteString DiffTime -> Parser ByteString DiffTime
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString DiffTime
diffTime Parser ByteString DiffTime
-> Parser (Maybe Char) -> Parser ByteString DiffTime
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser (Maybe Char)
oChar Char
'Z') --FIXME: Parse tz offsets
  UTCTime -> Parser ByteString UTCTime
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return (Day -> DiffTime -> UTCTime
UTCTime Day
d DiffTime
dt)

day :: Parser Day
day :: Parser Day
day = Parser Day
day2 Parser Day -> Parser Day -> Parser Day
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Day
day1
  where day1 :: Parser Day
day1 = Integer -> Int -> Int -> Day
fromGregorian (Integer -> Int -> Int -> Day)
-> Parser ByteString Integer
-> Parser ByteString (Int -> Int -> Day)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Parser ByteString Integer
forall a. Integral a => Int -> Parser a
decimalN Int
4
                             Parser ByteString (Int -> Int -> Day)
-> Parser ByteString Int -> Parser ByteString (Int -> Day)
forall a b.
Parser ByteString (a -> b)
-> Parser ByteString a -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> Parser ByteString Int -> Parser ByteString Int
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option Int
1 (Char -> Parser Char
char Char
'-' Parser Char -> Parser ByteString Int -> Parser ByteString Int
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> Parser ByteString Int
intN Int
2)
                             Parser ByteString (Int -> Day)
-> Parser ByteString Int -> Parser Day
forall a b.
Parser ByteString (a -> b)
-> Parser ByteString a -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> Parser ByteString Int -> Parser ByteString Int
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option Int
1 (Char -> Parser Char
char Char
'-' Parser Char -> Parser ByteString Int -> Parser ByteString Int
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> Parser ByteString Int
intN Int
2)
        day2 :: Parser Day
day2 = Integer -> Int -> Int -> Day
fromGregorian (Integer -> Int -> Int -> Day)
-> Parser ByteString Integer
-> Parser ByteString (Int -> Int -> Day)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Parser ByteString Integer
forall a. Integral a => Int -> Parser a
decimalN Int
4 Parser ByteString (Int -> Int -> Day)
-> Parser ByteString Int -> Parser ByteString (Int -> Day)
forall a b.
Parser ByteString (a -> b)
-> Parser ByteString a -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> Parser ByteString Int
intN Int
2 Parser ByteString (Int -> Day)
-> Parser ByteString Int -> Parser Day
forall a b.
Parser ByteString (a -> b)
-> Parser ByteString a -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> Parser ByteString Int
intN Int
2

dayWeek :: Parser Day
dayWeek :: Parser Day
dayWeek = Parser Day -> (Day -> Parser Day) -> Maybe Day -> Parser Day
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> Parser Day
forall a. String -> Parser ByteString a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Invalid week day") Day -> Parser Day
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Day -> Parser Day)
-> Parser ByteString (Maybe Day) -> Parser Day
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Parser ByteString (Maybe Day)
go
  where
    go :: Parser ByteString (Maybe Day)
go = Integer -> Int -> Int -> Maybe Day
fromWeekDateValid
      (Integer -> Int -> Int -> Maybe Day)
-> Parser ByteString Integer
-> Parser ByteString (Int -> Int -> Maybe Day)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Parser ByteString Integer
forall a. Integral a => Int -> Parser a
decimalN Int
4
      Parser ByteString (Int -> Int -> Maybe Day)
-> Parser ByteString Int -> Parser ByteString (Int -> Maybe Day)
forall a b.
Parser ByteString (a -> b)
-> Parser ByteString a -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Parser ByteString ByteString
"-W" Parser ByteString ByteString
-> Parser ByteString Int -> Parser ByteString Int
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> Parser ByteString Int
intN Int
2)
      Parser ByteString (Int -> Maybe Day)
-> Parser ByteString Int -> Parser ByteString (Maybe Day)
forall a b.
Parser ByteString (a -> b)
-> Parser ByteString a -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> Parser ByteString Int -> Parser ByteString Int
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option Int
1 (Char -> Parser Char
char Char
'-' Parser Char -> Parser ByteString Int -> Parser ByteString Int
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> Parser ByteString Int
intN Int
1)

diffTime :: Parser DiffTime
diffTime :: Parser ByteString DiffTime
diffTime = do
  DiffTime
h <- Int -> DiffTime
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> DiffTime)
-> Parser ByteString Int -> Parser ByteString DiffTime
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Parser ByteString Int
intN Int
2
  DiffTime
m <- Int -> DiffTime
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> DiffTime)
-> Parser ByteString Int -> Parser ByteString DiffTime
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Parser ByteString Int -> Parser ByteString Int
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option Int
0 (Char -> Parser (Maybe Char)
oChar Char
':' Parser (Maybe Char)
-> Parser ByteString Int -> Parser ByteString Int
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> Parser ByteString Int
intN Int
2)
  DiffTime
s <- DiffTime
-> (Scientific -> DiffTime) -> Maybe Scientific -> DiffTime
forall b a. b -> (a -> b) -> Maybe a -> b
maybe DiffTime
0 Scientific -> DiffTime
forall a b. (Real a, Fractional b) => a -> b
realToFrac (Maybe Scientific -> DiffTime)
-> Parser ByteString (Maybe Scientific)
-> Parser ByteString DiffTime
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString Scientific
-> Parser ByteString (Maybe Scientific)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Char -> Parser (Maybe Char)
oChar Char
':' Parser (Maybe Char)
-> Parser ByteString Scientific -> Parser ByteString Scientific
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString Scientific
AP.scientific)
  DiffTime -> Parser ByteString DiffTime
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return (DiffTime
s DiffTime -> DiffTime -> DiffTime
forall a. Num a => a -> a -> a
+ DiffTime
mDiffTime -> DiffTime -> DiffTime
forall a. Num a => a -> a -> a
*DiffTime
60 DiffTime -> DiffTime -> DiffTime
forall a. Num a => a -> a -> a
+ DiffTime
hDiffTime -> DiffTime -> DiffTime
forall a. Num a => a -> a -> a
*DiffTime
3600)

intN :: Int -> Parser Int
intN :: Int -> Parser ByteString Int
intN = Int -> Parser ByteString Int
forall a. Integral a => Int -> Parser a
decimalN

decimalN :: Integral a => Int -> Parser a
decimalN :: forall a. Integral a => Int -> Parser a
decimalN Int
n =
  Parser ByteString a
-> ((a, ByteString) -> Parser ByteString a)
-> Maybe (a, ByteString)
-> Parser ByteString a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> Parser ByteString a
forall a. String -> Parser ByteString a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"not an int") (a -> Parser ByteString a
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> Parser ByteString a)
-> ((a, ByteString) -> a) -> (a, ByteString) -> Parser ByteString a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a, ByteString) -> a
forall a b. (a, b) -> a
fst) (Maybe (a, ByteString) -> Parser ByteString a)
-> Parser ByteString (Maybe (a, ByteString)) -> Parser ByteString a
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (ByteString -> Maybe (a, ByteString))
-> Parser ByteString ByteString
-> Parser ByteString (Maybe (a, ByteString))
forall a b. (a -> b) -> Parser ByteString a -> Parser ByteString b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> Maybe (a, ByteString)
forall a. Integral a => ByteString -> Maybe (a, ByteString)
readDecimal (Int -> Parser ByteString ByteString
AP.take Int
n)

oChar :: Char -> Parser (Maybe Char)
oChar :: Char -> Parser (Maybe Char)
oChar = Parser Char -> Parser (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser Char -> Parser (Maybe Char))
-> (Char -> Parser Char) -> Char -> Parser (Maybe Char)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Parser Char
char


formatInterval :: Interval -> ByteString
formatInterval :: Interval -> ByteString
formatInterval = ByteString -> ByteString
toStrict (ByteString -> ByteString)
-> (Interval -> ByteString) -> Interval -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> ByteString
toLazyByteString (Builder -> ByteString)
-> (Interval -> Builder) -> Interval -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Interval -> Builder
formatIntervalB

formatIntervalB :: Interval -> Builder
formatIntervalB :: Interval -> Builder
formatIntervalB (RecurringInterval IntervalSpec
i Maybe Integer
r) = Builder
"R" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder -> (Integer -> Builder) -> Maybe Integer -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
"" Integer -> Builder
forall a. Show a => a -> Builder
bShow Maybe Integer
r Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"/"
                                              Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> IntervalSpec -> Builder
formatIntervalSpec IntervalSpec
i
formatIntervalB (Interval IntervalSpec
i)            = IntervalSpec -> Builder
formatIntervalSpec IntervalSpec
i

formatIntervalSpec :: IntervalSpec -> Builder
formatIntervalSpec :: IntervalSpec -> Builder
formatIntervalSpec (StartEnd UTCTime
s1 UTCTime
s2)      = UTCTime -> Builder
formatIsoTime   UTCTime
s1 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"/" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> UTCTime -> Builder
formatIsoTime   UTCTime
s2
formatIntervalSpec (StartDuration UTCTime
s1 Duration
s2) = UTCTime -> Builder
formatIsoTime   UTCTime
s1 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"/" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Duration -> Builder
formatDurationB Duration
s2
formatIntervalSpec (DurationEnd Duration
s1 UTCTime
s2)   = Duration -> Builder
formatDurationB Duration
s1 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"/" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> UTCTime -> Builder
formatIsoTime   UTCTime
s2
formatIntervalSpec (JustDuration Duration
s)      = Duration -> Builder
formatDurationB Duration
s

formatIsoTime :: UTCTime -> Builder
formatIsoTime :: UTCTime -> Builder
formatIsoTime = String -> Builder
forall a. IsString a => String -> a
fromString (String -> Builder) -> (UTCTime -> String) -> UTCTime -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeLocale -> String -> UTCTime -> String
forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale String
"%FT%T%QZ"

bShow :: Show a => a -> Builder
bShow :: forall a. Show a => a -> Builder
bShow = String -> Builder
forall a. IsString a => String -> a
fromString (String -> Builder) -> (a -> String) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show