module Diddo ( LogEntry(LogEntry) , DiddoEntry(DiddoEntry) , parseDiddoLogline , formatDiddoEntry , timestamp , logToDiddoEntry ) where import Data.DateTime( diffSeconds ) import Data.Maybe( fromMaybe ) import Data.Time.Clock( UTCTime(), NominalDiffTime(), diffUTCTime ) import Data.Time.Format( parseTime, formatTime ) import Data.Time.LocalTime( TimeZone() ) import Data.Time.LocalTime( ZonedTime(..), zonedTimeToUTC, utcToZonedTime ) import System.Locale import qualified Data.Text as T data LogEntry = LogEntry { timestamp :: UTCTime , timezone :: TimeZone , text :: T.Text } data DiddoEntry = DiddoEntry { startTime :: ZonedTime , endTime :: ZonedTime , comment :: T.Text } formatDiddoEntry :: String -> DiddoEntry -> T.Text formatDiddoEntry format entry = T.intercalate (T.pack ";") [ T.pack $ formatTime defaultTimeLocale format (startTime entry) , T.pack $ formatTime defaultTimeLocale format (endTime entry) , T.pack $ diffTimeToHMSString $ diffUTCTime (zonedTimeToUTC (endTime entry)) (zonedTimeToUTC (startTime entry)) , comment entry ] logToDiddoEntry :: UTCTime -> LogEntry -> DiddoEntry logToDiddoEntry startutc logentry = DiddoEntry startZoned endZoned $ text logentry where startZoned = utcToZonedTime (timezone logentry) startutc endZoned = utcToZonedTime (timezone logentry) $ timestamp logentry parseDiddoLogline :: T.Text -> LogEntry parseDiddoLogline line = LogEntry ts tz string where splitLine = T.splitOn (T.pack ";") line string = T.intercalate (T.pack ";") $ tail splitLine time = parseISOsecondsTime $ head splitLine (ts,tz) = (zonedTimeToUTC time, zonedTimeZone time) parseToZonedTime :: String -> String -> ZonedTime parseToZonedTime format string = fromMaybe (error $ "Input data broken: " ++ string) $ parseTime defaultTimeLocale format string parseISOsecondsTime :: T.Text -> ZonedTime parseISOsecondsTime timestring = parseToZonedTime (iso8601DateFormat $ Just "%T%z") $ T.unpack timestring diffTimeToHMSString :: NominalDiffTime -> String diffTimeToHMSString delta = printf "%d:%02d:%02d" h m s where (mLeft, s) = floor delta `divMod` 60 :: (Int, Int) (h, m) = mLeft `divMod` 60