Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 673
Sean Moubry Avatar asked Jan 25 '26 10:01

Sean Moubry


1 Answers

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.

like image 61
Sean Moubry Avatar answered Jan 27 '26 00:01

Sean Moubry