Ruby 字符段类型的时间范围和时间使用 cover 函数做比较出现问题

ice-forever · September 17, 2025 · Last by Rei replied at September 17, 2025 · 62 hits

当使用字符串范围 ("2025-09-17".."2025-10-10") 检查时间字符串时,所有时间点都返回 true

("2025-09-17".."2025-10-10").cover?("2025-09-17 07:24:22 +0800") # => true
("2025-09-17".."2025-10-10").cover?("2025-09-17 08:24:22 +0800") # => true

但当检查时间对象时,结果出现矛盾

("2025-09-17".."2025-10-10").cover?(Time.current - 4.hours) # => false
("2025-09-17".."2025-10-10").cover?(Time.current - 3.hours) # => true

数据验证

(Time.current - 4.hours).to_s # => "2025-09-17 07:29:45 +0800"
(Time.current - 3.hours).to_s # => "2025-09-17 08:29:45 +0800"

相同时间值(如 07:29:45 +0800):

作为字符串时能匹配范围

作为时间对象时不能匹配范围

更奇怪的是,时间对象在 08:00 前返回 false,08:00 后返回 true

cover? 方法怎么处理时间区间的时区的?

cover? 实际执行了 begin <= obj <= end 运算,具体来说,是计算 "2025-09-17" <= Time.current - 4.hours

"2025-09-17" <= Time.current - 4.hours 会将字符串 "2025-09-17" 转为时间,也就是:

> "2025-09-17".to_time
=> 2025-09-17 00:00:00 +0000

注意时区,当它与 2025-09-17 07:29:45 +0800 比较的时候,结果是 false。

如果是执行的字符串转时间的话start_date.to_time => #2025-09-17 00:00:00 +0800输出的是一个时区的时间,而且我进行比较的时候:

start_date.to_time <= (Time.current-7.hours)
 => true

也就是与 2025-09-17 07:19:51 +0800我的比较结果是 true

可能内部用的不是 to_time 而是 Time.parse 之类,我没空深挖了。从现象看就是时区没处理好。我写的话会用显式类型转换。

You need to Sign in before reply, if you don't have an account, please Sign up first.