import Control.Applicative( (<$>), (<*>) ) import Data.DateTime( DateTime(..), parseDateTime, formatDateTime, startOfTime, diffSeconds ) import Data.List.Split( splitOn ) import Data.List( zipWith4, transpose ) import Data.Maybe( fromJust, fromMaybe ) import Data.Monoid( mempty ) import Data.Time.Clock( secondsToDiffTime ) import Data.Time.Format( parseTime, formatTime ) import Data.Time.LocalTime( LocalTime(..), ZonedTime(..), zonedTimeToUTC, midnight, localDay ) import Diddo.Entry( DiddoEntry(..) ) import HMSTime( HMSTime(..), secondsToHMS ) import Options.Applicative( execParser, info, strOption, long, help, helper, briefDesc, fullDesc, progDesc, header, (<>) ) import System.Environment( getArgs ) import System.Locale data DiddoOpts = DiddoOpts { inDateFmt :: String , inFile :: String } parseToZonedTime :: String -> String -> ZonedTime parseToZonedTime format = fromMaybe (error "Input data broken.") . parseTime defaultTimeLocale format parseISOsecondsTime :: String -> ZonedTime parseISOsecondsTime = parseToZonedTime $ iso8601DateFormat $ Just "%T%z" parseRFC822Time :: String -> ZonedTime parseRFC822Time = parseToZonedTime rfc822DateFormat formatZonedTime :: String -> ZonedTime -> String formatZonedTime format = formatTime defaultTimeLocale format zonedTimesDeltas :: ZonedTime -> [ZonedTime] -> [Integer] zonedTimesDeltas startTime timestamps = let startTimeUTC = zonedTimeToUTC startTime relevantTimestamps = dropWhile (< startTimeUTC) $ map zonedTimeToUTC timestamps in zipWith diffSeconds relevantTimestamps $ startTimeUTC : init relevantTimestamps startOfZonedDay :: ZonedTime -> ZonedTime startOfZonedDay time = ZonedTime (LocalTime day midnight) $ zonedTimeZone time where day = localDay $ zonedTimeToLocalTime time mainWithOpts :: DiddoOpts -> IO () mainWithOpts opts = do [ timeStamps , entryText ] <- transpose . map (splitOn ";") . lines <$> readFile (inFile opts) let parseCustomTime = parseToZonedTime $ inDateFmt opts -- parsedTimes = map (parseToZonedTime $ inDateFmt opts) timeStamps parsedTimes = map parseCustomTime timeStamps deltasHMS = map secondsToHMS $ zonedTimesDeltas (startOfZonedDay $ head parsedTimes) parsedTimes diddos_summarized = zipWith4 DiddoEntry ((formatZonedTime (inDateFmt opts) $ startOfZonedDay $ head parsedTimes) : init timeStamps) timeStamps deltasHMS entryText mapM_ print diddos_summarized main :: IO () main = execParser opts >>= mainWithOpts where opts = info (helper <*> parser) ( header "diddohs - A Time/Task Tracker" <> progDesc "Diddoh Desc" -- <> briefDesc <> fullDesc ) parser = DiddoOpts <$> strOption ( long "indateform" <> help "Input date format, see date(1)" ) <*> strOption ( long "infile" )