Finding records created 10 days ago - ruby-on-rails

My initial thought was:
user.humans.where("created_at = ?", 10.days.ago)
Though, this seems to be looking for the record created 10 days ago at the exact time when the statement is called. I want to collect the records created on that day, regardless of their time.
Is anyone aware of a convenient way to do this? Let me know if I need to elaborate.
Thanks.

You'll probably want to use a range here, as I assume this is a datetime column.
User.humans.where("? <= created_at AND created_at <= ?", 10.days.ago.beginning_of_day, 10.days.ago.end_of_day)
You'll also want to make sure you're setting the time zone of your Rails application so that you're explicit about which time period you consider to be the 10th day.

Whichever DBMS you are using will have a method to convert a datetime to a date. You should then compare this to a date in ruby. For example, if your DBMS is MySQL you could say
user.humans.where("date(created_at) = ?", 10.days.ago.to_date)
If you're not using MySQL then you should be able to google converting a datetime to a date in your DBMS of choice.

Related

handling rails + postgres and timezones

I have an application which uses many different timezones... it sets them in a controller and they change depending on the user. All the times are stored in UTC without a timestamp etc.
My understanding is this is the normal way for Rails to handle timezones. This works fine 99% of the time until i need to do something directly with Postgres then the Timezone becomes a problem.
For example this query is completely wrong except for GMT, for example in Central Time Zone, depending on the hour set, it gets the wrong day:
Events.where("EXTRACT(dow FROM start_at)", Date.today.wday)
Where I'm trying to find all the dates that fall on a certain day.
I'm trying to do something like this. I don't need to search between timezones (they won't be mixed), but I do need to specify the timezone if it's not UTC to get correct results.
User.events.where("EXTRACT(dow FROM start_at AT TIME ZONE ?) = ?", 'UTC', Date.today.wday)
But I'm not sure how to use Time.zone to give me something that will work with TIME ZONE in Postgres.
Time.zone.tzinfo sometimes works... Postgres will work with 'Europe/Warsaw' but Rails returns 'Europe - Warsaw'
In general I'm not having much luck with timezones, any pointers would be appreciated.
Maybe someone else has a better overall solution, but what you need for the particular query is
Time.zone.tzinfo.identifier
Or, in your example:
User.events.where("EXTRACT(dow FROM start_at AT TIME ZONE ?) = ?", Time.zone.tzinfo.identifier, Date.today.wday)
Try using the Ruby TZInfo gem directly, instead of using Rails ActiveSupport::TimeZone.
Alternatively, use the MAPPING constant, as shown in the ActiveSupport::TimeZone documentation, which will take you from a Rails time zone key back to the standard IANA time zone identifier used by Postgres and others.
As Matt Johnson suggested use TZInfo gem directly. This way you can get the correctly formatted time zone identifiers you need to query with PostgreSQL.
For example if you use:
TZInfo::Timezone.all_country_zone_identifiers
This will return an array of correct IANA/Olson time zone identifiers. In other words you will get the correct 'Europe/Warsaw' NOT 'Europe - Warsaw'.

Selecting record based on time

I have a model A which uses Rails timestamps and a attribute called ttl which represents the time in minutes between each update of the record.
I want to select all records that should be updated ergo:
WHERE (Time.now - updated_at).to_minutes > ttl)
I've been trying to use variations of Feed.where("(?-updated_at) > ttl", Time.now).to_a but I've not succeeded yet. Can someone help me with the query?
The reason is, that databases can't do time calculations just like arithmetic calculations.
You have to use the time function of the DB, unfortunately there is no standard.
In MySQL you could use
Feed.where("TIMESTAMPADD(MINUTE,ttl,updated_at)<?",Time.now)

Configuring Ruby-on-rails created_at and updated_at dates time_zone

Rails stores created_at and updated_at timestamps in UTC time.
But I am using these fields to filter and store (and do a lot of other stuff with the records) based on these fields, so it's important that when I call created_at and updated_at attributes, I get timestamps in my time zone.
As told by the following two SO questions, I can do that by configuring the time zone in the environment.rb file.
However, that's now working for me.
Because I am fetching the records from the database, based on created_at fields (which are in UTC) so naturally wrong ones are coming out, and then I am displaying them, so the dates are displayed in UTC, again, not what I want.
Is there a way to change in what time-zones the rails stores the dates?
OR
Is there a workaround for how I can achieve the database-fetching and displaying, without making a call to Rails object.created_at attribute?
Rails and timezone in created_at
Rails Time zone issue
I wonder why I even asked the question on this forum, because the workaround seemed to be pretty simple. But it did take me eight hours to reach it :)
1) While fetching records from the database and displaying them, I could simply do
select CONVERT_TZ(date) as date from table;
instead of doing
select date from table;
CONVERT_TZ() is a mysql specific function, so it worked for me. Not a universal solution though.
2) Secondly, when I had to fetch the records from a date range given in any other time-zone, I could do one of the two things.
One - I could replace [user-entered-date] 00:00:00 with [user-entered-date] 07:00:00 for the date-range's starting point and [user-entered-date] 59:59:59 with [user-entered-date + 1.day] 07:00:00 for the range's ending point. Note this would require me to use DateTime objects instead of using Date objects.
Two - In the where clause, I could do
CONVERT_TZ(registrations.created_at) <= [user/entered/date]
instead of
(registrations.created_at) <= [user/entered/date]

What is the correct type I should use to store a date up to the minute?

I want to store the date of an event in my database, but I want to do so without storing informations about seconds or anything smaller than seconds. Using Rails, in my migration I have the option to create a date column or a datetime column, the first one of which is too less accurate, and the second one is too much (up to the second and less). Which type should I choose to store such a date? Currently I'm using datetime and setting the seconds to a fixed value (e.g. 0) manually each time some date is set in the model.
Something like this:
self.date ||= Time.now.change(:sec => 0)
Am I totally out of track? Should I just use an integer field for each component of the date instead? (year, month, day, etc...) Or is datetime the correct type but I'm not understanding the purpose of it? (I think it's meant for timestamps and such things where seconds matter)
datetime is the correct type. And be sure to store it without time zone at time zone UTC:
http://derickrethans.nl/storing-date-time-in-database.html
At your option, use an SQL trigger to round your date to the minute on insert/update. It'll simplify your ruby code.

Ruby on Rails Time.now

I'm having trouble working with Time.now. For some reason when I save an object to the DB it saves it for the year 2000. I'm trying to make a comparison to the object I saved in the DB to Time.now to check if it is greater, but it always returns false because of the year 2000. Does anyone know of a way I can work around this?
I just need to check to make sure 10 minutes has passed since I created a time object compared to Time.now
It sounds like your database column is of type time rather than datetime or timestamp. This will only store the time and when it is converted to a Time instance in ruby (which does support day, month, year, etc) the default values are used for day, month, year which is why you're seeing the year 2000.
You probably need to update your database column to be datetime or timestamp if that is the problem as it sounds like you'll want the day, month, year parts of the time anyway. In which case you're comparisons will work.
created_at < 10.minutes.ago should work

Resources