Skip to content

Commit

Permalink
Fix ISO 8601 formatting
Browse files Browse the repository at this point in the history
See #532 (comment)

Thanks to @kozak
  • Loading branch information
tomjaguarpaw committed Nov 4, 2021
1 parent 801d6eb commit 2995835
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 13 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
Fix ISO 8601 date fomatting. Thanks to Michal @kozak.

## 0.7.6.1

No user-visible changes
Expand Down
10 changes: 10 additions & 0 deletions Test/Test.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,8 @@ testLiterals = do
exampleDate = Time.fromGregorian 2018 11 29
exampleTime = Time.TimeOfDay 11 22 33
exampleUTCTime = Time.UTCTime exampleDate (Time.sinceMidnight exampleTime)
exampleDatePadded = Time.fromGregorian 18 11 29
exampleUTCTimePadded = Time.UTCTime exampleDatePadded (Time.sinceMidnight exampleTime)
it "sqlString" $ testLiteral O.sqlString "Hello"
it "sqlLazyByteString" $ testLiteral O.sqlLazyByteString "Hello"
it "sqlNumeric" $ testLiteral O.sqlNumeric 3.14159
Expand All @@ -1250,15 +1252,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 exampleDate
it "sqlDayPadded" $ testLiteral O.sqlDay exampleDatePadded
it "sqlUTCTime" $ testLiteral O.sqlUTCTime exampleUTCTime
it "sqlUTCTimePadded" $ testLiteral O.sqlUTCTime exampleUTCTimePadded
it "sqlLocalTime" $ testLiteral O.sqlLocalTime (Time.LocalTime exampleDate exampleTime)
it "sqlLocalTimePadded" $ testLiteral O.sqlLocalTime (Time.LocalTime exampleDatePadded exampleTime)

-- ZonedTime has no Eq instance, so we compare on the result of 'zonedTimeToUTC'
it "sqlZonedTime" $
let value = Time.utcToZonedTime Time.utc exampleUTCTime in
testH (pure (O.sqlZonedTime value))
(\r -> map Time.zonedTimeToUTC r `shouldBe` [Time.zonedTimeToUTC value])

it "sqlZonedTimePadded" $
let value = Time.utcToZonedTime Time.utc exampleUTCTimePadded in
testH (pure (O.sqlZonedTime value))
(\r -> map Time.zonedTimeToUTC r `shouldBe` [Time.zonedTimeToUTC value])

it "sqlInterval" $ testLiteral O.sqlInterval (Time.calendarTimeTime 1)

-- Check that MaybeFields's "Nothings" are not distinct, even if we
Expand Down
11 changes: 6 additions & 5 deletions src/Opaleye/Internal/PGTypes.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ 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.Compat 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 = quote . Time.iso8601Show
quote s = "'" ++ s ++ "'"

literalColumn :: forall a. IsSqlType a => HPQ.Literal -> Column a
literalColumn = Column . HPQ.CastExpr (showSqlType (Proxy :: Proxy a)) . HPQ.ConstExpr
Expand Down
14 changes: 6 additions & 8 deletions src/Opaleye/Internal/PGTypesExternal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -102,27 +102,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

0 comments on commit 2995835

Please sign in to comment.