module Database.RethinkDB.Time where
import Data.Text (Text)
import qualified Data.Time as Time
import qualified Data.Time.Clock.POSIX as Time
import Data.Aeson as JSON
import Data.Aeson.Types (Parser)
import Control.Monad
import Control.Applicative
import Database.RethinkDB.ReQL
import Database.RethinkDB.Protobuf.Ql2.Term.TermType
now :: ReQL
now = op NOW () ()
time :: ReQL -> ReQL -> ReQL -> ReQL -> ReQL -> ReQL -> ReQL -> ReQL
time y m d hh mm ss tz = op TIME [y, m, d, hh, mm, ss, tz] ()
epochTime :: ReQL -> ReQL
epochTime t = op EPOCH_TIME [t] ()
iso8601 :: ReQL -> ReQL
iso8601 t = op ISO8601 [t] ()
inTimezone :: Expr time => ReQL -> time -> ReQL
inTimezone tz t = op IN_TIMEZONE (t, tz) ()
data Bound a =
Open { boundValue :: a } |
Closed { boundValue :: a }
boundString :: Bound a -> Text
boundString Open{} = "open"
boundString Closed{} = "closed"
during :: (Expr left, Expr right, Expr time) => Bound left -> Bound right -> time -> ReQL
during l r t = op DURING (t, boundValue l, boundValue r) [
"left_bound" := boundString l, "right_bound" := boundString r]
timezone, date, timeOfDay, year, month, day, dayOfWeek, dayOfYear, hours, minutes, seconds ::
Expr time => time -> ReQL
timezone t = op TIMEZONE [t] ()
date t = op DATE [t] ()
timeOfDay t = op TIME_OF_DAY [t] ()
year t = op YEAR [t] ()
month t = op MONTH [t] ()
day t = op DAY [t] ()
dayOfWeek t = op DAY_OF_WEEK [t] ()
dayOfYear t = op DAY_OF_YEAR [t] ()
hours t = op HOURS [t] ()
minutes t = op MINUTES [t] ()
seconds t = op SECONDS [t] ()
toIso8601, toEpochTime :: Expr t => t -> ReQL
toIso8601 t = op TO_ISO8601 [t] ()
toEpochTime t = op TO_EPOCH_TIME [t] ()
newtype UTCTime = UTCTime Time.UTCTime
newtype ZonedTime = ZonedTime Time.ZonedTime
instance FromJSON UTCTime where
parseJSON (JSON.Object v) = UTCTime . Time.posixSecondsToUTCTime . fromRational <$> v .: "epoch_time"
parseJSON _ = mzero
instance FromJSON ZonedTime where
parseJSON (JSON.Object v) = do
tz <- v .: "timezone"
t <- v.: "epoch_time"
tz' <- parseTimeZone tz
return . ZonedTime $ Time.utcToZonedTime tz'
(Time.posixSecondsToUTCTime (fromRational t))
parseJSON _ = mzero
parseTimeZone :: String -> Parser Time.TimeZone
parseTimeZone "Z" = return Time.utc
parseTimeZone tz = Time.minutesToTimeZone <$> case tz of
('-':tz') -> negate <$> go tz'
('+':tz') -> go tz'
_ -> go tz
where
go tz' = do
(h, _:m) <- return $ break (==':') tz'
([(hh, "")], [(mm, "")]) <- return $ (reads h, reads m)
return $ hh * 60 + mm
instance Expr UTCTime where
expr (UTCTime t) = expr t
instance Expr ZonedTime where
expr (ZonedTime t) = expr t