diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,19 @@
 o'clock uses [PVP Versioning][1].
 The change log is available [on GitHub][2].
 
+Unreleased
+=====
+
+1.3.0
+=====
+
+* [#129](https://github.com/serokell/o-clock/pull/129)
+  + Deprecate `toNum`: may cause accidental flooring.
+  + Add the `toFractional` function to avoid the accidental flooring.
+  + Change the order of the type variables in the definition of `floorRat` so that the target type comes first.
+* [#131](https://github.com/serokell/o-clock/pull/131)
+  + Add `ceilingRat` and `ceilingUnit`.
+
 1.2.1.1
 =====
 
diff --git a/o-clock.cabal b/o-clock.cabal
--- a/o-clock.cabal
+++ b/o-clock.cabal
@@ -4,7 +4,7 @@
 -- SPDX-License-Identifier: MPL-2.0
 
 name:                o-clock
-version:             1.2.1.1
+version:             1.3.0
 synopsis:            Type-safe time library.
 description:         See README.md for details.
 homepage:            https://github.com/serokell/o-clock
@@ -23,8 +23,8 @@
 tested-with:         GHC == 8.6.5
                    , GHC == 8.8.3
                    , GHC == 8.10.4
-                   , GHC == 9.0.1
-                   , GHC == 9.2.1
+                   , GHC == 9.0.2
+                   , GHC == 9.2.4
 
 source-repository head
   type:     git
@@ -32,7 +32,7 @@
 
 common common-options
   build-depends:
-      base >=4.12 && <4.17
+      base >=4.12 && <5
   ghc-options: -Wall
   default-language: Haskell2010
 
@@ -74,10 +74,10 @@
                        Test.Time.Units
 
   build-depends:       o-clock
-                     , hedgehog       >= 0.6 && < 1.2
+                     , hedgehog       >= 0.6 && < 1.3
                      , hspec-expectations ^>= 0.8
                      , tasty          >= 0.12 && < 1.5
-                     , tasty-hedgehog >= 0.1 && < 1.2
+                     , tasty-hedgehog >= 0.1 && < 1.3.2
                      , tasty-hunit-compat ^>= 0.2
                      , type-spec      >= 0.3.0.1 && < 0.5
 
diff --git a/src/Time/Timestamp.hs b/src/Time/Timestamp.hs
--- a/src/Time/Timestamp.hs
+++ b/src/Time/Timestamp.hs
@@ -82,9 +82,9 @@
         -> Timestamp
 timeAdd t (Timestamp ts) = Timestamp (toRational (unTime $ toUnit @Second t) + ts)
 
--- | Returns the result of multiplication of two 'Time' elements.
-timeMul :: forall (unit :: Rat) . KnownRat unit
-        => RatioNat
+-- | Returns the result of multiplying a number by a 'Time' element.
+timeMul :: forall (unit :: Rat) .
+           RatioNat
         -> Time unit
         -> Time unit
 timeMul n (Time t) = Time (n * t)
diff --git a/src/Time/Units.hs b/src/Time/Units.hs
--- a/src/Time/Units.hs
+++ b/src/Time/Units.hs
@@ -3,8 +3,8 @@
 -- SPDX-License-Identifier: MPL-2.0
 
 {-# LANGUAGE AllowAmbiguousTypes        #-}
-{-# LANGUAGE ConstraintKinds            #-}
 {-# LANGUAGE CPP                        #-}
+{-# LANGUAGE ConstraintKinds            #-}
 {-# LANGUAGE DataKinds                  #-}
 {-# LANGUAGE DeriveGeneric              #-}
 {-# LANGUAGE ExplicitForAll             #-}
@@ -43,7 +43,10 @@
        , time
        , floorUnit
        , floorRat
+       , ceilingUnit
+       , ceilingRat
        , toNum
+       , toFractional
 
        , sec
        , ms
@@ -80,12 +83,12 @@
 import Text.ParserCombinators.ReadPrec (ReadPrec, lift)
 
 #ifdef HAS_aeson
-import Data.Aeson (ToJSON (..), FromJSON (..), withText)
-import Text.Read (readMaybe)
+import Data.Aeson (FromJSON (..), ToJSON (..), withText)
 import qualified Data.Text as Text
+import Text.Read (readMaybe)
 #endif
 
-import Time.Rational (type (*), type (/), type (:%), KnownDivRat, Rat, RatioNat, KnownRat, ratVal)
+import Time.Rational (KnownDivRat, KnownRat, Rat, RatioNat, ratVal, type (*), type (/), type (:%))
 
 import qualified Control.Concurrent as Concurrent
 import qualified System.CPUTime as CPUTime
@@ -300,7 +303,7 @@
 {-# INLINE fortnight #-}
 
 -- | Returns the greatest integer not greater than given 'Time'.
-floorRat :: forall (unit :: Rat) b . (Integral b) => Time unit -> b
+floorRat :: forall b (unit :: Rat) . Integral b => Time unit -> b
 floorRat = floor . unTime
 
 {- | Similar to 'floor', but works with 'Time' units.
@@ -318,6 +321,28 @@
 floorUnit :: forall (unit :: Rat) . Time unit -> Time unit
 floorUnit = time . fromIntegral @Natural . floorRat
 
+-- | Returns the smallest integer greater than or equal to the given 'Time'.
+--
+-- @since 1.3.0
+ceilingRat :: forall b (unit :: Rat) . (Integral b) => Time unit -> b
+ceilingRat = ceiling . unTime
+
+{- | Similar to 'ceiling', but works with 'Time' units.
+
+>>> ceilingUnit @Day (Time $ 5 % 2)
+3d
+
+>>> ceilingUnit (Time @Second $ 2 % 3)
+1s
+
+>>> ceilingUnit $ ps 42
+42ps
+
+@since 1.3.0
+-}
+ceilingUnit :: forall (unit :: Rat) . Time unit -> Time unit
+ceilingUnit = time . fromIntegral @Natural . ceilingRat
+
 {- | Convert time to the 'Num' in given units.
 
 For example, instead of writing
@@ -348,6 +373,25 @@
 toNum :: forall (unitTo :: Rat) n (unit :: Rat) . (KnownDivRat unit unitTo, Num n)
       => Time unit -> n
 toNum = fromIntegral @Natural . floorRat . toUnit @unitTo
+{-# DEPRECATED toNum
+  [ "May lead to unexpected flooring of the fractional time."
+  , "Use 'toFractional' to avoid rounding or 'floorRat' to keep the flooring behaviour."
+  ] #-}
+
+{- | Convert the 'Time' object to the 'Fractional' value.
+
+__Examples:__
+
+>>> toFractional @Rational $ hour (1 % 8)
+1 % 8
+
+>>> toFractional @Double $ hour (1 % 8)
+0.125
+
+@since 1.3.0
+-}
+toFractional :: forall r (unit :: Rat) . Fractional r => Time unit -> r
+toFractional = fromRational . toRational . unTime
 
 ----------------------------------------------------------------------------
 -- Functional
diff --git a/test/Test/Time/Units.hs b/test/Test/Time/Units.hs
--- a/test/Test/Time/Units.hs
+++ b/test/Test/Time/Units.hs
@@ -12,14 +12,16 @@
        ) where
 
 import Control.Exception (evaluate)
-import GHC.Real (Ratio ((:%)))
+import GHC.Real (Ratio ((:%)), (%))
 import Test.Hspec.Expectations (anyException, shouldBe, shouldThrow)
 import Test.Tasty (TestTree, testGroup)
 import Test.Tasty.HUnit (testCase)
 
-import Time (Day, Hour, Millisecond, Minute, Second, Time (..), Week, day, floorUnit, fortnight,
-             hour, mcs, minute, ms, ns, ps, sec, seriesF, toUnit, unitsF, week, (+:+))
 
+import Time (Day, Hour, Millisecond, Minute, Second, Time (..), Week, day, floorUnit, ceilingUnit,
+             fortnight, hour, mcs, minute, ms, ns, ps, sec, seriesF, toUnit, toFractional, unitsF,
+             week, (+:+))
+
 unitsTestTree :: TestTree
 unitsTestTree = testGroup "Units" unitsTests
 
@@ -74,6 +76,20 @@
             floorUnit (Time $ 5 :% 2) `shouldBe` day 2
         , testCase "returns 42ps when floor integer" $
             floorUnit (ps 42) `shouldBe` ps 42
+        ]
+    , testGroup "Ceiling tests"
+        [ testCase "returns 1s, given 2/3 seconds" $
+            ceilingUnit (Time @Second $ 2 :% 3) `shouldBe` sec 1
+        , testCase "returns 3d, given 2+1/2 days" $
+            ceilingUnit (Time $ 5 :% 2) `shouldBe` day 3
+        , testCase "returns 42ps, given exactly 42 picoseconds" $
+            ceilingUnit (ps 42) `shouldBe` ps 42
+        ]
+    , testGroup "Conversion to Fractional values"
+        [ testCase "The 'Rational' representation of (hour $ 1 % 8) should be equal to 1 % 8" $
+            toFractional @Rational (hour (1 % 8)) `shouldBe` 1 % 8
+        , testCase "The 'Double' representation of (hour $ 1 % 8) should be equal to 0.125" $
+            toFractional @Double (hour (1 % 8)) `shouldBe` 0.125
         ]
     , testGroup "Formatting tests"
         [ testCase "4000 minutes should be formatted without ending-zeros" $
