{-# LANGUAGE CPP #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE OverloadedStrings #-}

-- | Formatters for time.

module Formatting.Time where

import           Data.List
import           Data.Text.Lazy.Builder
import           Formatting.Formatters  hiding (build)
import           Formatting.Internal

import           Data.Text              (Text)
import qualified Data.Text              as T
import           Formatting.Buildable
import           Data.Time
#if MIN_VERSION_time(1,5,0)
import           System.Locale hiding (defaultTimeLocale)
#else
import           System.Locale
#endif

-- * For 'TimeZone' (and 'ZonedTime' and 'UTCTime'):

-- | Timezone offset on the format @-HHMM@.
tz :: FormatTime a => Format r (a -> r)
tz :: Format r (a -> r)
tz = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%z")

-- | Timezone name.
tzName :: FormatTime a => Format r (a -> r)
tzName :: Format r (a -> r)
tzName = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%Z")

-- | As 'dateTimeFmt' @locale@ (e.g. @%a %b %e %H:%M:%S %Z %Y@).
datetime :: FormatTime a => Format r (a -> r)
datetime :: Format r (a -> r)
datetime = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%c")

-- * For 'TimeOfDay' (and 'LocalTime' and 'ZonedTime' and 'UTCTime'):

-- | Same as @%H:%M@.
hm :: FormatTime a => Format r (a -> r)
hm :: Format r (a -> r)
hm = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%R")

-- | Same as @%H:%M:%S@.
hms :: FormatTime a => Format r (a -> r)
hms :: Format r (a -> r)
hms = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%T")

-- | As 'timeFmt' @locale@ (e.g. @%H:%M:%S@).
hmsL :: FormatTime a => Format r (a -> r)
hmsL :: Format r (a -> r)
hmsL = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%X")

-- | As 'time12Fmt' @locale@ (e.g. @%I:%M:%S %p@).
hmsPL :: FormatTime a => Format r (a -> r)
hmsPL :: Format r (a -> r)
hmsPL = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%r")

-- | Day half from ('amPm' @locale@), converted to lowercase, @am@,
-- @pm@.
dayHalf :: FormatTime a => Format r (a -> r)
dayHalf :: Format r (a -> r)
dayHalf = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%P")

-- | Day half from ('amPm' @locale@), @AM@, @PM@.
dayHalfU :: FormatTime a => Format r (a -> r)
dayHalfU :: Format r (a -> r)
dayHalfU = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%p")

-- | Hour, 24-hour, leading 0 as needed, @00@ - @23@.
hour24 :: FormatTime a => Format r (a -> r)
hour24 :: Format r (a -> r)
hour24 = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%H")

-- | Hour, 12-hour, leading 0 as needed, @01@ - @12@.
hour12 :: FormatTime a => Format r (a -> r)
hour12 :: Format r (a -> r)
hour12 = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%I")

-- | Hour, 24-hour, leading space as needed, @ 0@ - @23@.
hour24S :: FormatTime a => Format r (a -> r)
hour24S :: Format r (a -> r)
hour24S = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%k")

-- | Hour, 12-hour, leading space as needed, @ 1@ - @12@.
hour12S :: FormatTime a => Format r (a -> r)
hour12S :: Format r (a -> r)
hour12S = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%l")

-- | Minute, @00@ - @59@.
minute :: FormatTime a => Format r (a -> r)
minute :: Format r (a -> r)
minute = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%M")

-- | Second, without decimal part, @00@ - @60@.
second :: FormatTime a => Format r (a -> r)
second :: Format r (a -> r)
second = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%S")

-- | Picosecond, including trailing zeros, @000000000000@ -
-- @999999999999@.
pico :: FormatTime a => Format r (a -> r)
pico :: Format r (a -> r)
pico = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%q")

-- | Decimal point and up to 12 second decimals, without trailing
-- zeros. For a whole number of seconds, this produces the empty
-- string.
decimals :: FormatTime a => Format r (a -> r)
decimals :: Format r (a -> r)
decimals = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%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@.
epoch :: FormatTime a => Format r (a -> r)
epoch :: Format r (a -> r)
epoch = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%s")

-- * For 'Day' (and 'LocalTime' and 'ZonedTime' and 'UTCTime'):

-- | Same as @%m\/%d\/%y@.
dateSlash :: FormatTime a => Format r (a -> r)
dateSlash :: Format r (a -> r)
dateSlash = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%D")

-- | Same as @%Y-%m-%d@.
dateDash :: FormatTime a => Format r (a -> r)
dateDash :: Format r (a -> r)
dateDash = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%F")

-- | As 'dateFmt' @locale@ (e.g. @%m\/%d\/%y@).
dateSlashL :: FormatTime a => Format r (a -> r)
dateSlashL :: Format r (a -> r)
dateSlashL = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%x")

-- | Year.
year :: FormatTime a => Format r (a -> r)
year :: Format r (a -> r)
year = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%Y")

-- | Last two digits of year, @00@ - @99@.
yy :: FormatTime a => Format r (a -> r)
yy :: Format r (a -> r)
yy = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%y")

-- | Century (being the first two digits of the year), @00@ - @99@.
century :: FormatTime a => Format r (a -> r)
century :: Format r (a -> r)
century = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%C")

-- | Month name, long form ('fst' from 'months' @locale@), @January@ -
-- @December@.
monthName :: FormatTime a => Format r (a -> r)
monthName :: Format r (a -> r)
monthName = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%B")

-- | @ %H] month name, short form ('snd' from 'months' @locale@),
-- @Jan@ - @Dec@.
monthNameShort :: FormatTime a => Format r (a -> r)
monthNameShort :: Format r (a -> r)
monthNameShort = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%b")

