Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix date literals #532

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Test/Test.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1247,16 +1247,23 @@ testLiterals = do
it "sqlBool" $ testLiteral O.sqlBool True
it "sqlUUID" $ testLiteral O.sqlUUID (read "c2cc10e1-57d6-4b6f-9899-38d972112d8c")
it "sqlDay" $ testLiteral O.sqlDay (read "2018-11-29")
it "sqlDayPadded" $ testLiteral O.sqlDay (read "20-11-21")
it "sqlUTCTime" $ testLiteral O.sqlUTCTime (read "2018-11-29 11:22:33 UTC")
it "sqlUTCTimePadded" $ testLiteral O.sqlUTCTime (read "20-11-21 11:22:33 UTC")
it "sqlLocalTime" $ testLiteral O.sqlLocalTime (read "2018-11-29 11:22:33")
it "sqlLocalTimePadded" $ testLiteral O.sqlLocalTime (read "20-11-21 11:22:33")
it "sqlInterval" $ testLiteral O.sqlInterval (Time.calendarTimeTime 1)

-- ZonedTime has no Eq instance, so we compare on the result of 'zonedTimeToUTC'
it "sqlZonedTime" $
let value = read "2018-11-29 11:22:33 UTC" :: Time.ZonedTime in
testH (pure (O.sqlZonedTime value))
(\r -> map Time.zonedTimeToUTC r `shouldBe` [Time.zonedTimeToUTC value])

it "sqlInterval" $ testLiteral O.sqlInterval (Time.calendarTimeTime 1)
it "sqlZonedTimePadded" $
let value = read "20-11-21 11:22:33 UTC" :: Time.ZonedTime in
testH (pure (O.sqlZonedTime value))
(\r -> map Time.zonedTimeToUTC r `shouldBe` [Time.zonedTimeToUTC value])

-- Check that MaybeFields's "Nothings" are not distinct, even if we
-- fmap different values over their inner fields.
Expand Down Expand Up @@ -1379,6 +1386,7 @@ testAddIntervalFromTimeToTime = do
(realToFrac (Time.ctTime c :: Time.NominalDiffTime) :: Time.DiffTime)
+ Time.timeOfDayToTime t


main :: IO ()
main = do
let envVarName = "POSTGRES_CONNSTRING"
Expand Down
6 changes: 3 additions & 3 deletions opaleye-sqlite/src/Opaleye/SQLite/PGTypes.hs
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@ unsafePgFormatTime = IPT.unsafePgFormatTime
#-}

pgDay :: Time.Day -> Column PGDate
pgDay = IPT.unsafePgFormatTime "date" "'%F'"
pgDay = IPT.unsafePgFormatTime "date" "'%0Y-%m-%d'"

pgUTCTime :: Time.UTCTime -> Column PGTimestamptz
pgUTCTime = IPT.unsafePgFormatTime "timestamptz" "'%FT%TZ'"
pgUTCTime = IPT.unsafePgFormatTime "timestamptz" "'%0Y-%m-%dT%TZ'"

pgLocalTime :: Time.LocalTime -> Column PGTimestamp
pgLocalTime = IPT.unsafePgFormatTime "timestamp" "'%FT%T'"
pgLocalTime = IPT.unsafePgFormatTime "timestamp" "'%0Y-%m-%dT%T'"

pgTimeOfDay :: Time.TimeOfDay -> Column PGTime
pgTimeOfDay = IPT.unsafePgFormatTime "time" "'%T'"
Expand Down
1 change: 1 addition & 0 deletions opaleye.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ library
, semigroups >= 0.13 && < 0.20
, text >= 0.11 && < 1.3
, transformers >= 0.3 && < 0.6
, time >= 1.9.3 && < 2
, time-compat >= 1.9.5 && < 1.12
, time-locale-compat >= 0.1 && < 0.2
, uuid >= 1.3 && < 1.4
Expand Down
9 changes: 4 additions & 5 deletions src/Opaleye/Internal/PGTypes.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@ import qualified Data.Text.Lazy as LText
import qualified Data.Text.Lazy.Encoding as LTextEncoding
import qualified Data.ByteString as SByteString
import qualified Data.ByteString.Lazy as LByteString
import qualified Data.Time.Compat as Time
import qualified Data.Time.Locale.Compat as Locale
import qualified Data.Time.Format.ISO8601 as Time

unsafePgFormatTime :: Time.FormatTime t => HPQ.Name -> String -> t -> Column c
unsafePgFormatTime typeName formatString = castToType typeName . format
where format = Time.formatTime Locale.defaultTimeLocale formatString
unsafePgFormatTime :: Time.ISO8601 t => HPQ.Name -> t -> Column c
unsafePgFormatTime typeName = castToType typeName . format
where format s = "'" ++ Time.iso8601Show s ++ "'"

literalColumn :: forall a. IsSqlType a => HPQ.Literal -> Column a
literalColumn = Column . HPQ.CastExpr (showSqlType (Proxy :: Proxy a)) . HPQ.ConstExpr
Expand Down
15 changes: 6 additions & 9 deletions src/Opaleye/Internal/PGTypesExternal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import qualified Data.ByteString as SByteString
import qualified Data.ByteString.Lazy as LByteString
import Data.Scientific as Sci
import qualified Data.Time.Compat as Time
import qualified Data.Time.Format.ISO8601.Compat as Time.Format.ISO8601
import qualified Data.UUID as UUID

import Data.Int (Int64)
Expand Down Expand Up @@ -102,27 +101,25 @@ pgUUID :: UUID.UUID -> Column PGUuid
pgUUID = IPT.literalColumn . HPQ.StringLit . UUID.toString

pgDay :: Time.Day -> Column PGDate
pgDay = IPT.unsafePgFormatTime "date" "'%F'"
pgDay = IPT.unsafePgFormatTime "date"

pgUTCTime :: Time.UTCTime -> Column PGTimestamptz
pgUTCTime = IPT.unsafePgFormatTime "timestamptz" "'%FT%T%QZ'"
pgUTCTime = IPT.unsafePgFormatTime "timestamptz"

pgLocalTime :: Time.LocalTime -> Column PGTimestamp
pgLocalTime = IPT.unsafePgFormatTime "timestamp" "'%FT%T%Q'"
pgLocalTime = IPT.unsafePgFormatTime "timestamp"

pgZonedTime :: Time.ZonedTime -> Column PGTimestamptz
pgZonedTime = IPT.unsafePgFormatTime "timestamptz" "'%FT%T%Q%z'"
pgZonedTime = IPT.unsafePgFormatTime "timestamptz"

pgTimeOfDay :: Time.TimeOfDay -> Column PGTime
pgTimeOfDay = IPT.unsafePgFormatTime "time" "'%T%Q'"
pgTimeOfDay = IPT.unsafePgFormatTime "time"

-- "We recommend not using the type time with time zone"
-- http://www.postgresql.org/docs/8.3/static/datatype-datetime.html

sqlInterval :: Time.CalendarDiffTime -> Column PGInterval
sqlInterval = IPT.castToType "interval" . quote . Time.Format.ISO8601.iso8601Show
where
quote s = "'" ++ s ++ "'"
sqlInterval = IPT.unsafePgFormatTime "interval"

pgCiStrictText :: CI.CI SText.Text -> Column PGCitext
pgCiStrictText = IPT.literalColumn . HPQ.StringLit . SText.unpack . CI.original
Expand Down