packages feed

hquantlib-time-0.0.5.2: src/QuantLib/Time/Date.hs

module QuantLib.Time.Date
  ( module QuantLib.Time.Date,
    DayOfWeek (..),
  )
where

import Data.Time.Calendar (Day (..), DayOfWeek (..), addDays, toGregorian)
import Data.Time.Calendar.WeekDate (toWeekDate)

-- | Business Day conventions
-- - These conventions specify the algorithm used to adjust a date in case it is not a valid business day.
data BusinessDayConvention
  = Following
  | ModifiedFollowing
  | Preceding
  | ModifiedPreceding
  | Unadjusted
  deriving (Show, Eq, Enum)

-- -- | Week days
-- data WeekDay = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday
--         deriving (Show, Eq, Enum)

-- | Date
type Date = Day

-- | Defines a holidays for given calendar. Corresponds to calendar class in QuantLib
class Holiday m where
  isHoliday :: m -> (Integer, Int, Int) -> Bool

  isBusinessDay :: m -> Date -> Bool
  isBusinessDay m d = not (isHoliday m $ toGregorian d)

  hBusinessDayBetween :: m -> (Date, Date) -> Int
  hBusinessDayBetween m (fd, td) = foldl countDays 0 listOfDates
    where
      countDays counter x = counter + fromEnum (isBusinessDay m x)
      listOfDates = getDaysBetween (fd, td)

-- | Gets a week day
getWeekDay :: Date -> DayOfWeek
getWeekDay d = toEnum (weekDay - 1)
  where
    (_, _, weekDay) = toWeekDate d

-- | Generate a list of all dates inbetween
getDaysBetween :: (Day, Day) -> [Day]
getDaysBetween (fd, td) = reverse $ generator fd []
  where
    generator date x
      | date < td = generator nextDate (nextDate : x)
      | otherwise = x
      where
        nextDate = addDays 1 date

-- | Checks if the day is a weekend, i.e. Saturday or Sunday
isWeekEnd :: Date -> Bool
isWeekEnd d = (weekday == Saturday) || (weekday == Sunday)
  where
    weekday = getWeekDay d

-- | Gets the next working day
getNextBusinessDay :: Holiday a => a -> Date -> Date
getNextBusinessDay m d
  | isBusinessDay m nextDay = nextDay
  | otherwise = getNextBusinessDay m nextDay
  where
    nextDay = addDays 1 d