diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2025, Nikita Volkov
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/library/TextBuilderTime/Iso8601.hs b/library/TextBuilderTime/Iso8601.hs
new file mode 100644
--- /dev/null
+++ b/library/TextBuilderTime/Iso8601.hs
@@ -0,0 +1,93 @@
+module TextBuilderTime.Iso8601
+  ( day,
+    utcTime,
+  )
+where
+
+import Data.Time
+import TextBuilder
+import Prelude
+
+-- |
+-- Convert 'Day' to ISO-8601 format.
+--
+-- >>> day (fromGregorian 2022 6 16)
+-- "2022-06-16"
+{-# INLINE day #-}
+day :: Day -> TextBuilder
+day (toGregorian -> (year, month, day)) =
+  mconcat
+    [ fixedLengthDecimal 4 year,
+      "-",
+      fixedLengthDecimal 2 month,
+      "-",
+      fixedLengthDecimal 2 day
+    ]
+
+-- |
+-- Convert 'UTCTime' to ISO-8601 format.
+--
+-- >>> utcTime (UTCTime (fromGregorian 2022 6 16) 0)
+-- "2022-06-16T00:00:00Z"
+--
+-- >>> utcTime (UTCTime (fromGregorian 2022 6 16) 0.000001)
+-- "2022-06-16T00:00:00.000001Z"
+--
+-- >>> utcTime (UTCTime (fromGregorian 2022 6 16) 0.000000001)
+-- "2022-06-16T00:00:00.000000001Z"
+--
+-- >>> utcTime (UTCTime (fromGregorian 2022 6 16) (3 * 60 * 60 + 4 * 60 + 5))
+-- "2022-06-16T03:04:05Z"
+{-# INLINE utcTime #-}
+utcTime :: UTCTime -> TextBuilder
+utcTime UTCTime {..} =
+  let picoseconds = diffTimeToPicoseconds utctDayTime
+      (seconds, picosecond) = divMod picoseconds 1_000_000_000_000
+      seconds' = fromInteger seconds :: Int
+      (dayMinutes, second) = divMod seconds' 60
+      (hour, minute) = divMod dayMinutes 60
+   in mconcat
+        [ day utctDay,
+          "T",
+          fixedLengthDecimal 2 hour,
+          ":",
+          fixedLengthDecimal 2 minute,
+          ":",
+          fixedLengthDecimal 2 second,
+          picosecondsSubsecondsComponent (fromIntegral picosecond),
+          "Z"
+        ]
+
+-- |
+-- Subseconds component of the ISO-8601 format compiled from picoseconds.
+--
+-- >>> picosecondsSubsecondsComponent 000_000_000_001
+-- ".000000000001"
+--
+-- >>> picosecondsSubsecondsComponent 000_000_000_010
+-- ".00000000001"
+--
+-- >>> picosecondsSubsecondsComponent 100_000_000_000
+-- ".1"
+--
+-- >>> picosecondsSubsecondsComponent 0
+-- ""
+{-# INLINE picosecondsSubsecondsComponent #-}
+picosecondsSubsecondsComponent ::
+  -- | Picoseconds.
+  Int ->
+  TextBuilder
+picosecondsSubsecondsComponent =
+  skipTrail 12
+  where
+    skipTrail pos val =
+      if val == 0
+        then
+          mempty
+        else case divMod val 10 of
+          (quotient, remainder) ->
+            if remainder == 0
+              then
+                skipTrail (pred pos) quotient
+              else
+                "." <> fixedLengthDecimal pos val
diff --git a/text-builder-time.cabal b/text-builder-time.cabal
new file mode 100644
--- /dev/null
+++ b/text-builder-time.cabal
@@ -0,0 +1,77 @@
+cabal-version: 3.0
+name: text-builder-time
+version: 0.1
+category: Text, Builders, Time
+synopsis: Various formats for "time" in terms of "text-builder"
+description:
+  Part of the "text-builder" ecosystem, providing rendering to various formats for the types of the "time" library.
+  Currently it only provides support for ISO-8601.
+  Other formats are to be added later.
+
+homepage: https://github.com/nikita-volkov/text-builder-time
+bug-reports: https://github.com/nikita-volkov/text-builder-time/issues
+author: Nikita Volkov <nikita.y.volkov@mail.ru>
+maintainer: Nikita Volkov <nikita.y.volkov@mail.ru>
+copyright: (c) 2025, Nikita Volkov
+license: MIT
+license-file: LICENSE
+
+source-repository head
+  type: git
+  location: https://github.com/nikita-volkov/text-builder-time
+
+common base
+  default-language: Haskell2010
+  default-extensions:
+    BangPatterns
+    BlockArguments
+    ConstraintKinds
+    DataKinds
+    DefaultSignatures
+    DeriveDataTypeable
+    DeriveFoldable
+    DeriveFunctor
+    DeriveGeneric
+    DeriveTraversable
+    DerivingStrategies
+    EmptyDataDecls
+    FlexibleContexts
+    FlexibleInstances
+    FunctionalDependencies
+    GADTs
+    GeneralizedNewtypeDeriving
+    LambdaCase
+    LiberalTypeSynonyms
+    MagicHash
+    MultiParamTypeClasses
+    MultiWayIf
+    NoImplicitPrelude
+    NoMonomorphismRestriction
+    NumericUnderscores
+    OverloadedStrings
+    ParallelListComp
+    PatternGuards
+    QuasiQuotes
+    RankNTypes
+    RecordWildCards
+    ScopedTypeVariables
+    StandaloneDeriving
+    StrictData
+    TemplateHaskell
+    TupleSections
+    TypeApplications
+    TypeFamilies
+    TypeOperators
+    UnboxedTuples
+    ViewPatterns
+
+library
+  import: base
+  hs-source-dirs: library
+  exposed-modules:
+    TextBuilderTime.Iso8601
+
+  build-depends:
+    base >=4.11 && <5,
+    text-builder ^>=1.0.0.1,
+    time >=1.12 && <2,
