packages feed

fmt 0.2.0.0 → 0.3.0.0

raw patch · 5 files changed

+633/−31 lines, 5 filesdep +timedep +time-locale-compatPVP ok

version bump matches the API change (PVP)

Dependencies added: time, time-locale-compat

API changes (from Hackage documentation)

+ Fmt.Internal: fixedF :: Real a => Int -> a -> Builder
+ Fmt.Internal: ordinalF :: (Buildable a, Integral a) => a -> Builder
+ Fmt.Time: centuryF :: FormatTime a => a -> Builder
+ Fmt.Time: dateDashF :: FormatTime a => a -> Builder
+ Fmt.Time: dateSlashF :: FormatTime a => a -> Builder
+ Fmt.Time: dateSlashLF :: FormatTime a => a -> Builder
+ Fmt.Time: dateTimeF :: FormatTime a => a -> Builder
+ Fmt.Time: dayF :: FormatTime a => a -> Builder
+ Fmt.Time: dayHalfF :: FormatTime a => a -> Builder
+ Fmt.Time: dayHalfUF :: FormatTime a => a -> Builder
+ Fmt.Time: dayNameF :: FormatTime a => a -> Builder
+ Fmt.Time: dayNameShortF :: FormatTime a => a -> Builder
+ Fmt.Time: dayOfMonthF :: FormatTime a => a -> Builder
+ Fmt.Time: dayOfMonthOrdF :: FormatTime a => a -> Builder
+ Fmt.Time: dayOfMonthSF :: FormatTime a => a -> Builder
+ Fmt.Time: dayOfWeekF :: FormatTime a => a -> Builder
+ Fmt.Time: dayOfWeekFromZeroF :: FormatTime a => a -> Builder
+ Fmt.Time: daysF :: RealFrac n => Int -> n -> Builder
+ Fmt.Time: diffF :: forall n. RealFrac n => Bool -> n -> Builder
+ Fmt.Time: epochF :: FormatTime a => a -> Builder
+ Fmt.Time: hmF :: FormatTime a => a -> Builder
+ Fmt.Time: hmsF :: FormatTime a => a -> Builder
+ Fmt.Time: hmsLF :: FormatTime a => a -> Builder
+ Fmt.Time: hmsPLF :: FormatTime a => a -> Builder
+ Fmt.Time: hour12F :: FormatTime a => a -> Builder
+ Fmt.Time: hour12SF :: FormatTime a => a -> Builder
+ Fmt.Time: hour24F :: FormatTime a => a -> Builder
+ Fmt.Time: hour24SF :: FormatTime a => a -> Builder
+ Fmt.Time: hoursF :: RealFrac n => Int -> n -> Builder
+ Fmt.Time: minuteF :: FormatTime a => a -> Builder
+ Fmt.Time: minutesF :: RealFrac n => Int -> n -> Builder
+ Fmt.Time: monthF :: FormatTime a => a -> Builder
+ Fmt.Time: monthNameF :: FormatTime a => a -> Builder
+ Fmt.Time: monthNameShortF :: FormatTime a => a -> Builder
+ Fmt.Time: picosecondF :: FormatTime a => a -> Builder
+ Fmt.Time: secondF :: FormatTime a => a -> Builder
+ Fmt.Time: secondsF :: RealFrac n => Int -> n -> Builder
+ Fmt.Time: subsecondF :: FormatTime a => a -> Builder
+ Fmt.Time: timeF :: FormatTime a => Text -> a -> Builder
+ Fmt.Time: tzF :: FormatTime a => a -> Builder
+ Fmt.Time: tzNameF :: FormatTime a => a -> Builder
+ Fmt.Time: weekCenturyF :: FormatTime a => a -> Builder
+ Fmt.Time: weekF :: FormatTime a => a -> Builder
+ Fmt.Time: weekFromZeroF :: FormatTime a => a -> Builder
+ Fmt.Time: weekOfYearMonF :: FormatTime a => a -> Builder
+ Fmt.Time: weekYYF :: FormatTime a => a -> Builder
+ Fmt.Time: weekYearF :: FormatTime a => a -> Builder
+ Fmt.Time: yearF :: FormatTime a => a -> Builder
+ Fmt.Time: yearsF :: RealFrac n => Int -> n -> Builder
+ Fmt.Time: yyF :: FormatTime a => a -> Builder

Files