-- | Month of year, leading 0 as needed, @01@ - @12@.
month :: FormatTime a => Format r (a -> r)
month :: Format r (a -> r)
month = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%m")

-- | Day of month, leading 0 as needed, @01@ - @31@.
dayOfMonth :: FormatTime a => Format r (a -> r)
dayOfMonth :: Format r (a -> r)
dayOfMonth = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%d")

-- | Day of month, @1st@, @2nd@, @25th@, etc.
dayOfMonthOrd :: FormatTime a => Format r (a -> r)
dayOfMonthOrd :: Format r (a -> r)
dayOfMonthOrd = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Format Builder (Int -> Builder) -> Int -> Builder
forall a. Format Builder a -> a
bprint Format Builder (Int -> Builder)
forall n r. Integral n => Format r (n -> r)
ords (Int -> Builder) -> (a -> Int) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Int
forall a. FormatTime a => a -> Int
toInt)
  where toInt :: FormatTime a => a -> Int
        toInt :: a -> Int
toInt = String -> Int
forall a. Read a => String -> a
read (String -> Int) -> (a -> String) -> a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeLocale -> String -> a -> String
forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale String
"%d"

-- | Day of month, leading space as needed, @ 1@ - @31@.
dayOfMonthS :: FormatTime a => Format r (a -> r)
dayOfMonthS :: Format r (a -> r)
dayOfMonthS = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%e")

-- | Day of year for Ordinal Date format, @001@ - @366@.
day :: FormatTime a => Format r (a -> r)
day :: Format r (a -> r)
day = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%j")

-- | Year for Week Date format e.g. @2013@.
weekYear :: FormatTime a => Format r (a -> r)
weekYear :: Format r (a -> r)
weekYear = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%G")

-- | Last two digits of year for Week Date format, @00@ - @99@.
weekYY :: FormatTime a => Format r (a -> r)
weekYY :: Format r (a -> r)
weekYY = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%g")

-- | Century (first two digits of year) for Week Date format, @00@ -
-- @99@.
weekCentury :: FormatTime a => Format r (a -> r)
weekCentury :: Format r (a -> r)
weekCentury = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%f")

-- | Week for Week Date format, @01@ - @53@.
week :: FormatTime a => Format r (a -> r)
week :: Format r (a -> r)
week = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%V")

-- | Day for Week Date format, @1@ - @7@.
dayOfWeek :: FormatTime a => Format r (a -> r)
dayOfWeek :: Format r (a -> r)
dayOfWeek = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%u")

-- | Day of week, short form ('snd' from 'wDays' @locale@), @Sun@ -
-- @Sat@.
dayNameShort :: FormatTime a => Format r (a -> r)
dayNameShort :: Format r (a -> r)
dayNameShort = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%a")

