packages feed

postgresql-simple-interval 0.2025.8.27 → 0.2025.9.5

raw patch · 4 files changed

+113/−3 lines, 4 filesdep +timePVP ok

version bump matches the API change (PVP)

Dependencies added: time

API changes (from Hackage documentation)

+ Database.PostgreSQL.Simple.Interval: fromTime :: CalendarDiffDays -> NominalDiffTime -> Maybe Interval
+ Database.PostgreSQL.Simple.Interval: fromTimeSaturating :: CalendarDiffDays -> NominalDiffTime -> Interval
+ Database.PostgreSQL.Simple.Interval: intoTime :: Interval -> (CalendarDiffDays, NominalDiffTime)
+ Database.PostgreSQL.Simple.Interval.Unstable: fromMicro :: Micro -> Integer
+ Database.PostgreSQL.Simple.Interval.Unstable: fromTime :: CalendarDiffDays -> NominalDiffTime -> Maybe Interval
+ Database.PostgreSQL.Simple.Interval.Unstable: fromTimeSaturating :: CalendarDiffDays -> NominalDiffTime -> Interval
+ Database.PostgreSQL.Simple.Interval.Unstable: intoMicro :: Integer -> Micro
+ Database.PostgreSQL.Simple.Interval.Unstable: intoTime :: Interval -> (CalendarDiffDays, NominalDiffTime)

Files

