{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Data.Tax.ATO.FY
( Days
, days
, daysAll
, daysNone
, getDays
, getFraction
, FinancialYear
, financialYear
, financialYearRange
, financialYearRangeFromProxy
)
where
import GHC.TypeLits
import Data.Proxy
import Data.Ratio ((%))
import Data.Time.Calendar (Day, Year, fromGregorian, isLeapYear, toGregorian)
type FinancialYear = KnownNat
daysInYear :: KnownNat n => Proxy n -> Integer
daysInYear :: forall (n :: Nat). KnownNat n => Proxy n -> Year
daysInYear Proxy n
proxy
| Year -> Bool
isLeapYear (Proxy n -> Year
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Year
natVal Proxy n
proxy) = Year
366
| Bool
otherwise = Year
365
newtype Days (n :: Nat) = Days
{ forall (n :: Nat). Days n -> Year
getDays :: Integer
}
deriving (MonthOfYear -> Days n -> ShowS
[Days n] -> ShowS
Days n -> String
(MonthOfYear -> Days n -> ShowS)
-> (Days n -> String) -> ([Days n] -> ShowS) -> Show (Days n)
forall (n :: Nat). MonthOfYear -> Days n -> ShowS
forall (n :: Nat). [Days n] -> ShowS
forall (n :: Nat). Days n -> String
forall a.
(MonthOfYear -> a -> ShowS)
-> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall (n :: Nat). MonthOfYear -> Days n -> ShowS
showsPrec :: MonthOfYear -> Days n -> ShowS
$cshow :: forall (n :: Nat). Days n -> String
show :: Days n -> String
$cshowList :: forall (n :: Nat). [Days n] -> ShowS
showList :: [Days n] -> ShowS
Show)
days :: forall a. (FinancialYear a) => Integer -> Days a
days :: forall (a :: Nat). FinancialYear a => Year -> Days a
days = Year -> Days a
forall (n :: Nat). Year -> Days n
Days (Year -> Days a) -> (Year -> Year) -> Year -> Days a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Year -> Year -> Year
forall a. Ord a => a -> a -> a
max Year
0 (Year -> Year) -> (Year -> Year) -> Year -> Year
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Year -> Year -> Year
forall a. Ord a => a -> a -> a
min (Proxy a -> Year
forall (n :: Nat). KnownNat n => Proxy n -> Year
daysInYear (Proxy a
forall {k} (t :: k). Proxy t
Proxy :: Proxy a))
daysAll :: forall a. (FinancialYear a) => Days a
daysAll :: forall (a :: Nat). FinancialYear a => Days a
daysAll = Year -> Days a
forall (n :: Nat). Year -> Days n
Days (Proxy a -> Year
forall (n :: Nat). KnownNat n => Proxy n -> Year
daysInYear (Proxy a
forall {k} (t :: k). Proxy t
Proxy :: Proxy a))
daysNone :: Days a
daysNone :: forall (a :: Nat). Days a
daysNone = Year -> Days a
forall (n :: Nat). Year -> Days n
Days Year
0
getFraction :: forall a frac. (FinancialYear a, Fractional frac) => Days a -> frac
getFraction :: forall (a :: Nat) frac.
(FinancialYear a, Fractional frac) =>
Days a -> frac
getFraction Days a
n = Rational -> frac
forall a. Fractional a => Rational -> a
fromRational (Rational -> frac) -> Rational -> frac
forall a b. (a -> b) -> a -> b
$ Days a -> Year
forall (n :: Nat). Days n -> Year
getDays Days a
n Year -> Year -> Rational
forall a. Integral a => a -> a -> Ratio a
% Proxy a -> Year
forall (n :: Nat). KnownNat n => Proxy n -> Year
daysInYear (Proxy a
forall {k} (t :: k). Proxy t
Proxy :: Proxy a)
financialYear :: Day -> Year
financialYear :: Day -> Year
financialYear Day
d = case Day -> (Year, MonthOfYear, MonthOfYear)
toGregorian Day
d of
(Year
y, MonthOfYear
m, MonthOfYear
_)
| MonthOfYear
m MonthOfYear -> MonthOfYear -> Bool
forall a. Ord a => a -> a -> Bool
>= MonthOfYear
7 -> Year
y Year -> Year -> Year
forall a. Num a => a -> a -> a
+ Year
1
| Bool
otherwise -> Year
y
financialYearRange :: Year -> (Day, Day)
financialYearRange :: Year -> (Day, Day)
financialYearRange Year
y =
( Year -> MonthOfYear -> MonthOfYear -> Day
fromGregorian (Year
y Year -> Year -> Year
forall a. Num a => a -> a -> a
- Year
1) MonthOfYear
7 MonthOfYear
1
, Year -> MonthOfYear -> MonthOfYear -> Day
fromGregorian Year
y MonthOfYear
6 MonthOfYear
30
)
financialYearRangeFromProxy :: forall n. (FinancialYear n) => Proxy n -> (Day, Day)
financialYearRangeFromProxy :: forall (n :: Nat). FinancialYear n => Proxy n -> (Day, Day)
financialYearRangeFromProxy Proxy n
proxy = Year -> (Day, Day)
financialYearRange (Proxy n -> Year
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Year
natVal Proxy n
proxy)