+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 = formatTime defaultTimeLocale
+
+utcTimesDeltas :: ZonedTime -> [UTCTime] -> [Integer]
+utcTimesDeltas startTime timestamps =
+ let
+ startTimeUTC = zonedTimeToUTC startTime
+ relevantTimestamps = dropWhile (< startTimeUTC) timestamps
+ in
+ zipWith diffSeconds relevantTimestamps $ startTimeUTC : init relevantTimestamps
+
+startOfDay :: ZonedTime -> ZonedTime
+startOfDay time = ZonedTime (LocalTime day midnight) $ zonedTimeZone time
+ where
+ day = localDay $ zonedTimeToLocalTime time
+
+parseToUTCFromZonedString :: String -> String -> UTCTime
+parseToUTCFromZonedString fmt time = zonedTimeToUTC $ parseToZonedTime fmt time
+
+splitToMapOn :: String -> [String] -> Map.Map String [String]
+splitToMapOn sep lines = Map.fromList $ map (listToTuple . splitOn sep) lines
+ where listToTuple (x:xs) = (x, xs)
+
+logLinesToDiddohs :: String -> [String] -> [DiddoEntry]
+logLinesToDiddohs inDateFmt logLines =
+ let
+ loglineMap = splitToMapOn ";" logLines
+ zonedtimeEntryMap = Map.mapKeysMonotonic (parseToZonedTime inDateFmt) loglineMap
+ utctimeEntryMap = Map.mapKeys zonedTimeToUTC zonedtimeEntryMap
+
+ timeStamps = Map.keys loglineMap
+ entryTexts = map head $ Map.elems loglineMap
+ parsedTimes = Map.keys zonedtimeEntryMap
+
+ deltasHMS = map secondsToHMS $ utcTimesDeltas (startOfDay $ head parsedTimes) $ Map.keys utctimeEntryMap
+ in
+ zipWith4 DiddoEntry (formatZonedTime inDateFmt (startOfDay $ head parsedTimes) : init timeStamps)
+ timeStamps deltasHMS entryTexts
+
+readFilesToLines :: [String] -> IO [String]
+readFilesToLines filenames = lines . concat <$> mapM readFile filenames