diff --git a/postgresql-simple-interval.cabal b/postgresql-simple-interval.cabal
--- a/postgresql-simple-interval.cabal
+++ b/postgresql-simple-interval.cabal
@@ -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:
diff --git a/source/library/Database/PostgreSQL/Simple/Interval.hs b/source/library/Database/PostgreSQL/Simple/Interval.hs
--- a/source/library/Database/PostgreSQL/Simple/Interval.hs
+++ b/source/library/Database/PostgreSQL/Simple/Interval.hs
@@ -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
diff --git a/source/library/Database/PostgreSQL/Simple/Interval/Unstable.hs b/source/library/Database/PostgreSQL/Simple/Interval/Unstable.hs
--- a/source/library/Database/PostgreSQL/Simple/Interval/Unstable.hs
+++ b/source/library/Database/PostgreSQL/Simple/Interval/Unstable.hs
@@ -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@,
diff --git a/source/test-suite/Main.hs b/source/test-suite/Main.hs
--- a/source/test-suite/Main.hs
+++ b/source/test-suite/Main.hs
@@ -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
