27

Is there a function in haskell for epoch time in seconds / milliseconds ?

perhaps something similar to java's

System.currentTimeMillis();

edit: as Int or Integer?

Chris Stryczynski
  • 30,145
  • 48
  • 175
  • 286
jajdoo
  • 516
  • 1
  • 9
  • 21

6 Answers6

36

Yes.

getCurrentTime :: IO UTCTime.

UNIX epoch time could be retrieved as Int like that:

> :m + Data.Time System.Locale Control.Applicative
> epoch_int <- (read <$> formatTime defaultTimeLocale "%s" <$> getCurrentTime) :: IO Int
> epoch_int
1375025861

UPD: as other users noticed, there is much more simple way to do that:

> :m + Data.Time.Clock.POSIX
> round `fmap` getPOSIXTime 
1375040716
it :: Integer
5

Try this:

import Data.Time
import Data.Time.Clock.POSIX

t = getPOSIXTime

It has 6 decimal places of accuracy.

Blue Ice
  • 7,888
  • 6
  • 32
  • 52
4

How about:

import Data.Time.Clock.POSIX (getPOSIXTime)

timeNanos, timeMicros, timeMillis :: IO Integer

t mul = round . (mul *) <$> getPOSIXTime
timeNanos  = t 1000000000
timeMicros = t 1000000
timeMillis = t 1000

main = do
  tNanos  <- timeNanos
  tMicros <- timeMicros
  tMillis <- timeMillis

  print tNanos
  print tMicros
  print tMillis

-- OUT:
-- 1539161680010615122
-- 1539161680010617
-- 1539161680011
Erik Kaplun
  • 37,128
  • 15
  • 99
  • 111
  • 2
    This is incredibly wrong! If you run `timeInMicros` a couple times in ghci, you'll immediately see that returns almost random output! One moment it's `1538705499660488167`, shortly after it's `769352750056244969` which is half the size. You cannot make a `Rational` and then just keep the `numerator` - that's like saying something takes `5/365` years, so it's 5 years! – nh2 Oct 05 '18 at 02:16
  • (I got the above results using `time-1.8.0.2`.) – nh2 Oct 05 '18 at 02:16
  • 2
    The idea was to take the `numerator` of smth that is always `n % 1`, however, back when I wrote this snippet, `getPOSIXTime` returned `seconds.micros`, but now it returns `seconds.nanos`. Anyway, there are probably better ways to do this. For the time being, I've just used `round` instead of `numerator . toRational`. – Erik Kaplun Oct 10 '18 at 08:13
2

There is also the solution discussed in Real World Haskell:

import System.Time
getClockTime >>= (\(TOD sec _) -> return sec)
qpfiffer
  • 121
  • 1
  • 5
2
import Data.Time.Clock.POSIX

f :: Integral b => IO b
f = getCurrentTime >>= pure . (1000*) . utcTimeToPOSIXSeconds >>= pure . round

Round is to get integer which is not actually mandatory...

original answer was without (1000*) - now is fixed

Chris Stryczynski
  • 30,145
  • 48
  • 175
  • 286
RandomB
  • 3,367
  • 19
  • 30
  • **From review queue:** May I request you to please add some more context around your answer. Code-only answers are difficult to understand. It will help the asker and future readers both if you can add more information in your post. – help-info.de May 19 '17 at 17:53
  • Execuse me, for so short (and actually not totally right) answer. As for me, I do it in this manner: `getCurrentTime >>= pure . (1000*) . utcTimeToPOSIXSeconds >>= pure . round`. Both funcs are in Data.Time.Clock.POSIX. This (running in GHCi) returns milliseconds of current time – RandomB May 21 '17 at 05:23
  • @Paul-AG should it not be without the `1000*` (for seconds)? – Chris Stryczynski Aug 14 '20 at 18:05
-10

This works:

import System.IO.Unsafe
import Data.Time.Clock.POSIX

time = round (unsafePerformIO getPOSIXTime) :: Int

unsafePerformIO extracts time from the IO monad. Rounding to Int then yields the desired result.

UPDATE: In my Haskell web applications, I sometimes use unsafePerformIO to populate HTML checkbox and radio button forms with random numbers and hidden time stamps. Sometimes my text field and textbox forms allow users (players of interactive games) to provide data such as arbitrary numbers and dates. Justin, I trust that you don't think the user-supplied values are safer than the random numbers and time stamps I supply to the forms? And I hope you don't think I meant to imply, "Use things like unsafePerformIO if you don't understand what you're doing."

Web browsers use HTML, CSS and Javascript. You can't "keep it in the IO monad", and the browsers don't perform more or less safely depending on how the values they receive came out of Haskell monads.

Justin, for the benefit of everyone who reads this page, I ask you to reconsider and say if you still think I "really shouldn't be using unsafePerformIO this way"? My mind is open. I just don't have a clue as to what, if anything, I might be doing wrong in my work, or why readers should be discouraged from learning from me by the two down votes.

P.S. I've heard that one shouldn't say #@!% in front of the children, or in mixed company. Did I publish the "U" word where newbies might see it? Heaven forbid! -DS

David Schalk
  • 110
  • 4
  • 6
    You really shouldn't be using `unsafePerformIO` this way. It's mostly useful for calling functions that you know are pure using FFI. See [this SO thread for more info](http://stackoverflow.com/questions/19371636/am-i-abusing-unsafeperformio). If you're doing IO, keep it in the IO monad and your program will be safer to use and extend. Only use things like `unsafePerformIO` if you really understand what you're doing. – Justin Leitgeb Sep 26 '14 at 00:46
  • My comment is in the update, above. It wouldn't fit here – David Schalk Nov 07 '14 at 00:36
  • 7
    These are just crazy ways to use `unsafePerformIO`. Broadly speaking, you shouldn't use `unsafePerformIO` to perform that sort of IO. Yes, it's fine (in my book) to use it to grab some random numbers for a Las Vegas algorithm like Quickselect (but not for a Monte Carlo one), and it's fine to use it to allow a concurrent algorithm to implement a pure function (although I'm pretty sure there are higher-level functions to do that a little more nicely, though still dangerously), and it's certainly fine for (pure) FFI stuff, but these are not the sorts of things you're doing. – dfeuer Nov 07 '14 at 03:23