-- | Day of week, long form ('fst' from 'wDays' @locale@), @Sunday@ -
-- @Saturday@.
dayName :: FormatTime a => Format r (a -> r)
dayName :: Format r (a -> r)
dayName = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%A")

-- | Week number of year, where weeks start on Sunday (as
-- 'sundayStartWeek'), @00@ - @53@.
weekFromZero :: FormatTime a => Format r (a -> r)
weekFromZero :: Format r (a -> r)
weekFromZero = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%U")

-- | Day of week number, @0@ (= Sunday) - @6@ (= Saturday).
dayOfWeekFromZero :: FormatTime a => Format r (a -> r)
dayOfWeekFromZero :: Format r (a -> r)
dayOfWeekFromZero = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%w")

-- | Week number of year, where weeks start on Monday (as
-- 'mondayStartWeek'), @00@ - @53@.
weekOfYearMon :: FormatTime a => Format r (a -> r)
weekOfYearMon :: Format r (a -> r)
weekOfYearMon = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
"%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'.
diff :: (RealFrac n)
     => Bool     -- ^ Display 'in/ago'?
     -> Format r (n -> r) -- ^ Example: '3 seconds ago', 'in three days'.)
diff :: Bool -> Format r (n -> r)
diff Bool
fix =
  (n -> Builder) -> Format r (n -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later n -> Builder
diffed
  where
    diffed :: n -> Builder
diffed n
ts =
      case ((n, Format Builder (Int -> Builder), n) -> Bool)
-> [(n, Format Builder (Int -> Builder), n)]
-> Maybe (n, Format Builder (Int -> Builder), n)
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (\(n
s,Format Builder (Int -> Builder)
_,n
_) -> n -> n
forall a. Num a => a -> a
abs n
ts n -> n -> Bool
forall a. Ord a => a -> a -> Bool
>= n
s) ([(n, Format Builder (Int -> Builder), n)]
-> [(n, Format Builder (Int -> Builder), n)]
forall a. [a] -> [a]
reverse [(n, Format Builder (Int -> Builder), n)]
forall r. [(n, Format r (Int -> r), n)]
ranges) of
        Maybe (n, Format Builder (Int -> Builder), n)
Nothing -> Builder
"unknown"
        Just (n
_,Format Builder (Int -> Builder)
f,n
base) -> Format Builder (Int -> Builder) -> Int -> Builder
forall a. Format Builder a -> a
bprint (Format (Int -> Builder) (Int -> Builder)
forall r. Format r r
prefix Format (Int -> Builder) (Int -> Builder)
-> Format Builder (Int -> Builder)
-> Format Builder (Int -> Builder)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format Builder (Int -> Builder)
f Format Builder (Int -> Builder)
-> Format Builder Builder -> Format Builder (Int -> Builder)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format Builder Builder
forall r. Format r r
suffix) (n -> n -> Int
forall a. RealFrac a => a -> a -> Int
toInt n
ts n
base)
      where prefix :: Format r r
prefix = Builder -> Format r r
forall r. Builder -> Format r r
now (if Bool
fix Bool -> Bool -> Bool
&& n
ts n -> n -> Bool
forall a. Ord a => a -> a -> Bool
> n
0 then Builder
"in " else Builder
"")
            suffix :: Format r r
suffix = Builder -> Format r r
forall r. Builder -> Format r r
now (if Bool
fix Bool -> Bool -> Bool
&& n
ts n -> n -> Bool
forall a. Ord a => a -> a -> Bool
< n
0 then Builder
" ago" else Builder
"")
    toInt :: a -> a -> Int
toInt a
ts a
base = Int -> Int
forall a. Num a => a -> a
abs (a -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round (a
ts a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
base)) :: Int
    ranges :: [(n, Format r (Int -> r), n)]
ranges =
      [(n
0,Format r (Int -> r)
forall n r. Integral n => Format r (n -> r)
int Format r (Int -> r) -> Format r r -> Format r (Int -> r)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format r r
" milliseconds",n
0.001)
      ,(n
1,Format r (Int -> r)
forall n r. Integral n => Format r (n -> r)
int Format r (Int -> r) -> Format r r -> Format r (Int -> r)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format r r
" seconds",n
1)
      ,(n
minute,Builder -> Format r (Int -> r)
forall r a. Builder -> Format r (a -> r)
fconst Builder
"a minute",n
0)
      ,(n
minuten -> n -> n
forall a. Num a => a -> a -> a
*n
2,Format r (Int -> r)
forall n r. Integral n => Format r (n -> r)
int Format r (Int -> r) -> Format r r -> Format r (Int -> r)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format r r
" minutes",n
minute)
      ,(n
minuten -> n -> n
forall a. Num a => a -> a -> a
*n
30,Builder -> Format r (Int -> r)
forall r a. Builder -> Format r (a -> r)
fconst Builder
"half an hour",n
0)
      ,(n
minuten -> n -> n
forall a. Num a => a -> a -> a
*n
31,Format r (Int -> r)
forall n r. Integral n => Format r (n -> r)
int Format r (Int -> r) -> Format r r -> Format r (Int -> r)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format r r
" minutes",n
minute)
      ,(n
hour,Builder -> Format r (Int -> r)
forall r a. Builder -> Format r (a -> r)
fconst Builder
"an hour",n
0)
      ,(n
hourn -> n -> n
forall a. Num a => a -> a -> a
*n
2,Format r (Int -> r)
forall n r. Integral n => Format r (n -> r)
int Format r (Int -> r) -> Format r r -> Format r (Int -> r)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format r r
" hours",n
hour)
      ,(n
hourn -> n -> n
forall a. Num a => a -> a -> a
*n
3,Builder -> Format r (Int -> r)
forall r a. Builder -> Format r (a -> r)
fconst Builder
"a few hours",n
0)
      ,(n
hourn -> n -> n
forall a. Num a => a -> a -> a
*n
4,Format r (Int -> r)
forall n r. Integral n => Format r (n -> r)
int Format r (Int -> r) -> Format r r -> Format r (Int -> r)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format r r
" hours",n
hour)
      ,(n
day,Builder -> Format r (Int -> r)
forall r a. Builder -> Format r (a -> r)
fconst Builder
"a day",n
0)
      ,(n
dayn -> n -> n
forall a. Num a => a -> a -> a
*n
2,Format r (Int -> r)
forall n r. Integral n => Format r (n -> r)
int Format r (Int -> r) -> Format r r -> Format r (Int -> r)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format r r
" days",n
day)
      ,(n
week,Builder -> Format r (Int -> r)
forall r a. Builder -> Format r (a -> r)
fconst Builder
"a week",n
0)
      ,(n
weekn -> n -> n
forall a. Num a => a -> a -> a
*n
2,Format r (Int -> r)
forall n r. Integral n => Format r (n -> r)
int Format r (Int -> r) -> Format r r -> Format r (Int -> r)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format r r
" weeks",n
week)
      ,(n
month,Builder -> Format r (Int -> r)
forall r a. Builder -> Format r (a -> r)
fconst Builder
"a month",n
0)
      ,(n
monthn -> n -> n
forall a. Num a => a -> a -> a
*n
2,Format r (Int -> r)
forall n r. Integral n => Format r (n -> r)
int Format r (Int -> r) -> Format r r -> Format r (Int -> r)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format r r
" months",n
month)
      ,(n
year,Builder -> Format r (Int -> r)
forall r a. Builder -> Format r (a -> r)
fconst Builder
"a year",n
0)
      ,(n
yearn -> n -> n
forall a. Num a => a -> a -> a
*n
2,Format r (Int -> r)
forall n r. Integral n => Format r (n -> r)
int Format r (Int -> r) -> Format r r -> Format r (Int -> r)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format r r
" years",n
year)]
      where year :: n
year = n
month n -> n -> n
forall a. Num a => a -> a -> a
* n
12
            month :: n
month = n
day n -> n -> n
forall a. Num a => a -> a -> a
* n
30
            week :: n
week = n
day n -> n -> n
forall a. Num a => a -> a -> a
* n
7
            day :: n
day = n
hour n -> n -> n
forall a. Num a => a -> a -> a
* n
24
            hour :: n
hour = n
minute n -> n -> n
forall a. Num a => a -> a -> a
* n
60
            minute :: n
minute = n
60

-- | Display the absolute value time span in years.
years :: (RealFrac n)
      => Int -- ^ Decimal places.
      -> Format r (n -> r)
years :: Int -> Format r (n -> r)
years Int
n = (n -> Builder) -> Format r (n -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Format Builder (n -> Builder) -> n -> Builder
forall a. Format Builder a -> a
bprint (Int -> Format Builder (n -> Builder)
forall a r. Real a => Int -> Format r (a -> r)
fixed Int
n) (n -> Builder) -> (n -> n) -> n -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. n -> n
forall a. Num a => a -> a
abs (n -> n) -> (n -> n) -> n -> n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. n -> n
forall a. Fractional a => a -> a
count)
  where count :: a -> a
count a
n = a
n a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
365 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
24 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
60 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
60

-- | Display the absolute value time span in days.
days :: (RealFrac n)
      => Int -- ^ Decimal places.
      -> Format r (n -> r)
days :: Int -> Format r (n -> r)
days Int
n = (n -> Builder) -> Format r (n -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Format Builder (n -> Builder) -> n -> Builder
forall a. Format Builder a -> a
bprint (Int -> Format Builder (n -> Builder)
forall a r. Real a => Int -> Format r (a -> r)
fixed Int
n) (n -> Builder) -> (n -> n) -> n -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. n -> n
forall a. Num a => a -> a
abs (n -> n) -> (n -> n) -> n -> n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. n -> n
forall a. Fractional a => a -> a
count)
  where count :: a -> a
count a
n = a
n a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
24 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
60 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
60

-- | Display the absolute value time span in hours.
hours :: (RealFrac n)
      => Int -- ^ Decimal places.
      -> Format r (n -> r)
hours :: Int -> Format r (n -> r)
hours Int
n = (n -> Builder) -> Format r (n -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Format Builder (n -> Builder) -> n -> Builder
forall a. Format Builder a -> a
bprint (Int -> Format Builder (n -> Builder)
forall a r. Real a => Int -> Format r (a -> r)
fixed Int
n) (n -> Builder) -> (n -> n) -> n -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. n -> n
forall a. Num a => a -> a
abs (n -> n) -> (n -> n) -> n -> n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. n -> n
forall a. Fractional a => a -> a
count)
  where count :: a -> a
count a
n = a
n a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
60 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
60

-- | Display the absolute value time span in minutes.
minutes :: (RealFrac n)
      => Int -- ^ Decimal places.
      -> Format r (n -> r)
minutes :: Int -> Format r (n -> r)
minutes Int
n = (n -> Builder) -> Format r (n -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Format Builder (n -> Builder) -> n -> Builder
forall a. Format Builder a -> a
bprint (Int -> Format Builder (n -> Builder)
forall a r. Real a => Int -> Format r (a -> r)
fixed Int
n) (n -> Builder) -> (n -> n) -> n -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. n -> n
forall a. Num a => a -> a
abs (n -> n) -> (n -> n) -> n -> n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. n -> n
forall a. Fractional a => a -> a
count)
  where count :: a -> a
count a
n = a
n a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
60

-- | Display the absolute value time span in seconds.
seconds :: (RealFrac n)
      => Int -- ^ Decimal places.
      -> Format r (n -> r)
seconds :: Int -> Format r (n -> r)
seconds Int
n = (n -> Builder) -> Format r (n -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Format Builder (n -> Builder) -> n -> Builder
forall a. Format Builder a -> a
bprint (Int -> Format Builder (n -> Builder)
forall a r. Real a => Int -> Format r (a -> r)
fixed Int
n) (n -> Builder) -> (n -> n) -> n -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. n -> n
forall a. Num a => a -> a
abs (n -> n) -> (n -> n) -> n -> n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. n -> n
forall p. p -> p
count)
  where count :: p -> p
count p
n = p
n

-- * Internal.

-- | Formatter call. Probably don't want to use this.
fmt :: FormatTime a => Text -> a -> Text
fmt :: Text -> a -> Text
fmt Text
f = String -> Text
T.pack (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeLocale -> String -> a -> String
forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale (Text -> String
T.unpack Text
f)

-- | Helper for creating custom time formatters
customTimeFmt :: FormatTime a => Text -> Format r (a -> r)
customTimeFmt :: Text -> Format r (a -> r)
customTimeFmt Text
f = (a -> Builder) -> Format r (a -> r)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> a -> Text
forall a. FormatTime a => Text -> a -> Text
fmt Text
f)