I've tried several things I could find online to print the current time as an ISO8601 string, but none of them have worked:
This SO answer assumes you already know how to get the current time, but I can't figure that out.
I keep on getting an error
Could not find module ‘System.Locale’
because it seems likeSystem.Locale
is deprecated/not installed by default anymore?I tried installing
old-local
but that just gave me new errors, I think caused by incompatibilities betweentime
andold-locale
:• Couldn't match expected type ‘time-1.9.3:Data.Time.Format.Locale.TimeLocale’ with actual type ‘System.Locale.TimeLocale’ NB: ‘time-1.9.3:Data.Time.Format.Locale.TimeLocale’ is defined in ‘Data.Time.Format.Locale’ in package ‘time-1.9.3’ ‘System.Locale.TimeLocale’ is defined in ‘System.Locale’ in package ‘old-locale-1.0.0.7’ • In the first argument of ‘formatTime’, namely ‘defaultTimeLocale’ In the expression: formatTime defaultTimeLocale "%FT%T%QZ" In an equation for ‘iso8601’: iso8601 = formatTime defaultTimeLocale "%FT%T%QZ" | 49 | iso8601 = formatTime defaultTimeLocale "%FT%T%QZ" | ^^^^^^^^^^^^^^^^^
This wiki page gets the current time, but doesn't format it as ISO8601.
this blog post seems really good, but only has one section on formatting which is actually the same as 1.:
Prelude Data.Time> formatTime defaultTimeLocale "%T, %F (%Z)" myTime
What I want, is to be able to call a function have it print out the current time as an ISO8601 string. I'm guessing this will have to actually be an IO action since it's not a strict function.
CodePudding user response:
I think I figured it out. Note that Haskell has funky string formatting time specifications
%F
== year-month-day%T
== hour:minute:second%Q
== .up_to_12_decimals_for_fraction_of_a_second
import Data.Time.Format (defaultTimeLocale, formatTime)
import Data.Time.Clock
getCurrentTimeAsISO8601 :: IO String
getCurrentTimeAsISO8601 = do
t <- getCurrentTime
let val = formatTime defaultTimeLocale "%F %T%Q" t
-- Take the first 23 characters so we don't get the microseconds
return $ take 23 val
main = do
time <- getCurrentTimeAsISO8601
putStrLn time
You can use the online ghci
here to copy-paste the code and it should all work.
CodePudding user response:
You can slighly improve this by performing a functor mapping:
import Data.Time.Format (defaultTimeLocale, formatTime)
import Data.Time.Clock(getCurrentTime)
getCurrentTimeAsISO8601 :: IO String
getCurrentTimeAsISO8601 = take 23 . formatTime defaultTimeLocale "%F %T%Q" <$> getCurrentTime
CodePudding user response:
The show
instance for UTC is what you want. Therefore you can just use show.
getCurrentTimeASISO8601 :: IO String
getCurrentTimeASISO8601 = fmap (take 23 . show) getCurrentTime
Just a note: Up to my best knowledge ISO8601 isn't yyyy-MM-dd hh:mm:ss
but yyyy-MM-ddThh:mm:ss
. So if you are implementing this based on the standard, check it twice.
CodePudding user response:
I wonder if something from the time package’s Data.Time.Format.ISO8601 module might help? The iso8601Show
function turns a UTCTime into a ISO8601 formatted string.
import Data.Time (getCurrentTime)
import Data.Time.Format.ISO8601 (iso8601Show)
main :: IO ()
main = do
now <- getCurrentTime
putStrLn (iso8601Show now)