CHANGELOG.md view
@@ -1,3 +1,7 @@+# 0.3.0.0++* Added time formatters (see `Fmt.Time`).+ # 0.2.0.0  * Changed `format` and `formatLn` to be polyvariadic.
fmt.cabal view
@@ -1,5 +1,5 @@ name:                fmt-version:             0.2.0.0+version:             0.3.0.0 synopsis:            A new formatting library description:   A new formatting library that tries to be simple to understand while still@@ -41,7 +41,8 @@ bug-reports:         http://github.com/aelve/fmt/issues license:             BSD3 license-file:        LICENSE-author:              Artyom+author:              Artyom Kazak <yom@artyom.me>,+                     Dmitry Kovanikov <kovanikov@gmail.com> maintainer:          yom@artyom.me -- copyright: category:            Text@@ -57,6 +58,7 @@ library   exposed-modules:     Fmt                        Fmt.Internal+                       Fmt.Time   build-depends:       base >=4.6 && <5,                        base16-bytestring,                        base64-bytestring,@@ -64,8 +66,12 @@                        containers,                        microlens >= 0.3,                        text,-                       text-format >= 0.3+                       text-format >= 0.3,+                       time,+                       time-locale-compat   ghc-options:         -Wall -fno-warn-unused-do-bind+  if impl(ghc > 8.0)+    ghc-options:       -Wno-redundant-constraints   hs-source-dirs:      lib   default-language:    Haskell2010 
lib/Fmt.hs view
@@ -85,6 +85,9 @@   indent, indent',   nameF, +  -- ** Time+  module Fmt.Time,+   -- ** Lists   listF, listF',   blockListF, blockListF',@@ -178,6 +181,7 @@ #endif  import Fmt.Internal+import Fmt.Time   {- $overloadedstrings@@ -965,25 +969,6 @@   fromLazyText . TL.center (fromIntegral i) c . toLazyText . build  {- |-Add an ordinal suffix to a number:-->>> ordinalF 15-"15th"->>> ordinalF 22-"22nd"--}-ordinalF :: (Buildable a, Integral a) => a -> Builder-ordinalF n-  | tens > 3 && tens < 21 = build n <> "th"-  | otherwise = build n <> case n `mod` 10 of-                             1 -> "st"-                             2 -> "nd"-                             3 -> "rd"-                             _ -> "th"-  where-    tens = n `mod` 100--{- | Break digits in a number:  >>> commaizeF 15830000@@ -1067,15 +1052,6 @@ -} precF :: Real a => Int -> a -> Builder precF = TF.prec--{- |-Format a floating-point number without scientific notation:-->>> listF' (fixedF 5) [pi,0.1,10]-"[3.14159, 0.10000, 10.00000]"--}-fixedF :: Real a => Int -> a -> Builder-fixedF = TF.fixed  ---------------------------------------------------------------------------- -- Conditional formatters
lib/Fmt/Internal.hs view
@@ -18,6 +18,9 @@  {- | A module providing access to internals (in case you really need them). Can change at any time, though probably won't.++It also provides some functions that are used in 'Fmt.Time' (so that+'Fmt.Time' wouldn't need to import 'Fmt'). -} module Fmt.Internal (@@ -41,6 +44,10 @@   showSigned',   intToDigit',   indent',++  -- * Functions used in 'Fmt.Time'+  fixedF,+  ordinalF, ) where @@ -257,3 +264,35 @@             TL.unlines $ (TL.fromStrict pref <> x) : map (spaces <>) xs   where     spaces = TL.replicate (fromIntegral n) (TL.singleton ' ')++----------------------------------------------------------------------------+-- Functions used in Fmt.Time+----------------------------------------------------------------------------++{- |+Format a floating-point number without scientific notation:++>>> listF' (fixedF 5) [pi,0.1,10]+"[3.14159, 0.10000, 10.00000]"+-}+fixedF :: Real a => Int -> a -> Builder+fixedF = TF.fixed++{- |+Add an ordinal suffix to a number:++>>> ordinalF 15+"15th"+>>> ordinalF 22+"22nd"+-}+ordinalF :: (Buildable a, Integral a) => a -> Builder+ordinalF n+  | tens > 3 && tens < 21 = build n <> "th"+  | otherwise = build n <> case n `mod` 10 of+                             1 -> "st"+                             2 -> "nd"+                             3 -> "rd"+                             _ -> "th"+  where+    tens = n `mod` 100
+ lib/Fmt/Time.hs view
@@ -0,0 +1,577 @@+{- Acknowledgements+~~~~~~~~~~~~~~~~~~~++This module has been largely copied off+    <https://hackage.haskell.org/package/formatting/docs/Formatting-Time.html>+Written by Chris Done+    <https://github.com/chrisdone>+-}++{-# LANGUAGE CPP                 #-}+{-# LANGUAGE ExplicitForAll      #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-}+++{- | Formatters for various time types. This module copies the structure of+@<https://hackage.haskell.org/package/formatting/docs/Formatting-Time.html Formatting.Time>@+from the @<https://hackage.haskell.org/package/formatting formatting>@ package.++Most of the time you'll want to use one of these formatters:++@+>>> __'dateTimeF' t                  -- full date and time__+"Sun May 14 16:16:47 MSK 2017"++>>> __'hmF' t                        -- hours and minutes__+"16:16"++>>> __'hmsF' t                       -- hours, minutes and seconds__+"16:16:47"++>>> __'dateDashF' t                  -- date in ISO 8601 format__+"2017-05-14"++>>> __'diffF' False t                -- time period (convenient for humans)__+"3 seconds"++>>> __'diffF' True t                 -- point in time (convenient for humans)__+"3 seconds ago"+@++Note that two formatters from @Formatting.Time@ have been renamed:++@+pico     -> 'picosecondF'+decimals -> 'subsecondF'+@++-}+module Fmt.Time+(+  -- * Custom+  timeF,++  -- * For 'TimeZone' (and 'ZonedTime' and 'UTCTime')+  tzF,+  tzNameF,+  dateTimeF,++  -- * For 'TimeOfDay' (and 'LocalTime' and 'ZonedTime' and 'UTCTime')+  hmF,+  hmsF,+  hmsLF,+  hmsPLF,+  dayHalfF,+  dayHalfUF,+  hour24F,+  hour12F,+  hour24SF,+  hour12SF,+  minuteF,+  secondF,+  picosecondF,+  subsecondF,++  -- * For 'UTCTime' and 'ZonedTime'+  epochF,++  -- * For 'Day' (and 'LocalTime' and 'ZonedTime' and 'UTCTime')+  dateSlashF,+  dateDashF,+  dateSlashLF,+  yearF,+  yyF,+  centuryF,+  monthNameF,+  monthNameShortF,+  monthF,+  dayOfMonthF,+  dayOfMonthOrdF,+  dayOfMonthSF,+  dayF,+  weekYearF,+  weekYYF,+  weekCenturyF,+  weekF,+  dayOfWeekF,+  dayNameShortF,+  dayNameF,+  weekFromZeroF,+  dayOfWeekFromZeroF,+  weekOfYearMonF,++  -- * Time spans, diffs, 'NominalDiffTime', 'DiffTime', etc.+  diffF,+  yearsF,+  daysF,+  hoursF,+  minutesF,+  secondsF,+)+where+++import           Data.List               (find)+import           Data.Monoid             ((<>))+import           Data.Text               (Text)+import qualified Data.Text               as T+import           Data.Text.Buildable     (build)+import           Data.Text.Lazy.Builder  (Builder)+import           Data.Time++#if !MIN_VERSION_time(1,5,0)+import           Data.Time.Locale.Compat+#endif++import           Fmt.Internal            (fixedF, ordinalF)+++----------------------------------------------------------------------------+-- Custom+----------------------------------------------------------------------------++-- | Format time with an arbitrary formatting string. Other formatters in+-- this module are implemented using 'timeF'.+timeF :: FormatTime a => Text -> a -> Builder+timeF f = build . T.pack . formatTime defaultTimeLocale (T.unpack f)++----------------------------------------------------------------------------+-- For 'TimeZone' (and 'ZonedTime' and 'UTCTime')+----------------------------------------------------------------------------++-- | Timezone offset on the format @-HHMM@.+--+-- >>> t <- getZonedTime+-- >>> t+-- 2017-05-14 16:16:47.62135 MSK+-- >>> tzF t+-- "+0300"+tzF :: FormatTime a => a -> Builder+tzF = timeF "%z"++-- | Timezone name.+--+-- >>> tzNameF t+-- "MSK"+tzNameF :: FormatTime a => a -> Builder+tzNameF = timeF "%Z"++-- | As 'dateTimeFmt' @locale@ (e.g. @%a %b %e %H:%M:%S %Z %Y@).+--+-- >>> dateTimeF t+-- "Sun May 14 16:16:47 MSK 2017"+dateTimeF :: FormatTime a => a -> Builder+dateTimeF = timeF "%c"++----------------------------------------------------------------------------+-- For 'TimeOfDay' (and 'LocalTime' and 'ZonedTime' and 'UTCTime')+----------------------------------------------------------------------------++-- | Same as @%H:%M@.+--+-- >>> hmF t+-- "16:16"+hmF :: FormatTime a => a -> Builder+hmF = timeF "%R"++-- | Same as @%H:%M:%S@.+--+-- >>> hmsF t+-- "16:16:47"+hmsF :: FormatTime a => a -> Builder+hmsF = timeF "%T"++-- | As 'timeFmt' @locale@ (e.g. @%H:%M:%S@).+--+-- >>> hmsLF t+-- "16:16:47"+hmsLF :: FormatTime a => a -> Builder+hmsLF = timeF "%X"++-- | As 'time12Fmt' @locale@ (e.g. @%I:%M:%S %p@).+--+-- >>> hmsPLF t+-- "04:16:47 PM"+hmsPLF :: FormatTime a => a -> Builder+hmsPLF = timeF "%r"++-- | Day half from ('amPm' @locale@), converted to lowercase, @am@, @pm@.+--+-- >>> dayHalfF t+-- "pm"+dayHalfF :: FormatTime a => a -> Builder+dayHalfF = timeF "%P"++-- | Day half from ('amPm' @locale@), @AM@, @PM@.+--+-- >>> dayHalfUF t+-- "PM"+dayHalfUF :: FormatTime a => a -> Builder+dayHalfUF = timeF "%p"++-- | Hour, 24-hour, leading 0 as needed, @00@ - @23@.+--+-- >>> hour24F t+-- "16"+-- >>> let nightT = read "2017-05-14 00:21:32.714083 UTC" :: UTCTime+-- >>> nightT+-- 2017-05-14 00:21:32.714083 UTC+-- >>> hour24F nightT+-- "00"+hour24F :: FormatTime a => a -> Builder+hour24F = timeF "%H"++-- | Hour, 12-hour, leading 0 as needed, @01@ - @12@.+--+-- >>> hour12F t+-- "04"+-- >>> hour12F nightT+-- "12"+hour12F :: FormatTime a => a -> Builder+hour12F = timeF "%I"++-- | Hour, 24-hour, leading space as needed, @ 0@ - @23@.+--+-- >>> hour24SF nightT+-- " 0"+hour24SF :: FormatTime a => a -> Builder+hour24SF = timeF "%k"++-- | Hour, 12-hour, leading space as needed, @ 1@ - @12@.+--+-- >>> hour12SF nightT+-- "12"+hour12SF :: FormatTime a => a -> Builder+hour12SF = timeF "%l"++-- | Minute, @00@ - @59@.+--+-- >>> otherT+-- 2017-05-14 17:12:47.897343 MSK+-- >>> minuteF otherT+-- "12"+minuteF :: FormatTime a => a -> Builder+minuteF = timeF "%M"++-- | Second, without decimal part, @00@ - @60@.+--+-- >>> secondF t+-- "47"+secondF :: FormatTime a => a -> Builder+secondF = timeF "%S"++-- | Picosecond, including trailing zeros, @000000000000@ - @999999999999@.+--+-- >>> picosecondF t+-- "621350000000"+picosecondF :: FormatTime a => a -> Builder+picosecondF = timeF "%q"++-- | Decimal point of the second. Up to 12 digits, without trailing zeros.+-- For a whole number of seconds, this produces an empty string.+--+-- >>> subsecondF t+-- ".62135"+subsecondF :: FormatTime a => a -> Builder+subsecondF = timeF "%Q"++----------------------------------------------------------------------------+-- For 'UTCTime' and 'ZonedTime'+----------------------------------------------------------------------------++-- | Number of whole seconds since the Unix epoch. For times before the Unix+-- epoch, this is a negative number. Note that in @%s.%q@ and @%s%Q@ the+-- decimals are positive, not negative. For example, 0.9 seconds before the+-- Unix epoch is formatted as @-1.1@ with @%s%Q@.+--+-- >>> epochF t+-- "1494767807"+epochF :: FormatTime a => a -> Builder+epochF = timeF "%s"++----------------------------------------------------------------------------+-- For 'Day' (and 'LocalTime' and 'ZonedTime' and 'UTCTime')+----------------------------------------------------------------------------++-- | Same as @%m\/%d\/%y@.+--+-- >>> dateSlashF t+-- "05/14/17"+dateSlashF :: FormatTime a => a -> Builder+dateSlashF = timeF "%D"++-- | Same as @%Y-%m-%d@.+--+-- >>> dateDashF t+-- "2017-05-14"+dateDashF :: FormatTime a => a -> Builder+dateDashF = timeF "%F"++-- | As 'dateFmt' @locale@ (e.g. @%m\/%d\/%y@).+--+-- >>> dateSlashLF t+-- "05/14/17"+dateSlashLF :: FormatTime a => a -> Builder+dateSlashLF = timeF "%x"++-- | Year.+--+-- >>> yearF t+-- "2017"+yearF :: FormatTime a => a -> Builder+yearF = timeF "%Y"++-- | Last two digits of year, @00@ - @99@.+--+-- >>> yyF t+-- "17"+yyF :: FormatTime a => a -> Builder+yyF = timeF "%y"++-- | Century (being the first two digits of the year), @00@ - @99@.+--+-- >>> centuryF t+-- "20"+centuryF :: FormatTime a => a -> Builder+centuryF = timeF "%C"++-- | Month name, long form ('fst' from 'months' @locale@), @January@ -+-- @December@.+--+-- >>> let longMonthT = read "2017-01-12 00:21:32.714083 UTC" :: UTCTime+-- >>> monthNameF longMonthT+-- "January"+monthNameF :: FormatTime a => a -> Builder+monthNameF = timeF "%B"++-- | Month name, short form ('snd' from 'months' @locale@), @Jan@ - @Dec@.+--+-- >>> monthNameShortF longMonthT+-- "Jan"+monthNameShortF :: FormatTime a => a -> Builder+monthNameShortF = timeF "%b"++-- | Month of year, leading 0 as needed, @01@ - @12@.+--+-- >>> monthF longMonthT+-- "01"+monthF :: FormatTime a => a -> Builder+monthF = timeF "%m"++-- | Day of month, leading 0 as needed, @01@ - @31@.+--+-- >>> dayOfMonthF t+-- "14"+dayOfMonthF :: FormatTime a => a -> Builder+dayOfMonthF = timeF "%d"++-- | Day of month, @1st@, @2nd@, @25th@, etc.+--+-- >>> dayOfMonthOrdF t+-- "14th"+dayOfMonthOrdF :: FormatTime a => a -> Builder+dayOfMonthOrdF = ordinalF . timeToInt+  where+    timeToInt :: FormatTime a => a -> Int+    timeToInt = read . formatTime defaultTimeLocale "%d"++-- | Day of month, leading space as needed, @ 1@ - @31@.+dayOfMonthSF :: FormatTime a => a -> Builder+dayOfMonthSF = timeF "%e"++-- | Day of year for Ordinal Date format, @001@ - @366@.+--+-- >>> dayF t+-- "134"+dayF :: FormatTime a => a -> Builder+dayF = timeF "%j"++-- | Year for Week Date format e.g. @2013@.+--+-- >>> weekYearF t+-- "2017"+weekYearF :: FormatTime a => a -> Builder+weekYearF = timeF "%G"++-- | Last two digits of year for Week Date format, @00@ - @99@.+--+-- >>> weekYYF t+-- "17"+weekYYF :: FormatTime a => a -> Builder+weekYYF = timeF "%g"++-- | Century (first two digits of year) for Week Date format, @00@ - @99@.+--+-- >>> weekCenturyF t+-- "20"+weekCenturyF :: FormatTime a => a -> Builder+weekCenturyF = timeF "%f"++-- | Week for Week Date format, @01@ - @53@.+--+-- >>> weekF t+-- "19"+weekF :: FormatTime a => a -> Builder+weekF = timeF "%V"++-- | Day for Week Date format, @1@ - @7@.+--+-- >>> dayOfWeekF t+-- "7"+dayOfWeekF :: FormatTime a => a -> Builder+dayOfWeekF = timeF "%u"++-- | Day of week, short form ('snd' from 'wDays' @locale@), @Sun@ - @Sat@.+--+-- >>> dayNameShortF t+-- "Sun"+dayNameShortF :: FormatTime a => a -> Builder+dayNameShortF = timeF "%a"++-- | Day of week, long form ('fst' from 'wDays' @locale@), @Sunday@ -+-- @Saturday@.+--+-- >>> dayNameF t+-- "Sunday"+dayNameF :: FormatTime a => a -> Builder+dayNameF = timeF "%A"++-- | Week number of year, where weeks start on Sunday (as+-- 'sundayStartWeek'), @00@ - @53@.+--+-- >>> weekFromZeroF t+-- "20"+weekFromZeroF :: FormatTime a => a -> Builder+weekFromZeroF = timeF "%U"++-- | Day of week number, @0@ (= Sunday) - @6@ (= Saturday).+--+-- >>> dayOfWeekFromZeroF t+-- "0"+dayOfWeekFromZeroF :: FormatTime a => a -> Builder+dayOfWeekFromZeroF = timeF "%w"++-- | Week number of year, where weeks start on Monday (as+-- 'mondayStartWeek'), @00@ - @53@.+--+-- >>> weekOfYearMonF t+-- "19"+weekOfYearMonF :: FormatTime a => a -> Builder+weekOfYearMonF = timeF "%W"++----------------------------------------------------------------------------+-- Time spans, diffs, 'NominalDiffTime', 'DiffTime', etc.+----------------------------------------------------------------------------++-- | Display a time span as one time relative to another. Input is assumed to+-- be seconds. Typical inputs are 'NominalDiffTime' and 'DiffTime'.+--+-- >>> diffF False 100+-- "a minute"+-- >>> diffF True 100+-- "in a minute"+diffF :: forall n . RealFrac n+      => Bool     -- ^ Whether to display the @in/ago@ prefix or not+      -> n        -- ^ Example: @3 seconds ago@, @in 2 days@+      -> Builder+diffF fix = diffed+  where+    diffed :: RealFrac n => n -> Builder+    diffed ts =+      case find (\(s,_,_) -> abs ts >= s) (reverse ranges) of+        Nothing           -> "unknown"+        Just (_, f, base) -> prefix <> f (toInt ts base) <> suffix+      where+        prefix = if fix && ts > 0 then "in "  else ""+        suffix = if fix && ts < 0 then " ago" else ""++    toInt :: RealFrac n => n -> n -> Int+    toInt ts base = abs (round (ts / base))++    intF :: Builder -> Int -> Builder+    intF t n = build n <> t++    ranges :: RealFrac n => [(n, Int -> Builder, n)]+    ranges =+      [ (0           , intF  " milliseconds" , 0.001 )+      , (1           , intF  " seconds"      , 1     )+      , (minute      , const "a minute"      , 0     )+      , (minute * 2  , intF  " minutes"      , minute)+      , (minute * 30 , const "half an hour"  , 0     )+      , (minute * 31 , intF  " minutes"      , minute)+      , (hour        , const "an hour"       , 0     )+      , (hour * 2    , intF  " hours"        , hour  )+      , (hour * 3    , const "a few hours"   , 0     )+      , (hour * 4    , intF  " hours"        , hour  )+      , (day         , const "a day"         , 0     )+      , (day * 2     , intF  " days"         , day   )+      , (week        , const "a week"        , 0     )+      , (week * 2    , intF  " weeks"        , week  )+      , (month       , const "a month"       , 0     )+      , (month * 2   , intF  " months"       , month )+      , (year        , const "a year"        , 0     )+      , (year * 2    , intF  " years"        , year  )+      ]+      where year   = month  * 12+            month  = day    * 30+            week   = day    * 7+            day    = hour   * 24+            hour   = minute * 60+            minute = 60++-- | Display the absolute value time span in years.+--+-- >>> epochF t+-- "1494767807"+-- >>> yearsF 3 1494767807+-- "47.399"+yearsF :: RealFrac n+       => Int -- ^ Decimal places.+       -> n+       -> Builder+yearsF n = fixedF n . abs . count+  where count x = x / 365 / 24 / 60 / 60++-- | Display the absolute value time span in days.+--+-- >>> daysF 3 1494767807+-- "17300.553"+daysF :: RealFrac n+      => Int -- ^ Decimal places.+      -> n+      -> Builder+daysF n = fixedF n . abs . count+  where count x = x / 24 / 60 / 60++-- | Display the absolute value time span in hours.+--+-- >>> hoursF 3 3600+-- "1.000"+hoursF :: RealFrac n+       => Int -- ^ Decimal places.+       -> n+       -> Builder+hoursF n = fixedF n . abs . count+  where count x = x / 60 / 60++-- | Display the absolute value time span in minutes.+--+-- >>> minutesF 3 150+-- "2.500"+minutesF :: RealFrac n+         => Int -- ^ Decimal places.+         -> n+         -> Builder+minutesF n = fixedF n . abs . count+  where count x = x / 60++-- | Display the absolute value time span in seconds.+--+-- >>> secondsF 3 100+-- "100.000"+secondsF :: RealFrac n+         => Int -- ^ Decimal places.+         -> n+         -> Builder+secondsF n = fixedF n . abs