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 +4/−0
- fmt.cabal +9/−3
- lib/Fmt.hs +4/−28
- lib/Fmt/Internal.hs +39/−0
- lib/Fmt/Time.hs +577/−0
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