Haskell’s date packages are a huge step back from Apple’s NSDate, but workable. I’m writing a module for setting reminders at various times in the future (minutes, hours, days, weeks from now, this evening, tomorrow morning, etc).

For intervals less than a day, using addUTCTime makes the most sense:

addMinutes :: Int -> UTCTime -> UTCTime

addMinutes count now = addUTCTime (fromIntegral $ n) now

addHours count = addMinutes (count * 60)

For adding days, I’m pretty sure it’s best to convert to a LocalTime, addDays, then convert back to UTCTime. The documentation is littered with warnings that nothing takes DST into account, so this may end up being equivalent to adding multiples of 86400, but it still feels more appropriate to do it this way:

mapLocalTime :: (LocalTime -> LocalTime) -> TimeZone -> UTCTime -> UTCTime

mapLocalTime f timeZone = localTimeToUTC timeZone . f . utcToLocalTime timeZone

addDays’ count = mapLocalTime (\(LocalTime d t) -> LocalTime (addDays count d) t)

(I have a feeling a lens library could make that a bit less gruesome, but I haven’t gotten around to learning one yet.)