{-# LANGUAGE CPP #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Fmt.Time
(
timeF,
tzF,
tzNameF,
dateTimeF,
hmF,
hmsF,
hmsLF,
hmsPLF,
dayHalfF,
dayHalfUF,
hour24F,
hour12F,
hour24SF,
hour12SF,
minuteF,
secondF,
picosecondF,
subsecondF,
epochF,
dateSlashF,
dateDashF,
dateSlashLF,
yearF,
yyF,
centuryF,
monthNameF,
monthNameShortF,
monthF,
dayOfMonthF,
dayOfMonthOrdF,
dayOfMonthSF,
dayF,
weekYearF,
weekYYF,
weekCenturyF,
weekF,
dayOfWeekF,
dayNameShortF,
dayNameF,
weekFromZeroF,
dayOfWeekFromZeroF,
weekOfYearMonF,
diffF,
yearsF,
daysF,
hoursF,
minutesF,
secondsF,
)
where
import Data.List (find)
#if !MIN_VERSION_base(4,9,0)
import Data.Monoid ((<>))
#endif
import Data.Text (Text)
import qualified Data.Text as T
import Formatting.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.Numeric (fixedF, ordinalF)
timeF :: FormatTime a => Text -> a -> Builder
timeF :: forall a. FormatTime a => Text -> a -> Builder
timeF Text
f = forall p. Buildable p => p -> Builder
build forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale (Text -> String
T.unpack Text
f)
tzF :: FormatTime a => a -> Builder
tzF :: forall a. FormatTime a => a -> Builder
tzF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%z"
tzNameF :: FormatTime a => a -> Builder
tzNameF :: forall a. FormatTime a => a -> Builder
tzNameF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%Z"
dateTimeF :: FormatTime a => a -> Builder
dateTimeF :: forall a. FormatTime a => a -> Builder
dateTimeF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%c"
hmF :: FormatTime a => a -> Builder
hmF :: forall a. FormatTime a => a -> Builder
hmF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%R"
hmsF :: FormatTime a => a -> Builder
hmsF :: forall a. FormatTime a => a -> Builder
hmsF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%T"
hmsLF :: FormatTime a => a -> Builder
hmsLF :: forall a. FormatTime a => a -> Builder
hmsLF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%X"
hmsPLF :: FormatTime a => a -> Builder
hmsPLF :: forall a. FormatTime a => a -> Builder
hmsPLF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%r"
dayHalfF :: FormatTime a => a -> Builder
dayHalfF :: forall a. FormatTime a => a -> Builder
dayHalfF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%P"
dayHalfUF :: FormatTime a => a -> Builder
dayHalfUF :: forall a. FormatTime a => a -> Builder
dayHalfUF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%p"
hour24F :: FormatTime a => a -> Builder
hour24F :: forall a. FormatTime a => a -> Builder
hour24F = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%H"
hour12F :: FormatTime a => a -> Builder
hour12F :: forall a. FormatTime a => a -> Builder
hour12F = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%I"
hour24SF :: FormatTime a => a -> Builder
hour24SF :: forall a. FormatTime a => a -> Builder
hour24SF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%k"
hour12SF :: FormatTime a => a -> Builder
hour12SF :: forall a. FormatTime a => a -> Builder
hour12SF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%l"
minuteF :: FormatTime a => a -> Builder
minuteF :: forall a. FormatTime a => a -> Builder
minuteF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%M"
secondF :: FormatTime a => a -> Builder
secondF :: forall a. FormatTime a => a -> Builder
secondF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%S"
picosecondF :: FormatTime a => a -> Builder
picosecondF :: forall a. FormatTime a => a -> Builder
picosecondF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%q"
subsecondF :: FormatTime a => a -> Builder
subsecondF :: forall a. FormatTime a => a -> Builder
subsecondF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%Q"
epochF :: FormatTime a => a -> Builder
epochF :: forall a. FormatTime a => a -> Builder
epochF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%s"
dateSlashF :: FormatTime a => a -> Builder
dateSlashF :: forall a. FormatTime a => a -> Builder
dateSlashF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%D"
dateDashF :: FormatTime a => a -> Builder
dateDashF :: forall a. FormatTime a => a -> Builder
dateDashF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%F"
dateSlashLF :: FormatTime a => a -> Builder
dateSlashLF :: forall a. FormatTime a => a -> Builder
dateSlashLF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%x"
yearF :: FormatTime a => a -> Builder
yearF :: forall a. FormatTime a => a -> Builder
yearF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%Y"
yyF :: FormatTime a => a -> Builder
yyF :: forall a. FormatTime a => a -> Builder
yyF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%y"
centuryF :: FormatTime a => a -> Builder
centuryF :: forall a. FormatTime a => a -> Builder
centuryF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%C"
monthNameF :: FormatTime a => a -> Builder
monthNameF :: forall a. FormatTime a => a -> Builder
monthNameF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%B"
monthNameShortF :: FormatTime a => a -> Builder
monthNameShortF :: forall a. FormatTime a => a -> Builder
monthNameShortF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%b"
monthF :: FormatTime a => a -> Builder
monthF :: forall a. FormatTime a => a -> Builder
monthF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%m"
dayOfMonthF :: FormatTime a => a -> Builder
dayOfMonthF :: forall a. FormatTime a => a -> Builder
dayOfMonthF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%d"
dayOfMonthOrdF :: FormatTime a => a -> Builder
dayOfMonthOrdF :: forall a. FormatTime a => a -> Builder
dayOfMonthOrdF = forall a. (Buildable a, Integral a) => a -> Builder
ordinalF forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. FormatTime a => a -> Int
timeToInt
where
timeToInt :: FormatTime a => a -> Int
timeToInt :: forall a. FormatTime a => a -> Int
timeToInt = forall a. Read a => String -> a
read forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale String
"%d"
dayOfMonthSF :: FormatTime a => a -> Builder
dayOfMonthSF :: forall a. FormatTime a => a -> Builder
dayOfMonthSF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%e"
dayF :: FormatTime a => a -> Builder
dayF :: forall a. FormatTime a => a -> Builder
dayF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%j"
weekYearF :: FormatTime a => a -> Builder
weekYearF :: forall a. FormatTime a => a -> Builder
weekYearF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%G"
weekYYF :: FormatTime a => a -> Builder
weekYYF :: forall a. FormatTime a => a -> Builder
weekYYF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%g"
weekCenturyF :: FormatTime a => a -> Builder
weekCenturyF :: forall a. FormatTime a => a -> Builder
weekCenturyF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%f"
weekF :: FormatTime a => a -> Builder
weekF :: forall a. FormatTime a => a -> Builder
weekF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%V"
dayOfWeekF :: FormatTime a => a -> Builder
dayOfWeekF :: forall a. FormatTime a => a -> Builder
dayOfWeekF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%u"
dayNameShortF :: FormatTime a => a -> Builder
dayNameShortF :: forall a. FormatTime a => a -> Builder
dayNameShortF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%a"
dayNameF :: FormatTime a => a -> Builder
dayNameF :: forall a. FormatTime a => a -> Builder
dayNameF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%A"
weekFromZeroF :: FormatTime a => a -> Builder
weekFromZeroF :: forall a. FormatTime a => a -> Builder
weekFromZeroF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%U"
dayOfWeekFromZeroF :: FormatTime a => a -> Builder
dayOfWeekFromZeroF :: forall a. FormatTime a => a -> Builder
dayOfWeekFromZeroF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%w"
weekOfYearMonF :: FormatTime a => a -> Builder
weekOfYearMonF :: forall a. FormatTime a => a -> Builder
weekOfYearMonF = forall a. FormatTime a => Text -> a -> Builder
timeF Text
"%W"
diffF :: forall n . RealFrac n
=> Bool
-> n
-> Builder
diffF :: forall n. RealFrac n => Bool -> n -> Builder
diffF Bool
fix = RealFrac n => n -> Builder
diffed
where
diffed :: RealFrac n => n -> Builder
diffed :: RealFrac n => n -> Builder
diffed n
ts =
case forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (\(n
s,Int -> Builder
_,n
_) -> forall a. Num a => a -> a
abs n
ts forall a. Ord a => a -> a -> Bool
>= n
s) (forall a. [a] -> [a]
reverse RealFrac n => [(n, Int -> Builder, n)]
ranges) of
Maybe (n, Int -> Builder, n)
Nothing -> Builder
"unknown"
Just (n
_, Int -> Builder
f, n
base) -> Builder
prefix forall a. Semigroup a => a -> a -> a
<> Int -> Builder
f (RealFrac n => n -> n -> Int
toInt n
ts n
base) forall a. Semigroup a => a -> a -> a
<> Builder
suffix
where
prefix :: Builder
prefix = if Bool
fix Bool -> Bool -> Bool
&& n
ts forall a. Ord a => a -> a -> Bool
> n
0 then Builder
"in " else Builder
""
suffix :: Builder
suffix = if Bool
fix Bool -> Bool -> Bool
&& n
ts forall a. Ord a => a -> a -> Bool
< n
0 then Builder
" ago" else Builder
""
toInt :: RealFrac n => n -> n -> Int
toInt :: RealFrac n => n -> n -> Int
toInt n
ts n
base = forall a. Num a => a -> a
abs (forall a b. (RealFrac a, Integral b) => a -> b
round (n
ts forall a. Fractional a => a -> a -> a
/ n
base))
intF :: Builder -> Int -> Builder
intF :: Builder -> Int -> Builder
intF Builder
t Int
n = forall p. Buildable p => p -> Builder
build Int
n forall a. Semigroup a => a -> a -> a
<> Builder
t
ranges :: RealFrac n => [(n, Int -> Builder, n)]
ranges :: RealFrac n => [(n, Int -> Builder, n)]
ranges =
[ (n
0 , Builder -> Int -> Builder
intF Builder
" milliseconds" , n
0.001 )
, (n
1 , Builder -> Int -> Builder
intF Builder
" seconds" , n
1 )
, (n
minute , forall a b. a -> b -> a
const Builder
"a minute" , n
0 )
, (n
minute forall a. Num a => a -> a -> a
* n
2 , Builder -> Int -> Builder
intF Builder
" minutes" , n
minute)
, (n
minute forall a. Num a => a -> a -> a
* n
30 , forall a b. a -> b -> a
const Builder
"half an hour" , n
0 )
, (n
minute forall a. Num a => a -> a -> a
* n
31 , Builder -> Int -> Builder
intF Builder
" minutes" , n
minute)
, (n
hour , forall a b. a -> b -> a
const Builder
"an hour" , n
0 )
, (n
hour forall a. Num a => a -> a -> a
* n
2 , Builder -> Int -> Builder
intF Builder
" hours" , n
hour )
, (n
hour forall a. Num a => a -> a -> a
* n
3 , forall a b. a -> b -> a
const Builder
"a few hours" , n
0 )
, (n
hour forall a. Num a => a -> a -> a
* n
4 , Builder -> Int -> Builder
intF Builder
" hours" , n
hour )
, (n
day , forall a b. a -> b -> a
const Builder
"a day" , n
0 )
, (n
day forall a. Num a => a -> a -> a
* n
2 , Builder -> Int -> Builder
intF Builder
" days" , n
day )
, (n
week , forall a b. a -> b -> a
const Builder
"a week" , n
0 )
, (n
week forall a. Num a => a -> a -> a
* n
2 , Builder -> Int -> Builder
intF Builder
" weeks" , n
week )
, (n
month , forall a b. a -> b -> a
const Builder
"a month" , n
0 )
, (n
month forall a. Num a => a -> a -> a
* n
2 , Builder -> Int -> Builder
intF Builder
" months" , n
month )
, (n
year , forall a b. a -> b -> a
const Builder
"a year" , n
0 )
, (n
year forall a. Num a => a -> a -> a
* n
2 , Builder -> Int -> Builder
intF Builder
" years" , n
year )
]
where year :: n
year = n
month forall a. Num a => a -> a -> a
* n
12
month :: n
month = n
day forall a. Num a => a -> a -> a
* n
30
week :: n
week = n
day forall a. Num a => a -> a -> a
* n
7
day :: n
day = n
hour forall a. Num a => a -> a -> a
* n
24
hour :: n
hour = n
minute forall a. Num a => a -> a -> a
* n
60
minute :: n
minute = n
60
yearsF :: RealFrac n
=> Int
-> n
-> Builder
yearsF :: forall n. RealFrac n => Int -> n -> Builder
yearsF Int
n = forall a. Real a => Int -> a -> Builder
fixedF Int
n forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => a -> a
abs forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a}. Fractional a => a -> a
count
where count :: a -> a
count a
x = a
x forall a. Fractional a => a -> a -> a
/ a
365 forall a. Fractional a => a -> a -> a
/ a
24 forall a. Fractional a => a -> a -> a
/ a
60 forall a. Fractional a => a -> a -> a
/ a
60
daysF :: RealFrac n
=> Int
-> n
-> Builder
daysF :: forall n. RealFrac n => Int -> n -> Builder
daysF Int
n = forall a. Real a => Int -> a -> Builder
fixedF Int
n forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => a -> a
abs forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a}. Fractional a => a -> a
count
where count :: a -> a
count a
x = a
x forall a. Fractional a => a -> a -> a
/ a
24 forall a. Fractional a => a -> a -> a
/ a
60 forall a. Fractional a => a -> a -> a
/ a
60
hoursF :: RealFrac n
=> Int
-> n
-> Builder
hoursF :: forall n. RealFrac n => Int -> n -> Builder
hoursF Int
n = forall a. Real a => Int -> a -> Builder
fixedF Int
n forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => a -> a
abs forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a}. Fractional a => a -> a
count
where count :: a -> a
count a
x = a
x forall a. Fractional a => a -> a -> a
/ a
60 forall a. Fractional a => a -> a -> a
/ a
60
minutesF :: RealFrac n
=> Int
-> n
-> Builder
minutesF :: forall n. RealFrac n => Int -> n -> Builder
minutesF Int
n = forall a. Real a => Int -> a -> Builder
fixedF Int
n forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => a -> a
abs forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a}. Fractional a => a -> a
count
where count :: a -> a
count a
x = a
x forall a. Fractional a => a -> a -> a
/ a
60
secondsF :: RealFrac n
=> Int
-> n
-> Builder
secondsF :: forall n. RealFrac n => Int -> n -> Builder
secondsF Int
n = forall a. Real a => Int -> a -> Builder
fixedF Int
n forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => a -> a
abs