postgresql-types 0.1.5.1 → 0.1.6.0
raw patch · 5 files changed
+59/−1 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ PostgresqlTypes.Timestamp: refineFromLocalTime :: LocalTime -> Maybe Timestamp
+ PostgresqlTypes.Timestamptz: refineFromUtcTime :: UTCTime -> Maybe Timestamptz
Files
- postgresql-types.cabal +1/−1
- src/library/PostgresqlTypes/Timestamp.hs +15/−0
- src/library/PostgresqlTypes/Timestamptz.hs +15/−0
- src/unit-tests/PostgresqlTypes/TimestampSpec.hs +14/−0
- src/unit-tests/PostgresqlTypes/TimestamptzSpec.hs +14/−0
postgresql-types.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: postgresql-types-version: 0.1.5.1+version: 0.1.6.0 category: PostgreSQL, Codecs synopsis: Precise PostgreSQL types representation and driver-agnostic codecs description:
src/library/PostgresqlTypes/Timestamp.hs view
@@ -8,6 +8,7 @@ -- * Constructors normalizeFromMicroseconds, normalizeFromLocalTime,+ refineFromLocalTime, ) where @@ -154,6 +155,20 @@ let diffTime = Time.diffLocalTime localTime postgresTimestampEpoch micros = round (diffTime * 1_000_000) in normalizeFromMicroseconds micros++-- | Construct a PostgreSQL 'Timestamp' from 'Time.LocalTime', validating that+-- it is representable exactly (both within range and without loss of+-- sub-microsecond precision). Returns 'Nothing' if the value is outside the+-- valid range or cannot be round-tripped without loss.+refineFromLocalTime :: Time.LocalTime -> Maybe Timestamp+refineFromLocalTime localTime =+ let diffTime = Time.diffLocalTime localTime postgresTimestampEpoch+ micros = round (diffTime * 1_000_000)+ in if micros >= minMicroseconds+ && micros <= maxMicroseconds+ && toLocalTime (Timestamp micros) == localTime+ then Just (Timestamp micros)+ else Nothing -- | Format a LocalTime for PostgreSQL timestamp text format. -- PostgreSQL requires specific formatting for extreme dates:
src/library/PostgresqlTypes/Timestamptz.hs view
@@ -8,6 +8,7 @@ -- * Constructors normalizeFromMicroseconds, normalizeFromUtcTime,+ refineFromUtcTime, ) where @@ -165,6 +166,20 @@ let diffTime = Time.diffUTCTime utcTime postgresUtcEpoch micros = round (diffTime * 1_000_000) in normalizeFromMicroseconds micros++-- | Construct a PostgreSQL 'Timestamptz' from 'Time.UTCTime', validating that+-- it is representable exactly (both within range and without loss of+-- sub-microsecond precision). Returns 'Nothing' if the value is outside the+-- valid range or cannot be round-tripped without loss.+refineFromUtcTime :: Time.UTCTime -> Maybe Timestamptz+refineFromUtcTime utcTime =+ let diffTime = Time.diffUTCTime utcTime postgresUtcEpoch+ micros = round (diffTime * 1_000_000)+ in if micros >= minMicroseconds+ && micros <= maxMicroseconds+ && toUtcTime (Timestamptz micros) == utcTime+ then Just (Timestamptz micros)+ else Nothing -- | Format a UTCTime for PostgreSQL timestamptz text format. -- PostgreSQL requires specific formatting for extreme dates:
src/unit-tests/PostgresqlTypes/TimestampSpec.hs view
@@ -6,6 +6,7 @@ import Test.Hspec import Test.QuickCheck import qualified UnitTests.Scripts as Scripts+import Prelude spec :: Spec spec = do@@ -30,6 +31,19 @@ localTime = Time.LocalTime day tod pgTimestamp = Timestamp.normalizeFromLocalTime localTime Timestamp.toLocalTime pgTimestamp `shouldBe` localTime++ describe "refineFromLocalTime" do+ it "accepts a LocalTime within range and precision" do+ let day = Time.fromGregorian 2023 6 15+ tod = Time.TimeOfDay 12 30 45+ localTime = Time.LocalTime day tod+ fmap Timestamp.toLocalTime (Timestamp.refineFromLocalTime localTime) `shouldBe` Just localTime++ it "rejects a LocalTime with sub-microsecond precision" do+ let day = Time.fromGregorian 2023 6 15+ tod = Time.TimeOfDay 12 30 45.1234565+ localTime = Time.LocalTime day tod+ Timestamp.refineFromLocalTime localTime `shouldBe` Nothing describe "Accessors" do describe "toLocalTime" do
src/unit-tests/PostgresqlTypes/TimestamptzSpec.hs view
@@ -6,6 +6,7 @@ import Test.Hspec import Test.QuickCheck import qualified UnitTests.Scripts as Scripts+import Prelude spec :: Spec spec = do@@ -30,6 +31,19 @@ utcTime = Time.UTCTime day diffTime pgTimestamptz = Timestamptz.normalizeFromUtcTime utcTime Timestamptz.toUtcTime pgTimestamptz `shouldBe` utcTime++ describe "refineFromUtcTime" do+ it "accepts a UTCTime within range and precision" do+ let day = Time.fromGregorian 2023 6 15+ diffTime = Time.secondsToDiffTime 45045 -- 12:30:45+ utcTime = Time.UTCTime day diffTime+ fmap Timestamptz.toUtcTime (Timestamptz.refineFromUtcTime utcTime) `shouldBe` Just utcTime++ it "rejects a UTCTime with sub-microsecond precision" do+ let day = Time.fromGregorian 2023 6 15+ diffTime = Time.picosecondsToDiffTime (45045 * 1_000_000_000_000 + 123_456_500)+ utcTime = Time.UTCTime day diffTime+ Timestamptz.refineFromUtcTime utcTime `shouldBe` Nothing describe "Accessors" do describe "toUtcTime" do