{-|
Module      : Util
Description : Collections of utility functions.
Copyright   : (c) IOcrafts, 2024-present
License     : BSD
Maintainer  : Maurizio Dusi
Stability   : stable
Portability : POSIX

This module provides utility functions for file, date and time manipulation.

-}


module Util
    ( createFile
    , toDate
    , toEpoch
    ) where

import           Control.Monad    ( unless )

import           Data.Time

import           System.Directory ( doesFileExist )

{-|
  Convert a string to seconds since Epoch.
  The input string should be in the format %F %R %Z (YYYY-MM-DD HH-mm and abbreviated time zone name).
  If the parsing fails, it defaults to the beginning of Epoch (i.e., zero).

  Example usage:

  >>> toDate "2022-01-01 12:00 UTC"
  2022-01-01 12:00:00 UTC
-}
toDate :: String -> UTCTime
toDate :: String -> UTCTime
toDate String
d =  case Bool -> TimeLocale -> String -> String -> Maybe UTCTime
forall (m :: * -> *) t.
(MonadFail m, ParseTime t) =>
Bool -> TimeLocale -> String -> String -> m t
parseTimeM Bool
True TimeLocale
defaultTimeLocale String
"%F %R %Z" String
d of
              Just UTCTime
x -> UTCTime
x
              Maybe UTCTime
Nothing -> Day -> DiffTime -> UTCTime
UTCTime (Integer -> MonthOfYear -> MonthOfYear -> Day
fromGregorian Integer
1970 MonthOfYear
01 MonthOfYear
01) (Integer -> DiffTime
secondsToDiffTime Integer
0)

{-|
  Convert a 'UTCTime' value to seconds since Epoch.

  Example usage:

   >>> toEpoch (UTCTime (fromGregorian 2022 01 01) (secondsToDiffTime 0))
  1640995200
-}
toEpoch :: UTCTime -> Integer
toEpoch :: UTCTime -> Integer
toEpoch UTCTime
d = String -> Integer
forall a. Read a => String -> a
read (String -> Integer) -> String -> Integer
forall a b. (a -> b) -> a -> b
$ TimeLocale -> String -> UTCTime -> String
forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale String
"%s" UTCTime
d

{-|
  Create a file if it does not exist.

  Example usage:

  >>> createFile "test.txt"
-}
createFile :: FilePath -> IO ()
createFile :: String -> IO ()
createFile String
cfile = do
  Bool
fileExists <- String -> IO Bool
doesFileExist String
cfile
  Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
fileExists (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> String -> IO ()
writeFile String
cfile String
""