如何以更具Rails风格的方式获取某一天的小时数?
Rails风格计算夏令日当天小时数的方法
嘿,这个问题问到点子上了!你当前的写法确实能算出结果,但不仅有浮点精度的小问题(比如得到24.99999999999972而不是精确的25.0),而且代码也不够直观简洁——完全可以用更符合Rails优雅风格的方式来实现。
第一步:先解决精度问题
首先,你可以通过整数时间戳计算来避免浮点误差,写法更严谨:
start = Time.zone.parse('31-10-2021').beginning_of_day end_day = Time.zone.parse('31-10-2021').end_of_day (end_day.to_i - start.to_i) / 3600.0 # => 25.0
用时间戳(整数)相减再转浮点数,就能得到精确的小时数,不会出现奇怪的近似值。
第二步:封装成Rails风格的便捷方法
Rails核心本身没有内置hours_in_day这类方法,但我们可以通过扩展核心类的方式,实现你期望的那种简洁调用,这完全符合Rails的“优雅封装”理念。
你可以在项目的config/initializers/date_extensions.rb文件中添加以下代码(初始化文件会在Rails启动时加载):
class Date # 传入时区参数,默认使用项目配置的Time.zone def hours_in_day(time_zone = Time.zone) start_time = time_zone.local(year, month, day) end_time = start_time.end_of_day (end_time.to_i - start_time.to_i) / 3600.0 end end
之后你就能像预想的那样,用非常直观的方式调用:
Date.parse('31-10-2021').hours_in_day # => 25.0 # 如果需要指定其他时区,也可以传参 Date.parse('31-10-2021').hours_in_day(ActiveSupport::TimeZone['New York'])
如果你更习惯从TimeWithZone对象调用,也可以扩展ActiveSupport::TimeWithZone:
class ActiveSupport::TimeWithZone def hours_in_day (end_of_day.to_i - beginning_of_day.to_i) / 3600.0 end end
调用方式:
Time.zone.parse('31-10-2021').hours_in_day # => 25.0
这种封装的好处在于:代码可读性极强,复用性高,完全贴合Rails追求的简洁、直观的编码风格。
内容的提问来源于stack exchange,提问作者mejiaro
相关产品推荐
相关产品推荐

