Sean Moubry
Sean Moubry

Reputation: 1057

How to automatically convert JSON time strings into Time objects with Ruby?

When I’m using Ruby to consume a web service API that returns time strings in JSON, I want them automatically converted into Time objects (or DateTime objects) so that I don’t have do it manually myself.

For example, I want this to output Time instead of String:

irb(main):001:0> require 'json'
=> true
irb(main):002:0> payload = JSON.generate({ now: Time.now })
=> "{\"now\":\"2018-04-02 13:15:56 -0500\"}"
irb(main):003:0> JSON.parse(payload)['now'].class
=> String

I understand that times are not part of the JSON spec. I’m just wondering if there’s a way to configure Ruby’s stdlib JSON parser to automatically parse dates, or if there’s a library that does this for you.

Upvotes: 2

Views: 2437

Answers (1)

Sean Moubry
Sean Moubry

Reputation: 1057

Active Support can automatically convert ISO 8601 formatted times into ActiveSupport::TimeWithZone objects when you set ActiveSupport.parse_json_times = true.

http://api.rubyonrails.org/classes/ActiveSupport/JSON.html

#!/usr/bin/env ruby

require 'active_support/json'
require 'active_support/time'

Time.zone = 'UTC'
ActiveSupport.parse_json_times = true

puts payload1 = JSON.generate({ now: Time.now })
puts payload2 = ActiveSupport::JSON.encode({ now: Time.now })

puts ActiveSupport::JSON.decode(payload1)['now'].class
puts ActiveSupport::JSON.decode(payload2)['now'].class

Which will output:

{"now":"2018-04-02 13:19:40 -0500"}
{"now":"2018-04-02T13:19:40.291-05:00"}
String
ActiveSupport::TimeWithZone

Notice how Ruby stdlib’s default time is not parseable by Active Support. Only the ISO 8601 formatted time gets successfully converted. Active Support uses a regex to detect times. You can read the tests to get a good idea of the time formats that it supports. Looks like it supports ISO 8601, but does not support Unix/POSIX/Epoch timestamps.

I was informed of this feature in Active Support when I created this issue against Rails.

Some history: Time parsing used to be the default behavior in Rails, but then ActiveSupport.parse_json_times was added for people who wanted to turn it off, and then it became turned off by default, so now you have to opt into it.

Upvotes: 10

Related Questions