    {-# LANGUAGE PatternGuards #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# OPTIONS_GHC -fno-warn-type-defaults #-}

    -- | Formatters for high-res, real-time and timer clock values from "System.Clock".

    module Formatting.Clock (timeSpecs) where

    import Data.Text.Lazy.Builder
    import Formatting
    import Formatting.Internal
    import System.Clock

    fmt :: Integer -> Builder
    fmt :: Integer -> Builder
    fmt Integer
    diff
      | Just Double
    i <- Integer -> Maybe Double
    scale ((Integer
    10 Integer -> Integer -> Integer
    forall a b. (Num a, Integral b) => a -> b -> a
    ^ Integer
    9) Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    60 Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    60 Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    24) = Format Builder (Double -> Builder) -> Double -> Builder
    forall a. Format Builder a -> a
    bprint (Int -> Format Builder (Double -> Builder)
    forall a r. Real a => Int -> Format r (a -> r)
    fixed Int
    2 Format Builder (Double -> Builder)
    -> Format Builder Builder -> Format Builder (Double -> Builder)
    forall r a r'. Format r a -> Format r' r -> Format r' a
    % Format Builder Builder
    " d") Double
    i
      | Just Double
    i <- Integer -> Maybe Double
    scale ((Integer
    10 Integer -> Integer -> Integer
    forall a b. (Num a, Integral b) => a -> b -> a
    ^ Integer
    9) Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    60 Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    60) = Format Builder (Double -> Builder) -> Double -> Builder
    forall a. Format Builder a -> a
    bprint (Int -> Format Builder (Double -> Builder)
    forall a r. Real a => Int -> Format r (a -> r)
    fixed Int
    2 Format Builder (Double -> Builder)
    -> Format Builder Builder -> Format Builder (Double -> Builder)
    forall r a r'. Format r a -> Format r' r -> Format r' a
    % Format Builder Builder
    " h") Double
    i
      | Just Double
    i <- Integer -> Maybe Double
    scale ((Integer
    10 Integer -> Integer -> Integer
    forall a b. (Num a, Integral b) => a -> b -> a
    ^ Integer
    9) Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    60) = Format Builder (Double -> Builder) -> Double -> Builder
    forall a. Format Builder a -> a
    bprint (Int -> Format Builder (Double -> Builder)
    forall a r. Real a => Int -> Format r (a -> r)
    fixed Int
    2 Format Builder (Double -> Builder)
    -> Format Builder Builder -> Format Builder (Double -> Builder)
    forall r a r'. Format r a -> Format r' r -> Format r' a
    % Format Builder Builder
    " m") Double
    i
      | Just Double
    i <- Integer -> Maybe Double
    scale (Integer
    10 Integer -> Integer -> Integer
    forall a b. (Num a, Integral b) => a -> b -> a
    ^ Integer
    9) = Format Builder (Double -> Builder) -> Double -> Builder
    forall a. Format Builder a -> a
    bprint (Int -> Format Builder (Double -> Builder)
    forall a r. Real a => Int -> Format r (a -> r)
    fixed Int
    2 Format Builder (Double -> Builder)
    -> Format Builder Builder -> Format Builder (Double -> Builder)
    forall r a r'. Format r a -> Format r' r -> Format r' a
    % Format Builder Builder
    " s") Double
    i
      | Just Double
    i <- Integer -> Maybe Double
    scale (Integer
    10 Integer -> Integer -> Integer
    forall a b. (Num a, Integral b) => a -> b -> a
    ^ Integer
    6) = Format Builder (Double -> Builder) -> Double -> Builder
    forall a. Format Builder a -> a
    bprint (Int -> Format Builder (Double -> Builder)
    forall a r. Real a => Int -> Format r (a -> r)
    fixed Int
    2 Format Builder (Double -> Builder)
    -> Format Builder Builder -> Format Builder (Double -> Builder)
    forall r a r'. Format r a -> Format r' r -> Format r' a
    % Format Builder Builder
    " ms") Double
    i
      | Just Double
    i <- Integer -> Maybe Double
    scale (Integer
    10 Integer -> Integer -> Integer
    forall a b. (Num a, Integral b) => a -> b -> a
    ^ Integer
    3) = Format Builder (Double -> Builder) -> Double -> Builder
    forall a. Format Builder a -> a
    bprint (Int -> Format Builder (Double -> Builder)
    forall a r. Real a => Int -> Format r (a -> r)
    fixed Int
    2 Format Builder (Double -> Builder)
    -> Format Builder Builder -> Format Builder (Double -> Builder)
    forall r a r'. Format r a -> Format r' r -> Format r' a
    % Format Builder Builder
    " us") Double
    i
      | Bool
    otherwise = Format Builder (Integer -> Builder) -> Integer -> Builder
    forall a. Format Builder a -> a
    bprint (Format Builder (Integer -> Builder)
    forall a r. Integral a => Format r (a -> r)
    int Format Builder (Integer -> Builder)
    -> Format Builder Builder -> Format Builder (Integer -> Builder)
    forall r a r'. Format r a -> Format r' r -> Format r' a
    % Format Builder Builder
    " ns") Integer
    diff
      where
        scale :: Integer -> Maybe Double
        scale :: Integer -> Maybe Double
    scale Integer
    i =
          if Integer
    diff Integer -> Integer -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Integer
    i
            then Double -> Maybe Double
    forall a. a -> Maybe a
    Just (Integer -> Double
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Integer
    diff Double -> Double -> Double
    forall a. Fractional a => a -> a -> a
    / Integer -> Double
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Integer
    i)
            else Maybe Double
    forall a. Maybe a
    Nothing

    -- | Same as @durationNS@ but works on `TimeSpec` from the clock package.
    timeSpecs :: Format r (TimeSpec -> TimeSpec -> r)
    timeSpecs :: forall r. Format r (TimeSpec -> TimeSpec -> r)
    timeSpecs = ((Builder -> r) -> TimeSpec -> TimeSpec -> r)
    -> Format r (TimeSpec -> TimeSpec -> r)
    forall r a. ((Builder -> r) -> a) -> Format r a
    Format (\Builder -> r
    g TimeSpec
    x TimeSpec
    y -> Builder -> r
    g (TimeSpec -> TimeSpec -> Builder
    fmt0 TimeSpec
    x TimeSpec
    y))
      where
        fmt0 :: TimeSpec -> TimeSpec -> Builder
    fmt0 (TimeSpec Int64
    s1 Int64
    n1) (TimeSpec Int64
    s2 Int64
    n2) = Integer -> Builder
    fmt Integer
    diff
          where
            diff :: Integer
            diff :: Integer
    diff = Integer
    a2 Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    - Integer
    a1
            a1 :: Integer
    a1 = (Int64 -> Integer
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int64
    s1 Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    10 Integer -> Integer -> Integer
    forall a b. (Num a, Integral b) => a -> b -> a
    ^ Integer
    9) Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    + Int64 -> Integer
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int64
    n1
            a2 :: Integer
    a2 = (Int64 -> Integer
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int64
    s2 Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    10 Integer -> Integer -> Integer
    forall a b. (Num a, Integral b) => a -> b -> a
    ^ Integer
    9) Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    + Int64 -> Integer
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int64
    n2