I have a simple Rails 3.b1 (Ruby 1.9.1) application running on Sqlite3. I have this table:
create_table :time_tests do |t|
t.time :time
end
And I see this behavior:
irb(main):001:0> tt = TimeTest.new
=> #<TimeTest id: nil, time: nil>
irb(main):002:0> tt.time = Time.zone.now
=> Mon, 03 May 2010 20:13:21 UTC +00:00
irb(main):003:0> tt.save
=> true
irb(main):004:0> TimeTest.find(:first)
=> #<TimeTest id: 1, time: "2000-01-01 20:13:21">
So, the time is coming back blank. Checking the table, the data looks OK:
sqlite> select * from time_tests;
1|2010-05-03 20:13:21.774741
I guess it's on the retrieval part? What's going on here?
Technically, it's not coming back blank. It comes back as a time with a default date. It returns 2000-01-01 20:13:21 as the time, which is expected.
Rails is doing some magic loading of the data into a Time object and clearing out the date (since you only told it to store the time).
If you want to store the date and time then you need to define the column as a datetime. And conversely, if you wanted just a date you would use date.
So to recap:
date => "2010-12-12 00:00:00"
time => "2000-01-01 13:14:15"
datetime => "2010-12-12 13:14:15"
Related
Say I have a simple ActiveRecord model with this example schema:
create_table "users", id: :serial do |t|
t.datetime "updated_at"
end
When I run the following code in the console:
user = User.new
user.updated_at = DateTime.now
user.updated_at # => Thu, 27 Feb 2020 09:28:51 GMT +00:00
My question is: why this output is different than the normal return value of DateTime.now, which is
DateTime.now # => Thu, 27 Feb 2020 10:28:51 +0100
Is there some kind of serializer involved? How can I find out more about this?
AR updated_at/created_at are time zone aware attributes. You can read more about them here:
https://api.rubyonrails.org/classes/ActiveRecord/Timestamp.html
If you grab a User record for instance, and call time_zone_aware_types on it, you'll get the timezone aware column types
user = User.first
user.time_zone_aware_types
=> [:datetime, :time]
These types of columns are automatically converted to Time.zone when retrieved from the database even though they are stored in UTC.
The difference with DateTime.now is that it's not timezone aware and just returns the time in UTC
add your time zone in your config/application.rb inside the
class Application < Rails::Application
.......
# it will be like this
config.time_zone = "Asia/Riyadh"
.....
end
I have a model "Request", that have the common attributes created_at and updated_at, but have others datetime attributes: "inserted_at" and "response_deadline". My problem is especially with response_deadline, that sometimes is stored with the correct timezone and other times with a different one (wtf??), and in other cases, response_deadline with the same timezone's giving a correct datetime and the other a wrong datetime.
My application.rb is configured with the correct timezone:
config.time_zone = 'Brasilia'
and I already tried change the AR default timezone:
config.active_record.default_timezone = :utc or :local
Other problem is that if I put :local the problem in response_deadline is solved, but the other datetime attributes get wrong.
The server timezone and date are correct too.
Sometimes the response_deadline is stored like that:
response_deadline: "2018-11-01 02:00:00" - WRONG
and other like that:
response_deadline: "2018-11-01 03:00:00" - CORRECT
And the strangiest behavior, two apparently wrong timezones:
response_deadline: "2018-11-09 02:00:00" - WRONG
response_deadline: "2018-10-30 02:00:00" - CORRECT?
but when I run in rails c:
2.3.0 :002 > request1.response_deadline
=> Thu, 08 Nov 2018 23:00:00 -03 -03:00
2.3.0 :002 > request2.response_deadline
=> Tue, 30 Out 2018 00:00:00 -02 -02:00
The data are taken from a CSV file (uploaded), and the response_deadline has this format:
29/10/2018 23:59:59
Controller snippet:
uploaded_file = params[:file]
unsaved = []
begin
sheet = RubyXL::Parser.parse(uploaded_file.tempfile.path)
dados = sheet[0]
demandas = []
(4...(dados.sheet_data.rows.size - 1)).each do |num|
if !dados.sheet_data.rows[num][1].nil?
request_type = RequestType.has_request_type? dados.sheet_data.rows[num][3].value,Request.sources[:ouv]
demanda = {
protocol: dados.sheet_data.rows[num][2].value,
source_cd: Request.sources[:ouv],
request_type_id: request_type,
created_at: dados.sheet_data.rows[num][7].value,
inserted_at: Time.now,
response_deadline: dados.sheet_data.rows[num][8].value,
requester_name: dados.sheet_data.rows[num][21].value.blank? ? "AnĂ´nimo" : dados.sheet_data.rows[num][21].value,
hide_requester_information: nil,
all_completed_information: false
}
demandas << demanda
end
end
count = 0
demandas.each_with_index do |demanda, index|
request = Request.new(demanda)
request.requester = Requester.where(name: "eouv").take
if request.valid? && !request.request_type_id.nil?
if request.save
...
Why?? I really wanna understand what is happening... =/
All the attributes are datetime, including :response_deadline of course.
Environment:
This is happen only in the production enviroment, the DB is Oracle 12c, running on a RHEL 6.
Ruby 2.3.0 and Rails 4.2.1
Someone could help to try indetify what is going on?
ps:some days ago this was not happening.
I am generating a report from my ruby on rails app that would run everyday at 7 in the morning.
This report would collect the results from the previous day.
So basically I want query previous day's results to my Mongo collection. This is what I am tried:
logs = Log.where(:comp => comp, :created_at => (Date.today -1))
I got the following error:
BSON::InvalidDocument: Date is not currently supported; use a UTC Time instance instead.
What is the best approach to get the aboce result:
This is the the format of my date in my db:
"created_at" : ISODate("2015-12-02T23:12:38.076Z")
You can do something like this in mongoid:
logs = Log.where(:comp => comp, :created_at.gte => (Date.today -1 ).to_datetime)
Date.to_datetime will default to midnight as shown here:
(Date.today - 1).to_datetime
=> Wed, 30 Mar 2016 00:00:00 +0000
I have
Rails 3.0.9
Activerecord-sqlserver-adapter 3.0.15
TinyTds
MSSQL 2005
I have a problem with using Time.now.
That is what I do in console:
Could someone explain this behavior?
irb(main):026:0> row = Eclaim.where(:id => 1).first
=> #<Eclaim id: 1, id_user: 1, property: "inv", app_number: nil, patent_number:
nil, native_number: nil, title: nil, applicants: nil, receive_date: nil, change_
date: "2012-05-08 10:20:44">
irb(main):027:0> row[:change_date] = Time.now
=> 2012-05-08 13:37:13 +0300
irb(main):028:0> row.save
=> true
irb(main):029:0> row = Eclaim.where(:id => 1).first
=> #<Eclaim id: 1, id_user: 1, property: "inv", app_number: nil, patent_number:
nil, native_number: nil, title: nil, applicants: nil, receive_date: nil, change_
date: "2012-05-08 10:37:13">
irb(main):047:0> Time.zone
=> (GMT+00:00) UTC
Why am I getting the date 2012-05-08 10:37:13 in database instead of being 2012-05-08 13:37:13 +0300?
I have found the solution:
In application.rb you should write such settings:
config.time_zone = 'Riga'
config.active_record.default_timezone = :local
ActiveRecord stores dates in UTC (previously known as GMT). It converts the dates back to the local time zone when you format the date. After Eclaim.where(:id => 1).first, do a row.change_date.
irb(main):029:0> row = Eclaim.where(:id => 1).first
irb(main):029:0> row.change_date
i am not an expert in dates, but what happens if you change to utc like this
> row[:change_date] = Time.now.localtime
> row.save
I think that will give the correct result. As to why this happens(my 2 cents):
One should always store the dates in some standard(people seem to differ as to what format that is). However just be aware that when storing as utc time, you will need to display the time as local time(easily done). In your example above rails is automatically converting to utc and storing it. Hope it helps
EDIT
Rails i think still defaults to utc time(not sure how to change this). However from utc time in database you could call localtime.What happens if you call this
Eclaim.first.change_date.localtime
This is the only way i can think off to get the localtime from utc stored in database.
Suppose I have a standard Post.first.created_at datetime. Can I compare that directly with a datetime in the format 2009-06-03 16:57:45.608000 -04:00 by doing something like:
Post.first.created_at > Time.parse("2009-06-03 16:57:45.608000 -04:00")
Edit: Both fields are datetimes, not dates.
Yes, you can use comparison operators to compare dates e.g.:
irb(main):018:0> yesterday = Date.new(2009,6,13)
=> #<Date: 4909991/2,0,2299161>
irb(main):019:0> Date.today > yesterday
=> true
But are you trying to compare a date to a datetime?
If that's the case, you'll want to convert the datetime to a date then do the comparison.
I hope this helps.
Yes you can compare directly the value of a created_at ActiveRecord date/time field with a regular DateTime object (like the one you can obtain parsing the string you have).
In a project i have a Value object that has a created_at datetime object:
imac:trunk luca$ script/console
Loading development environment (Rails 2.3.2)
>> Value.first.created_at
=> Fri, 12 Jun 2009 08:00:45 CEST 02:00
>> Time.parse("2009-06-03 16:57:45.608000 -04:00")
=> Wed Jun 03 22:57:45 0200 2009
>> Value.first.created_at > Time.parse("2009-06-03 16:57:45.608000 -04:00")
=> true
The created_at field is defined as:
create_table "values", :force => true do |t|
[...]
t.datetime "created_at"
end
N.B. if your field is a date and not a datetime, then you need to convert it to a time:
Post.first.created_at.to_time > Time.parse("2009-06-03 16:57:45.608000 -04:00")
or parse a date:
Post.first.created_at > Date.parse("2009-06-03 16:57:45.608000 -04:00")
otherwise you'll get a:
ArgumentError: comparison of Date with Time failed