@@ -22,17 +22,22 @@ module Network.Google.Data.Time
23import Control.Lens
23import Control.Lens
24import Data.Aeson
24import Data.Aeson
25−import qualified Data.Aeson.Types as Aeson
25+import qualified Data.Aeson.Types as Aeson
26import Data.Attoparsec.Text
26import Data.Attoparsec.Text
27−import Data.Bifunctor (first, second)
27+import Data.Bifunctor (first, second)
28−import Data.Bits ((.&.))
28+import Data.Bits ((.&.))
29−import Data.Char (ord)
29+import Data.Char (ord)
30−import Data.Data (Data, Typeable)
30+import Data.Data (Data, Typeable)
31+import Data.Scientific (Scientific)
32+import qualified Data.Scientific as Sci
31−import Data.Text (Text)
33+import Data.Text (Text)
32−import qualified Data.Text as 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
33import Data.Time
37import Data.Time
34import GHC.Generics
38import GHC.Generics
35−import Web.HttpApiData (FromHttpApiData (..), ToHttpApiData (..))
39+import Web.HttpApiData (FromHttpApiData (..),
37-- | This SHOULD be a time in the format of hh:mm:ss. It is
42-- | This SHOULD be a time in the format of hh:mm:ss. It is
38-- recommended that you use the "date-time" format instead of "time"
43-- recommended that you use the "date-time" format instead of "time"
@@ -66,10 +71,25 @@ newtype DateTime' = DateTime' { unDateTime :: UTCTime }
66_DateTime :: Iso' DateTime' UTCTime
71_DateTime :: Iso' DateTime' UTCTime
67_DateTime = iso unDateTime DateTime'
72_DateTime = iso unDateTime DateTime'
74+-- | A duration in seconds with up to nine fractional digits, terminated by 's'.
76+-- /Example/: @"3.5s"@.
77+newtype Duration = Duration { unDuration :: Scientific }
78+ deriving (Eq, Ord, Show, Generic, Data, Typeable)
80+_Duration :: Iso' Duration Scientific
81+_Duration = iso unDuration Duration
69instance ToJSON Time' where toJSON = String . toQueryParam
83instance ToJSON Time' where toJSON = String . toQueryParam
70instance ToJSON Date' where toJSON = String . toQueryParam
84instance ToJSON Date' where toJSON = String . toQueryParam
71instance ToJSON DateTime' where toJSON = toJSON . unDateTime
85instance ToJSON DateTime' where toJSON = toJSON . unDateTime
87+instance ToJSON Duration where
90+ . Sci.formatScientificBuilder Sci.Fixed (Just 9)
73instance FromJSON Time' where
93instance FromJSON Time' where
74 parseJSON = fmap Time' . withText "time" (run timeParser)
94 parseJSON = fmap Time' . withText "time" (run timeParser)
@@ -79,6 +99,9 @@ instance FromJSON Date' where
79instance FromJSON DateTime' where
99instance FromJSON DateTime' where
80 parseJSON = fmap DateTime' . parseJSON
100 parseJSON = fmap DateTime' . parseJSON
102+instance FromJSON Duration where
103+ parseJSON = fmap Duration . withText "duration" (run durationParser)
82parseText :: Parser a -> Text -> Either Text a
105parseText :: Parser a -> Text -> Either Text a
83parseText p = first Text.pack . parseOnly p
106parseText p = first Text.pack . parseOnly p
@@ -100,6 +123,9 @@ dayParser = do
100 d <- twoDigits
123 d <- twoDigits
101 maybe (fail "invalid date") pure (fromGregorianValid y m d)
124 maybe (fail "invalid date") pure (fromGregorianValid y m d)
126+durationParser :: Parser Scientific
127+durationParser = Sci.fromFloatDigits <$> (double <* char 's')
103-- | Parse a two-digit integer (e.g. day of month, hour).
129-- | Parse a two-digit integer (e.g. day of month, hour).
104twoDigits :: Parser Int
130twoDigits :: Parser Int
105twoDigits = do
131twoDigits = do