Store time interval in PostgreSQL from Rails - ruby-on-rails-3

I need to store time inverval in PosgreSQL. Data will be put from Ruby on Rails.
Say, PizzaHut accepts orders from 9:00 to 18:00.
I've created following migration:
class AddOrderTimeAndDeliveryTimeToMerchants < ActiveRecord::Migration
def self.up
add_column :merchants, :order_time, :interval
end
I've read the documentation, and have following code now:
Merchant.create( :delivery_time => "9:00 18:00" )
When i execute it, i get following error message:
PGError: ERROR: invalid input syntax for type interval: "9:00 18:00"
How to do it correctly ?

I don't think an interval is really what you want for that. An interval represents a timespan without any specific end points; for example, you add an interval to an existing time to get another time. You would be better off with two distinct times:
add_column :merchants, :order_from, :time, :null => false
add_column :merchants, :order_to, :time, :null => false
Then, if for some reason you need to know how many hours they're open for delivery, you can construct an interval by subtracting :order_from from :order_to.
If you really must use an interval, then you'll need to construct a value something like this:
:delivery_time => "interval '11 hour'"
Note how this illustrates that an interval is not a specific time range from A to B, it is just a time range of some certain length (with no specified end points).

It's likely that you want a time without timezone here, since if Dominoes in NY opens at 9:00 local time, and Dominoes in California also opens at 9:00 local time, then a time with a timezone would not work properly.
What you likely want is one of two things. either two times a start and an end time, or a start time and an interval. I would suggest two times, but the choice is yours. Note that you can an interval from two times by subtracting one from the other.
select '09:00:00'::time - '05:00:00'::time;
?column?
----------
04:00:00

Related

How to add time instances to ontology

I have created a time ontology in protege, in which I have to add minute, seconds and hour values as 09,19, etc. At output I want to show time as 11:30:00. When I added instances to hour and then seconds it showed me that individual already added. How to resolve that issue?
If I understand correctly what you are trying to achieve is to have a single class, say Time, for which you can specify the hours, minutes and seconds. This is in fact an example of an n-ary relation, where you model the time relation as a class. A way to model this then is:
DataProperty: hours
Domain: Time
Range: xsd:byte[>= "0"^^xsd:byte , <= "24"^^xsd:byte]
DataProperty: minutes>
Domain: Time
Range: xsd:byte[>= "0"^^xsd:byte , <= "60"^^xsd:byte]
DataProperty: seconds>
Domain: Time
Range: xsd:byte[>= "60"^^xsd:byte , <= "0"^^xsd:byte]
Class: Time
Then to specify, let say the opening time of some store, as 8:30, you can create the following individual:
Individual: openingTime
Types: Time
Facts:
hours "8"^^xsd:byte,
minutes "30"^^xsd:byte,
seconds "0"^^xsd:byte

Rails business hours query for active record

I have two models
OfficeTimeing < ActiveRecord::Base
belongs_to :office
end
Office < ActiveRecord::Base
has_many :office_timings
end
with two fields opening_time and closing_time these fields have string values like "09:00 AM" I want a query how can I find currently open offices I want something like this.
Office.joins(:office_timings).where("Datetime.now > office_timings.opening_time AND office_timings.closing_time > DateTime.now")
I don't know how to compare two times represented as a string without being able to parse them in rails first, however, have you considered storing your opening and closing times in seconds (counting from midnight) rather than strings? That way you would easily be able to write this query.
UPDATE: A few useful methods to achieve this.
To get the current seconds since midnight for a specific time:
seconds = specific_time.seconds_since_midnight
To convert the seconds since midnight into a Time object:
time_instance = Time.at(seconds)
To produce a string in the form of 09:00 AM
time_instance.strftime("%I:%M %p")
Details about Time class.
Details about strftime.
You need to inject Datetime.now into your query using ?:
Office.joins(:office_timings)
.where(
"? > office_timings.opening_time AND office_timings.closing_time > ?",
Datetime.now, Datetime.now
)
Each ? will be safely replaced by the arguments following the query string.
You could also do this directly in Postgres using now(), and make the condition a bit easier to read using BETWEEN:
.where("now() BETWEEN office_timings.opening_time AND office_timings.closing_time")

SQL: do-not-disturb time interval for push notifications

