@@ -22,17 +22,22 @@ module Network.Google.Data.Time
2222
2323import Control.Lens
2424import Data.Aeson
25−import qualified Data.Aeson.Types as Aeson
25+import qualified Data.Aeson.Types as Aeson
2626import Data.Attoparsec.Text
27−import Data.Bifunctor (first, second)
28−import Data.Bits ((.&.))
29−import Data.Char (ord)
30−import Data.Data (Data, Typeable)
31−import Data.Text (Text)
32−import qualified Data.Text as Text
27+import Data.Bifunctor (first, second)
28+import Data.Bits ((.&.))
29+import Data.Char (ord)
30+import Data.Data (Data, Typeable)
31+import Data.Scientific (Scientific)
32+import qualified Data.Scientific as Sci
33+import Data.Text (Text)
34+import qualified Data.Text as Text
35+import qualified Data.Text.Lazy.Builder as Build
36+import qualified Data.Text.Lazy.Builder.Scientific as Sci
3337import Data.Time
3438import GHC.Generics
35−import Web.HttpApiData (FromHttpApiData (..), ToHttpApiData (..))
39+import Web.HttpApiData (FromHttpApiData (..),
40+ ToHttpApiData (..))
3641
3742-- | This SHOULD be a time in the format of hh:mm:ss. It is
3843-- recommended that you use the "date-time" format instead of "time"
@@ -66,10 +71,25 @@ newtype DateTime' = DateTime' { unDateTime :: UTCTime }
6671_DateTime :: Iso' DateTime' UTCTime
6772_DateTime = iso unDateTime DateTime'
6873
74+-- | A duration in seconds with up to nine fractional digits, terminated by 's'.
75+--
76+-- /Example/: @"3.5s"@.
77+newtype Duration = Duration { unDuration :: Scientific }
78+ deriving (Eq, Ord, Show, Generic, Data, Typeable)
79+
80+_Duration :: Iso' Duration Scientific
81+_Duration = iso unDuration Duration
82+
6983instance ToJSON Time' where toJSON = String . toQueryParam
7084instance ToJSON Date' where toJSON = String . toQueryParam
7185instance ToJSON DateTime' where toJSON = toJSON . unDateTime
7286
87+instance ToJSON Duration where
88+ toJSON = toJSON
89+ . Build.toLazyText
90+ . Sci.formatScientificBuilder Sci.Fixed (Just 9)
91+ . unDuration
92+
7393instance FromJSON Time' where
7494 parseJSON = fmap Time' . withText "time" (run timeParser)
7595
@@ -79,6 +99,9 @@ instance FromJSON Date' where
7999instance FromJSON DateTime' where
80100 parseJSON = fmap DateTime' . parseJSON
81101
102+instance FromJSON Duration where
103+ parseJSON = fmap Duration . withText "duration" (run durationParser)
104+
82105parseText :: Parser a -> Text -> Either Text a
83106parseText p = first Text.pack . parseOnly p
84107
@@ -100,6 +123,9 @@ dayParser = do
100123 d <- twoDigits
101124 maybe (fail "invalid date") pure (fromGregorianValid y m d)
102125
126+durationParser :: Parser Scientific
127+durationParser = Sci.fromFloatDigits <$> (double <* char 's')
128+
103129-- | Parse a two-digit integer (e.g. day of month, hour).
104130twoDigits :: Parser Int
105131twoDigits = do