DateTime objects are truncating milliseconds
coneybeare opened this issue · 5 comments
I have a test where I create an object, grab the json response (as rendered by acts_as_api
), then compare it's values against the object's attributes.to_json.
While this works for nearly all objects, I have noticed something very weird on Rails 4 with DateTime objects.
>> puts apple.updated_at
2014-02-07 18:35:55 UTC
>> puts apple.updated_at.to_json
"2014-02-07T18:35:55.423Z"
...
(make get :show call to server, returning json on apple)
...
>> puts json['apple']['updated_at']
"2014-02-07T18:35:55.000Z"
Here you can see that the controller, calling render_for_api
, on the same object, is zeroing (or possible rounding) the milliseconds at the end. Otherwise, they are equal. Do you have any ideas as to why, or how I can resolve this?
Hi Matt,
I don't think milliseconds in as_json
/to_json
is a default setting. Did you patch anything, e.g. ActiveSupport::TimeWithZone
?
Generally speaking - there is no converter in acts_as_api
itself to format DateTime
or similar objects. This task is done by Rails itself.
Is your database engine truncating the value?
class User < ActiveRecord::Base
acts_as_api
api_accessible :public do |template|
template.add :email
template.add :current_sign_in_at
end
end
class UsersController < ApplicationController
respond_to :json
def index
@users = User.all
@users << User.new(current_sign_in_at: Time.now)
respond_with(@users, :api_template => :public, :root => :users)
end
end
Using MySQL I get truncated values for all records except for the one I'm adding at the end of the collection (which is not saved)
That's exactly what is happening. MySQL doesn't store milliseconds so when read from disk it gets truncated. The object I am comparing it to is in memory newly created.
It seems like Rails itself omits milliseconds when rendering a time as json.
This is from a Rails 3.2 app using Postgres (which stores milliseconds)
User.last.updated_at.as_json
# => "2014-02-09T11:37:26Z"
User.last.updated_at_before_type_cast
# => "2014-01-31 11:37:26.061182"
User.last.updated_at.usec
# => 61182
If you need to render milliseconds, you probably need to overwrite ActiveSupport::TimeWithZone::as_json
I don't need to, I just needed them to match for rspec purposes. No biggie