packages feed

o-clock 1.2.1.1 → 1.4.0.1

raw patch · 6 files changed

Files

CHANGELOG.md view
@@ -9,6 +9,32 @@ o'clock uses [PVP Versioning][1]. The change log is available [on GitHub][2]. +1.4.0.1+=======+* [#145](https://github.com/serokell/o-clock/pull/145)+  + Bump some upper bounds.+  + Get rid of warnings with GHC-9.12.++1.4.0+=====++* [#136](https://github.com/serokell/o-clock/pull/136)+  + Remove `toNum`.+* [#139](https://github.com/serokell/o-clock/pull/139)+  + Add `Data` instance to `Time`.+* [#140](https://github.com/serokell/o-clock/pull/140)+  + Increase some upper bounds.++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 ===== 
o-clock.cabal view
@@ -4,7 +4,7 @@ -- SPDX-License-Identifier: MPL-2.0  name:                o-clock-version:             1.2.1.1+version:             1.4.0.1 synopsis:            Type-safe time library. description:         See README.md for details. homepage:            https://github.com/serokell/o-clock@@ -20,11 +20,13 @@ extra-doc-files:     CHANGELOG.md                    , README.md                    , README.lhs-tested-with:         GHC == 8.6.5-                   , GHC == 8.8.3-                   , GHC == 8.10.4-                   , GHC == 9.0.1-                   , GHC == 9.2.1+tested-with:         GHC == 9.0.2+                   , GHC == 9.2.8+                   , GHC == 9.4.8+                   , GHC == 9.6.6+                   , GHC == 9.8.4+                   , GHC == 9.10.1+                   , GHC == 9.12.1  source-repository head   type:     git@@ -32,7 +34,7 @@  common common-options   build-depends:-      base >=4.12 && <4.17+      base >=4.12 && <5   ghc-options: -Wall   default-language: Haskell2010 @@ -50,7 +52,7 @@                        TypeApplications                        TypeFamilies   if flag(aeson)-    build-depends:     aeson    >= 1.2.4 && < 2.1+    build-depends:     aeson    >= 1.2.4 && < 2.3                      , text     cpp-options:       -DHAS_aeson @@ -74,10 +76,10 @@                        Test.Time.Units    build-depends:       o-clock-                     , hedgehog       >= 0.6 && < 1.2+                     , hedgehog       >= 0.6 && < 1.6                      , hspec-expectations ^>= 0.8-                     , tasty          >= 0.12 && < 1.5-                     , tasty-hedgehog >= 0.1 && < 1.2+                     , tasty          >= 0.12 && < 1.6+                     , tasty-hedgehog >= 0.1 && < 1.5.0                      , tasty-hunit-compat ^>= 0.2                      , type-spec      >= 0.3.0.1 && < 0.5 @@ -95,7 +97,7 @@   main-is:             Doctest.hs    build-tool-depends:  doctest:doctest-  build-depends:       doctest >= 0.16 && < 0.21+  build-depends:       doctest >= 0.16 && < 0.24                      , Glob    >= 0.9 && < 0.11   ghc-options:         -threaded -rtsopts -with-rtsopts=-N @@ -109,8 +111,8 @@    build-tool-depends:  markdown-unlit:markdown-unlit   build-depends:       o-clock-                     , markdown-unlit ^>= 0.5-  ghc-options:         -threaded -rtsopts -with-rtsopts=-N -pgmL markdown-unlit+                     , markdown-unlit >= 0.5 && < 0.7+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N -pgmL markdown-unlit -Wno-orphans  benchmark o-clock-benchmark   import:              common-options
src/Time/Rational.hs view
@@ -1,18 +1,28 @@--- SPDX-FileCopyrightText: 2019 Serokell <https://serokell.io>+-- SPDX-FileCopyrightText: 2019-2023 Serokell <https://serokell.io> -- -- SPDX-License-Identifier: MPL-2.0  {-# LANGUAGE AllowAmbiguousTypes  #-} {-# LANGUAGE CPP                  #-} {-# LANGUAGE ConstraintKinds      #-}+{-# LANGUAGE DataKinds            #-} {-# LANGUAGE FlexibleContexts     #-} {-# LANGUAGE FlexibleInstances    #-} {-# LANGUAGE NoStarIsType         #-}+{-# LANGUAGE PolyKinds            #-} {-# LANGUAGE Rank2Types           #-}-{-# LANGUAGE TypeInType           #-} {-# LANGUAGE TypeOperators        #-} {-# LANGUAGE UndecidableInstances #-} +-- See https://github.com/ghc/ghc/commit/13d627bbd0bc3dd30d672de341aa7f471be0aa2c+-- Starting from 9.6, GHC doesn't print promotion ticks when they are not necessary.+-- Because of that we need to support too many cases in doctests.+-- Let's force redundant ticks for now and remove this flag later when we stop+-- supporting 9.0 at least.+#if ( __GLASGOW_HASKELL__ >= 906 )+{-# OPTIONS_GHC -fprint-redundant-promotion-ticks #-}+#endif+ -- | This module introduces 'Rat' kind and all necessary functional.  module Time.Rational@@ -43,6 +53,11 @@ import GHC.TypeNats (Div, KnownNat, Mod, Nat, natVal, type (<=?)) import qualified GHC.TypeNats import Unsafe.Coerce (unsafeCoerce)++#if ( __GLASGOW_HASKELL__ >= 906 )+-- $setup+-- >>> {-# OPTIONS_GHC -fprint-redundant-promotion-ticks #-}+#endif  -- | Data structure represents the rational number. -- Rational number can be represented as a pair of
src/Time/Timestamp.hs view
@@ -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)
src/Time/Units.hs view
@@ -3,9 +3,10 @@ -- SPDX-License-Identifier: MPL-2.0  {-# LANGUAGE AllowAmbiguousTypes        #-}-{-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE CPP                        #-}+{-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DataKinds                  #-}+{-# LANGUAGE DeriveDataTypeable         #-} {-# LANGUAGE DeriveGeneric              #-} {-# LANGUAGE ExplicitForAll             #-} {-# LANGUAGE FlexibleContexts           #-}@@ -43,7 +44,9 @@        , time        , floorUnit        , floorRat-       , toNum+       , ceilingUnit+       , ceilingRat+       , toFractional         , sec        , ms@@ -68,7 +71,10 @@ import Control.Monad.IO.Class (MonadIO, liftIO) import Data.Char (isDigit, isLetter) import Data.Coerce (coerce)+import Data.Data (Data)+#if !(MIN_VERSION_base(4,20,0)) import Data.Foldable (foldl')+#endif import Data.Proxy (Proxy (..)) import Data.Semigroup (Semigroup (..)) import GHC.Generics (Generic)@@ -80,12 +86,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@@ -113,7 +119,7 @@  -- | Time unit is represented as type level rational multiplier with kind 'Rat'. newtype Time (rat :: Rat) = Time { unTime :: RatioNat }-    deriving (Eq, Ord, Enum, Generic)+    deriving (Eq, Ord, Enum, Generic, Data)  -- | Addition is associative binary operation for 'Semigroup' of 'Time'. instance Semigroup (Time (rat :: Rat)) where@@ -300,7 +306,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,36 +324,42 @@ floorUnit :: forall (unit :: Rat) . Time unit -> Time unit floorUnit = time . fromIntegral @Natural . floorRat -{- | Convert time to the 'Num' in given units.+-- | 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 -For example, instead of writing+{- | Similar to 'ceiling', but works with 'Time' units. -@-foo :: POSIXTime-foo = 10800  -- 3 hours-@+>>> ceilingUnit @Day (Time $ 5 % 2)+3d -one can write more safe implementation:+>>> ceilingUnit (Time @Second $ 2 % 3)+1s -@-foo = toNum @Second $ hour 3-@+>>> ceilingUnit $ ps 42+42ps -__Examples:__+@since 1.3.0+-}+ceilingUnit :: forall (unit :: Rat) . Time unit -> Time unit+ceilingUnit = time . fromIntegral @Natural . ceilingRat ->>> toNum @Second @Natural $ hour 3-10800+{- | Convert the 'Time' object to the 'Fractional' value. ->>> toNum @Minute @Int $ hour 3-180+__Examples:__ ->>> toNum @Hour @Natural $ hour 3-3+>>> toFractional @Rational $ hour (1 % 8)+1 % 8 +>>> toFractional @Double $ hour (1 % 8)+0.125++@since 1.3.0 -}-toNum :: forall (unitTo :: Rat) n (unit :: Rat) . (KnownDivRat unit unitTo, Num n)-      => Time unit -> n-toNum = fromIntegral @Natural . floorRat . toUnit @unitTo+toFractional :: forall r (unit :: Rat) . Fractional r => Time unit -> r+toFractional = fromRational . toRational . unTime  ---------------------------------------------------------------------------- -- Functional
test/Test/Time/Units.hs view
@@ -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" $