DEV Community

Prathamesh Sonpatki
Prathamesh Sonpatki

Posted on • Originally published at prathamesh.tech on

Converting Unix epoch timestamps to Ruby objects

While working on API integrations with third party services, I get timestamp of the event in the request payload.

{ 
"timestamp": "1583122008",
...
}
Enter fullscreen mode Exit fullscreen mode

Unix Time or Epoch Time

This timestamp is the number of seconds that have elapsed since the Unix epoch , that is the time 00:00:00 UTC on 1 January 1970, minus leap seconds. In Ruby, if we want to get unix time for current time, it is very easy.

>> Time.now.to_i
=> 1583122191

Enter fullscreen mode Exit fullscreen mode

But how to take his epoch time and convert it back to a Ruby Time object?

Thanks to jrochkind for helping me improve the wording of this paragraph.

Time::at to the rescue

Ruby has a handy method Time::at which can covert Unix epoch time back to a Time object.

>> ts = Time.now.to_i
=> 1583122280
>> Time.at(ts)
=> 2020-03-02 09:41:20 +0530
Enter fullscreen mode Exit fullscreen mode

It prints the time in local time zone, which is IST in my case. But Time::at also supports timezone argument as follows.

>> ts = Time.now.to_i
>> Time.at(ts, in: "+01:00")
=> 2020-03-02 05:13:24 +0100
>> Time.at(ts, in: "-02:00")
=> 2020-03-02 02:13:24 -0200
Enter fullscreen mode Exit fullscreen mode

The in keyword arguments accepts timezone offset in the form of +HH:MM or -HH:MM.

Time#at is provided by Ruby and not by Rails or Active Support.

Ruby's lack of documentation..

While looking at the solution to this parsing problem, I checked documentation of Time::at method on ruby-doc.org. I came across this:

If in argument is given, the result is in that timezone or UTC offset, or if a numeric argument is given, the result is in local time.

This led me down to Ruby's source code to understand what kind of arguments can be passed as in to Time::at. After checking the code, the in argument accepts following:

  • Timezone offset in the form of +HH:MM or -HH:MM.
>> ts = Time.now.to_i
>> Time.at(ts, in: "+01:00")
=> 2020-03-02 05:13:24 +0100
>> Time.at(ts, in: "-02:00")
=> 2020-03-02 02:13:24 -0200
Enter fullscreen mode Exit fullscreen mode
  • UTC string
>> Time.at(ts, in: "UTC")
=> 2020-03-02 04:13:24 UTC
Enter fullscreen mode Exit fullscreen mode
>> Time.at(ts, in: "E")
=> 2020-03-02 09:13:24 +0500
>> Time.at(ts, in: "Z")
=> 2020-03-02 04:13:24 UTC
Enter fullscreen mode Exit fullscreen mode

If we pass anything else, we get an error message.

>> Time.at(ts, in: "IST")
Traceback (most recent call last):
        2: from (irb):12
        1: from (irb):12:in `at'
ArgumentError ("+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset)
Enter fullscreen mode Exit fullscreen mode

This error message is from Ruby 2.7. In Ruby 2.6, the error message did not mention about military timezones. It only talked about UTC offset.

I opened a pull request to improve the documentation of Time::at and it got merged quickly. The documentation of Time::at will have all possible combinations for the in argument in the next release of Ruby 👏🏻

Top comments (0)