Converting Unix epoch timestamps to Ruby objects
Tags: ruby, tips, timestamps
Published: 2020-03-03 10:54:17

---
title: Converting Unix epoch timestamps to Ruby objects
published: true
date: 2020-03-02 04:29:32 UTC
tags: ruby,tips,timestamps
canonical_url: https://prathamesh.tech/2020/03/02/converting-timestamps-to-ruby-objects/
---

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

```yaml
{ 
"timestamp": "1583122008",
...
}
```

### 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.

```rb
>> Time.now.to_i
=> 1583122191

```

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

> Thanks to [jrochkind](https://www.reddit.com/user/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.

```rb
>> ts = Time.now.to_i
=> 1583122280
>> Time.at(ts)
=> 2020-03-02 09:41:20 +0530
```

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

```rb
>> 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
```

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.

```rb
>> 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
```
- UTC string

```rb
>> Time.at(ts, in: "UTC")
=> 2020-03-02 04:13:24 UTC
```

- [Military timezones](https://militarybenefits.info/military-time/) such as "A", "B", "C".

```rb
>> Time.at(ts, in: "E")
=> 2020-03-02 09:13:24 +0500
>> Time.at(ts, in: "Z")
=> 2020-03-02 04:13:24 UTC
```

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

```rb
>> 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)
```

> 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](https://github.com/ruby/ruby/pull/2929) 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 👏🏻