{-# LANGUAGE OverloadedStrings #-} module Birthdate ( Birthdate(..) , fullname , age , readBirthdates , filterBirthday ) where import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.IO as T import qualified Data.Text.Read as T import Data.Either (partitionEithers) import Date (Date(Date), sameDayAndMonth, yearsGap) data Birthdate = Birthdate { date :: Date , lastname :: Text , firstname :: Text } deriving (Eq, Show) fullname :: Birthdate -> Text fullname d = T.concat [firstname d, " ", lastname d] age :: Date -> Birthdate -> Int age currentDate birthdate = yearsGap currentDate (date birthdate) readBirthdates :: FilePath -> IO (Either Text [Birthdate]) readBirthdates path = do eitherBirthdates <- map parseBirthdate . zip [1..] . T.lines <$> T.readFile path return $ case partitionEithers eitherBirthdates of ([], birthdates) -> Right birthdates (errors, _) -> Left $ T.intercalate "\n" errors parseBirthdate :: (Int, Text) -> Either Text Birthdate parseBirthdate (line, text) = case map T.strip $ T.splitOn "," text of [date, lastname, firstname] -> case map T.decimal $ T.splitOn "/" date of [Right (day, ""), Right (month, ""), Right (year, "")] -> Right Birthdate { date = Date year month day , lastname = lastname , firstname = firstname } _ -> Left $ T.concat [ lineOutput line , " birthdate: " , date , ". (Required: year/month/day)" ] _ -> Left $ T.concat [ lineOutput line , " line: " , text , ". (Required: date, lastname, firstname)" ] lineOutput :: Int -> Text lineOutput line = T.concat [ "[L" , T.pack . show $ line , "]" ] filterBirthday :: Date -> [Birthdate] -> [Birthdate] filterBirthday d = filter (sameDayAndMonth d . date)