Reputation: 137
So I am trying to learn Haskell, so I am sorry if this has already been asked, but I could not find a question that properly answered my doubts.
So my question is given UTCTime
what is the easiest and straightforward way of getting the following:
Also if there is convenient way of converting UTCTime
to some local time using just Asia/Tokyo
or similar strings.
I couldn't find a single library that gave all of these features and got confused and to be quite honest irritated that I need to convert between different types and use multiple libraries to achieve the above. Maybe I was not looking properly.
My effort so far:
import Data.Time
-- Difference between JST and UTC in seconds
-- JST is 9 hours ahead of UTC
utcJSTDiff :: Int
utcJSTDiff = 32400
getHour :: UTCTime -> Int
getHour time = todHour (timeToTimeOfDay (utctDayTime time))
getMinutes :: UTCTime -> Int
getMinutes time = todMin (timeToTimeOfDay (utctDayTime time))
isReminderHour :: Int -> Bool
isReminderHour hour
| hour == morningReminderHour || hour == eveningReminderHour = True
| otherwise = False
isReminderMins :: Int -> Bool
isReminderMins mins
| mins <= reminderMinuteLimit = True
| otherwise = False
timeforReminder :: UTCTime -> Bool
timeforReminder time
| isReminderHour (getHour time) && isReminderMins (getMinutes time) = True
| otherwise = False
utcToJST :: UTCTime -> UTCTime
utcToJST = addUTCTime (realToFrac utcJSTDiff)
main :: IO()
main = do
currentTime <- getCurrentTime
let jstTime = utcToJST currentTime
if timeforReminder jstTime
then action1
else action2
Upvotes: 4
Views: 1150
Reputation: 50864
Edit: Fixed to use timezone-olson
/ timezone-series
for correct timezone processing.
You should be able to do almost everything with the time
package, except that proper timezone processing will require timezone-olson
and timezone-series
packages on Linux systems; I'm not sure how to do it on Windows systems. Maybe someone else has a better way.
Here's the code:
module Time where
import Data.Time -- package "time"
import Data.Time.Calendar.WeekDate -- package "time"
import Data.Time.LocalTime.TimeZone.Olson -- package "timezone-olson"
import Data.Time.LocalTime.TimeZone.Series -- package "timezone-series"
-- |POSIX-specific timezone lookup
lookupTimeZone :: String -> IO TimeZoneSeries
lookupTimeZone tz =
getTimeZoneSeriesFromOlsonFile ("/usr/share/zoneinfo/" ++ tz)
data MyTime = MyTime
{ year :: Integer
, month :: Int
, week :: Int
, dayOfMonth :: Int
, dayOfWeek :: Int
, hour :: Int
, minutes :: Int
, seconds :: Int
} deriving (Show)
getMyTime :: TimeZoneSeries -> UTCTime -> MyTime
getMyTime tz t =
let LocalTime day (TimeOfDay hh mm ss) = utcToLocalTime' tz t
(yr, mn, dom) = toGregorian day
(_, wk, dow) = toWeekDate day
in MyTime yr mn wk dom dow hh mm (round ss)
main :: IO ()
main = do
currentTime <- getCurrentTime
-- Note: if you want time in local timezone, use:
-- tz <- getTimeZoneSeriesFromOlsonFile "/etc/localtime"
tz <- lookupTimeZone "Asia/Tokyo"
print $ getMyTime tz currentTime
A few cautionary notes:
lookupTimeZone
will throw an exception if it can't find the timezone file at /usr/share/zoneinfo/your/timezone
toWeekDate
to see exactly how that's defined.Data.Time.Format
(still in the time
package) to format them in the current (or some other) locale.Upvotes: 7