对于时间26:12,ActiveRecord返回“参数超出范围”

时间:2011-11-23 04:34:18

标签: ruby-on-rails ruby datetime activerecord

似乎ActiveRecord和Ruby的Time对象在24:00以上的时间内效果不佳。然而,我的数据库有很多,因为它们代表午夜后的时间,但被认为是在同一天。这是我data provider的设计决定:

  

注意:跨越多个日期的旅程的停止时间大于   24:00:00。例如,如果旅行从晚上10:30开始。结束于   第二天凌晨2:15:00,停止时间为22:30:00   和26:15:00输入停止时间为22:30:00和02:15:00   没有产生预期的结果。

如何停用我的Time对象的“验证”? suggested我在MySQL查询中将我的时间字段写为varchar,但我正在寻找一种不会使数据库干预的解决方案。

更新:关于保持>的相关性24:00格式,查询和asc命令停止使用该格式的所有stop_times将返回类似于:23:45,23:54,24:35,24:55,25:15,这是实际的顺序下一班巴士即将到来。

而另一种方式会返回:0:35,0:55,1:15,23:45,23:54(这是错误的,前3个stop_times应该在之后排序 em>最后3)。

2 个答案:

答案 0 :(得分:2)

你问题中的注释是关于TimeDifference,而不是Time对象。

我认为您应该将TimeDifference建模为数据库中的十进制或浮点字段,其值等于秒数的时间差。然后当您将其打印出来时,可以将其重新格式化为天数,小时,分钟。

请注意,这是减去Time对象在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

尝试在Time对象或Time DB-field中存储时差似乎不对。

如果您从外部来源获得奇怪的输入值,例如“26:12”,最好将它们转换为秒:

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

...然后以秒为单位存储时差


哇,这来自Google API? YIKES !!!

但是,不要将它存储在Time对象中。

你可以使用divmod()来清理:

 tomorrow,real_hour = hour.divmod(24)

其中“明天”存储未来的天数,real_hour是24小时制的有效值。

如何为开始和停止时间单独创建“TripTime”类,并拥有自己的属性:小时,分钟,天?航空公司通常将到达时间显示为“03:12 +1”..意味着将来+1天。

... 或只存储那些奇怪的值作为字符串,保持排序顺序,并计算小时/分钟/秒的差异,然后您可以根据需要将它们转换为上面显示的是splitmap

答案 1 :(得分:0)

尽管@Tilo是正确的,这可能不是最好的时间格式,但我不得不坚持使用它们,所以最终使用原始SQL将时间列转换为字符串:

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