Question

It seems that ActiveRecord and Ruby's Time object doesn't play nice with times that are over 24:00. However my database has a lot of those, as they represent a time after midnight but considered to be on the same day. This is a design decision of my data provider:

Note: Trips that span multiple dates will have stop times greater than 24:00:00. For example, if a trip begins at 10:30:00 p.m. and ends at 2:15:00 a.m. on the following day, the stop times would be 22:30:00 and 26:15:00. Entering those stop times as 22:30:00 and 02:15:00 would not produce the desired results.

How do I deactivate this "validation" of my Time objects? It was suggested that I write my time field as a varchar within the MySQL query but I'm looking for a solution that doesn't make the database intervene.

UPDATE: Regarding the relevance of keeping the > 24:00 format, querying and asc ordering all the stop_times for a stop using that format would return something like: 23:45, 23:54, 24:35, 24:55, 25:15, which is the actual order in which the next buses are coming.

Whereas going the other way would return: 0:35, 0:55, 1:15, 23:45, 23:54 (this is wrong, the first 3 stop_times are supposed to be sorted after the last 3).

Was it helpful?

Solution 2

Although @Tilo is right that this is probably not the best time format there is, I had to stick to them and so ended up using raw SQL to convert the time column into a string:

sql = "SELECT CONVERT(stop_time, CHAR) as stop_time from stop_times"
stop_times = ActiveRecord::Base.connection.select_all sql
time = stop_times[0]['stop_time'] # => returned as a string

OTHER TIPS

the note in your question is talking about a TimeDifference, not a Time object.

I think you should model the TimeDifference as a decimal or float field in the DB, with a value equal to the time difference in numbers of seconds.. and then when you print it out, you can re-format it as Days, Hours, Minutes.

Please note that this is how subtracting Time objects works in Ruby:

> t1 = Time.now
 => 2011-11-22 20:54:54 -0800 
> t2 = Time.now.tomorrow
 => 2011-11-23 20:54:59 -0800 
> t2 - t1
 => 86404.928009862    # these are seconds!  just store this in a float or decimal field
> (t2 - t1).class
 => Float              # NOT a Time object

Trying to store the time difference in a Time object or Time DB-field seems wrong.

If you get weird input values from an outside source, like "26:12" , better to convert them to seconds:

hours,minutes = "26:12".split(/:/).map(&:to_i)
seconds = hours * 3600 + minutes * 60

... and then store the time-difference in seconds


wow, this comes from a Google API?? YIKES!!!

Still, don't store it in a Time object.

you can use divmod() to clean things up:

 tomorrow,real_hour = hour.divmod(24)

where "tomorrow" stores the number of days in the future, and real_hour is a valid value for a 24-hour clock.

How about making a separate Class "TripTime" for those start and stop times, and have your own attributes: hours, minutes, days ? Airlines typically show arrival times as "03:12 +1" .. meaning +1 day in the future.

... or store just those weird values as a string, that keeps the sort-order, and to calculate the difference in hours/minutes/seconds, you can then convert them as needed as shown above with split and map

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top