suppose you get start_time and end_time
eg) 10pm to 6am
You don't want to send push notifications to users when event occurs in the time interval.
How would you implement (sql query) such a feature?
i.e. How would you grab all devices that doesn't fall in the time interval condition?
Edit
I did the following for now.
I have a boolean field to indicate whether start and end time is inverted (eg 10pm to 10am)
I exclude sets
(inverted=False, start < now, end > now)
(inverted=True, start > now)
(inverted=True, end < now)
Well, I wonder if this is a good solution.

Rails 3.2.8 - How to handle Time zones?

I've participated the Rails Rumble this year and I found myself tangled by time zone issues.
I uploaded my app in linode and I live in EST time zone or -4 to UTC.
I have a model and it saves things by doing the following:
def self.processing_creation(user_id, home_id, chore_id)
registered_chore = RegisteredChore.where("DATE(created_at) = ?", Date.today).find_by_user_id_and_home_id_and_chore_id(user_id, home_id, chore_id)
unless registered_chore
registered_chore = RegisteredChore.create(user_id: user_id, home_id: home_id, chore_id: chore_id, created_at: Time.zone.now)
user = registered_chore.user
user.add_one_chore_point
end
registered_chore
end
RegisteredChore.where("DATE(created_at) = ?", Date.today).find_by_user_id_and_home_id_and_chore_id(user_id, home_id, chore_id)
returns false even if the data was just created.
I noticed that "create" saves in UTC but Date.today uses user's local time zone.
What's the best way to handle this?
Another example to illustrate the issue:
I want to register a chore at 11 PM in EST time.
The server is already in the next day (e.g: 12).
Rails saves the data in the next day date (12).
But user is still in day 11.
Technically, user with the current method, could save the entry again because the days are different from the db and user interface.
How to solve this?
Rails will, by default, save times to the database as UTC. If you're using DATE([Date.today]), then it's going to be looking up records on the 11th, not the 12th. To get the right date, you probably want to set Time.zone to the user's current timezone, and then do the query.
I built a gem called by_star to handle this kind of date searching, and I reckon you should use it. With it, your query would be this:
RegisteredChore.today.where(:user_id => user.id,
:home_id => home.id,
:chore_id => chore.id)
Rails 3 by default saves all the time in database relative in GMT+00:00 time zone. So you will have to set an offset while computing time depending on your timezone. Else, you can change default Activerecord time zone by adding following to application.rb
config.time_zone = 'Your time zone' (Example: 'Eastern Time (US & Canada)')
config.active_record.default_timezone = 'Your time zone' (Example: 'Eastern Time (US & Canada)')

date comparisons in Rails

I'm having trouble with a date comparison in a named scope. I'm trying to determine if an event is current based on its start and end date. Here's the named scope I'm using which kind of works, though not for events that have the same start and end date.
named_scope :date_current, :conditions => ["Date(start_date) <= ? AND Date(end_date) >= ?", Time.now, Time.now]
This returns the following record, though it should return two records, not one...
>> Event.date_current
=> [#<Event id: 2161, start_date: "2010-02-15 00:00:00", end_date: "2010-02-21 00:00:00", ...]
What it's not returning is this as well
>> Event.find(:last)
=> #<Event id: 2671, start_date: "2010-02-16 00:00:00", end_date: "2010-02-16 00:00:00", ...>
The server time seems to be in UTC and I presume that the entries are being stored in the DB in UTC. Any ideas as to what I'm doing wrong or what to try?
Thanks!
Easiest way to debug is to look in your rails log to see exactly what SQL statement is being generated by Rails.
Then post the sql if still having problems.
In the meantime, my guess is that something is not set to UTC. Where something is the set {operating system, rails environment, dbms}
Added: Also, why are you comparing "Date" (in the dbms) with "Time" values (from your statement)? Better to have the type classes match explicitly. I use the standard of a new day has time component 00:00:00. That way you can compare with the db without needing the date function in your SQL.
I struggled with the same issue. The records are stored in UTC, but the utc value is not inserted into the query. I solved it, like you, by converting it to utc manually, like this time.utc.
def find_production_since(start_time)
find(:all, :conditions => ["time > ?", start_time.utc])
end
This might help you.
named_scope :date_current, :conditions => ["Date(start_date) <= Date(NOW()) AND Date(end_date) >= Date(NOW())"]
Rather than using Time.now (and then laboriously converting to a date as per your second comment) you could just use Date.today, which will insert '2010-04-20' into your SQL, and should compare against Date(start_date) without worrying about times.