0

I get a number representing date from a back-end, and I'm trying to convert it to a date this way:

number = item["created"].to_i
number #=> 1512387277084
DateTime.strptime(number.to_s ,'%s') #=> 49895-08-24T08:58:04+00:00
Time.at(number).utc #=> 49895-08-24 08:58:04 UTC
Time.at(number) #=> 49895-08-24 11:58:04 +0300

But this is a wrong result.

If I use Epoch & Unix Timestamp Conversion Tools, I get this result:

1512387277084
Assuming that this timestamp is in milliseconds:
GMT: Monday, December 4, 2017 11:34:37.084 AM
Your time zone: Monday, December 4, 2017 2:34:37.084 PM GMT+03:00

Time.at(number) doesn't work.

How to convert it correctly?

2 Answers 2

4
DateTime.strptime('1512387277084', '%Q')
#⇒ #<DateTime: 2017-12-04T11:34:37+00:00
#       ((2458092j,41677s,84000000n),+0s,2299161j)>

DateTime formatting.

0
1

According to the ruby documentation takes the at method, of the Time class, as argument "the number of seconds" since the Epoch not the "milliseconds" since the Epoch. Another variant takes as arguments the "seconds" since the Epoch and "Microseconds with frac".

You need to convert number (the input) from ms to sec and us to get the expected / correct result.

Examples

Wrong (ms interpeted as seconds):

> number = 1512387277084 # ms since epoch
=> 1512387277084
> Time.at(number)
=> 49895-08-24 10:58:04 +0200

Seconds with fractal:

> number2 = number / 1000.0
=> 1512387277.084
> Time.at(number2)
=> 2017-12-04 12:34:37 +0100
> Time.at(number2).usec
=> 84000
> Time.at(number2).nsec
=> 84000110 # Wrong of by 110 ns 

> Time.at(number2.round(3)).nsec
=> 84000110 # Wrong of by 110 ns
> Time.at(number2.round(2)).usec
=> 79999 # Wrong
> Time.at(number2.round(2)).nsec
=> 79999923 # Wrong

Seconds only:

> number3 = number / 1000
=> 1512387277
> Time.at(number3)
=> 2017-12-04 12:34:37 +0100
> Time.at(number3).usec
=> 0 # Wrong
> Time.at(number3).nsec
=> 0 # Wrong

Seconds and Microseconds:

ms = number % 1000 # Milliseconds
=> 84
> us = ms * 1000 # Microseconds
=> 84000
> Time.at(number3, us)
=> 2017-12-04 12:34:37 +0100
> Time.at(number3, us).usec
=> 84000 # OK
> Time.at(number3, us).nsec
=> 84000000 # OK
> Time.at(number3, us).to_f
=> 1512387277.084 # OK

Update 2

Seconds as Rational

> number4 = number.quo(1000)
=> (378096819271/250)
> Time.at(number4)
=> 2017-12-04 12:34:37 +0100
> Time.at(number4).usec
=> 84000 # OK
> Time.at(number4).nsec
=> 84000000 # OK
> Time.at(number4).to_f
=> 1512387277.084 # OK
3
  • You do have to divide number by 1000 in order to use Time.at, but using floating point division will not give the correct result: Time.at(number2).nsec returns 84000110. The correct result would be 84000000 – yours is 110 nanoseconds off.
    – Stefan
    Commented Dec 6, 2017 at 15:07
  • @Stefan updated my answer to take your input into account. Thx. Commented Dec 6, 2017 at 20:37
  • 1
    Doesn't have to be that complicated: Time.at(number.quo(1000))
    – Stefan
    Commented Dec 6, 2017 at 21:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.