postgresql-simple-interval.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: postgresql-simple-interval-version: 0.2025.8.27+version: 0.2025.9.5 synopsis: A simple interval type for PostgreSQL. description:   This library provides a simple interval type for PostgreSQL. It supports@@ -28,6 +28,7 @@     base >=4.13 && <4.22,     bytestring >=0.10.10 && <0.13,     postgresql-simple ^>=0.7,+    time >=1.9.3 && <1.15,    default-language: Haskell2010   ghc-options:
source/library/Database/PostgreSQL/Simple/Interval.hs view
@@ -1,7 +1,7 @@ module Database.PostgreSQL.Simple.Interval   ( Unstable.Interval (..), -    -- * Constructors+    -- * Construction     Unstable.zero,     Unstable.fromMicroseconds,     Unstable.fromMilliseconds,@@ -29,10 +29,19 @@     Unstable.fromWeeksLiteral,     Unstable.fromYearsLiteral, +    -- * Conversion+    Unstable.intoTime,+    Unstable.fromTime,++    -- ** Saturating+    Unstable.fromTimeSaturating,+     -- * Arithmetic     Unstable.negate,-    Unstable.negateSaturating,     Unstable.add,++    -- ** Saturating+    Unstable.negateSaturating,     Unstable.addSaturating,   ) where
source/library/Database/PostgreSQL/Simple/Interval/Unstable.hs view
@@ -15,10 +15,12 @@ import qualified Data.ByteString.Builder as Builder import qualified Data.ByteString.Char8 as Ascii import qualified Data.ByteString.Lazy as LazyByteString+import qualified Data.Fixed as Fixed import qualified Data.Function as Function import qualified Data.Int as Int import qualified Data.Scientific as Scientific import qualified Data.Text as Text+import qualified Data.Time as Time import qualified Database.Persist as Persist import qualified Database.Persist.Sql as Persist import qualified Database.PostgreSQL.Simple.FromField as Postgres@@ -427,6 +429,67 @@         (Function.on safeAdd months x y)         (Function.on safeAdd days x y)         (Function.on safeAdd microseconds x y)++-- | Converts an interval into types from the @time@ library. See 'fromTime'+-- for the opposite conversion.+--+-- >>> intoTime (MkInterval 1 2 3)+-- (P1M2D,0.000003s)+intoTime :: Interval -> (Time.CalendarDiffDays, Time.NominalDiffTime)+intoTime x =+  ( Time.CalendarDiffDays+      { Time.cdMonths = toInteger $ months x,+        Time.cdDays = toInteger $ days x+      },+    Time.secondsToNominalDiffTime+      . realToFrac+      . intoMicro+      . toInteger+      $ microseconds x+  )++-- | Converts types from the @time@ library into an interval. See 'intoTime'+-- for the opposite conversion.+--+-- >>> fromTime ('Time.CalendarDiffDays' 1 2) 3+-- Just (MkInterval {months = 1, days = 2, microseconds = 3000000})+--+-- Returns 'Nothing' if the result would overflow. See 'fromTimeSaturating' for+-- a version that uses saturating arithmetic instead.+--+-- >>> fromTime mempty 9223372036854.775808+-- Nothing+--+-- Note that this truncates extra precision.+--+-- >>> fromTime mempty 0.0000009+-- Just (MkInterval {months = 0, days = 0, microseconds = 0})+fromTime :: Time.CalendarDiffDays -> Time.NominalDiffTime -> Maybe Interval+fromTime x y =+  MkInterval+    <$> Bits.toIntegralSized (Time.cdMonths x)+    <*> Bits.toIntegralSized (Time.cdDays x)+    <*> Bits.toIntegralSized (fromMicro . realToFrac $ Time.nominalDiffTimeToSeconds y)++-- | Like 'fromTime' but uses saturating arithmetic rather than returning+-- 'Maybe'.+--+-- >>> fromTimeSaturating ('Time.CalendarDiffDays' 1 2) 3+-- MkInterval {months = 1, days = 2, microseconds = 3000000}+-- >>> fromTimeSaturating mempty 9223372036854.775808+-- MkInterval {months = 1, days = 2, microseconds = 9223372036854775807}+fromTimeSaturating :: Time.CalendarDiffDays -> Time.NominalDiffTime -> Interval+fromTimeSaturating x y =+  MkInterval+    (toIntegralSaturating $ Time.cdMonths x)+    (toIntegralSaturating $ Time.cdDays x)+    (toIntegralSaturating . fromMicro . realToFrac $ Time.nominalDiffTimeToSeconds y)++intoMicro :: Integer -> Fixed.Micro+intoMicro = Fixed.MkFixed++fromMicro :: Fixed.Micro -> Integer+fromMicro (Fixed.MkFixed x) = x  -- | Renders an interval to a 'Builder'. This always has the same format: -- @"\@ A mon B day C hour D min E sec F us"@, where @A@, @B@, @C@, @D@, @E@,
source/test-suite/Main.hs view
@@ -11,6 +11,7 @@ import qualified Data.ByteString.Lazy as LazyByteString import qualified Data.Int as Int import qualified Data.Proxy as Proxy+import qualified Data.Time as Time import qualified Database.PostgreSQL.LibPQ as Pq import qualified Database.PostgreSQL.Simple as Postgres import qualified Database.PostgreSQL.Simple.Internal as Postgres@@ -230,6 +231,42 @@      H.it "succeeds with saturating microsecond" $ do       I.negateSaturating (I.MkInterval 0 0 minBound) `H.shouldBe` I.MkInterval 0 0 maxBound++  H.describe "intoTime" $ do+    H.it "works" $ do+      I.intoTime (I.MkInterval 1 2 3) `H.shouldBe` (Time.CalendarDiffDays 1 2, 0.000003)++  H.describe "fromTime" $ do+    H.it "succeeds with no overflow" $ do+      I.fromTime (Time.CalendarDiffDays 1 2) 0.000003 `H.shouldBe` Just (I.MkInterval 1 2 3)++    H.it "truncates extra precision" $ do+      I.fromTime mempty 0.0000009 `H.shouldBe` Just (I.MkInterval 0 0 0)++    H.it "fails with microsecond overflow" $ do+      I.fromTime mempty 9223372036854.775808 `H.shouldBe` Nothing++    H.it "fails with day overflow" $ do+      I.fromTime (Time.CalendarDiffDays 0 2147483648) 0 `H.shouldBe` Nothing++    H.it "fails with month overflow" $ do+      I.fromTime (Time.CalendarDiffDays 2147483648 0) 0 `H.shouldBe` Nothing++  H.describe "fromTimeSaturating" $ do+    H.it "works without saturating" $ do+      I.fromTimeSaturating (Time.CalendarDiffDays 1 2) 0.000003 `H.shouldBe` I.MkInterval 1 2 3++    H.it "truncates extra precision" $ do+      I.fromTimeSaturating mempty 0.0000009 `H.shouldBe` I.MkInterval 0 0 0++    H.it "works with saturating microseconds" $ do+      I.fromTimeSaturating mempty 9223372036854.775808 `H.shouldBe` I.MkInterval 0 0 maxBound++    H.it "works with saturating days" $ do+      I.fromTimeSaturating (Time.CalendarDiffDays 0 2147483648) 0 `H.shouldBe` I.MkInterval 0 maxBound 0++    H.it "works with saturating months" $ do+      I.fromTimeSaturating (Time.CalendarDiffDays 2147483648 0) 0 `H.shouldBe` I.MkInterval maxBound 0 0    H.describe "render" $ do     H.it "works with zero" $ do