6

我有一个时间对象 T。将 N 天添加到 T 的合理方法是什么?

我想出的最好的感觉有点折磨:

require 'date'
def add_days(time, days)
  time.to_date.next_day(days).to_time
end

PS:如果你在美国,正确答案必须满足:

add_days(Time.new(2013, 3, 10, 0), 1) == Time.new(2013, 3, 11, 0)

如果您在欧盟,正确答案必须满足:

add_days(Time.new(2013, 3, 31, 0), 1) == Time.new(2013, 4, 1, 0)

PPS:这是一个 Ruby 问题,而不是 Rails 问题。

4

4 回答 4

11

Time有一个接受秒的+方法。

N = 3

t = Time.now + N * 86400 # 24 * 60 * 60 

或者,如果您引入 ActiveSupport,它会更容易

require 'active_support/core_ext'

t = Time.now + N.days

你显然可以做你自己的帮手

class Fixnum
  def days
    self * 86400
  end
end

t = Time.now # => 2013-01-31 16:06:31 +0700

t + 3.days # => 2013-02-03 16:06:31 +0700
于 2013-01-31T09:02:16.673 回答
6

似乎已经成为我的风格,我正在回答我自己的问题。

由于跨 DST / ST 的转换相当罕见(在世界许多地方,不存在),更有效的方法是首先添加 (n_days * 24 * 60 * 60) 秒,然后检查 UTC 偏移量是否已更改。如果有,则创建一个更正的时间对象。

像这样:

def add_days(time, n_days)
  t2 = time + (n_days * 24 * 60 * 60)
  utc_delta = time.utc_offset - t2.utc_offset
  (utc_delta == 0) ? t2 : t2 + utc_delta
end

这种方法避免了许多额外的对象创建,并正确处理夏令时之间的转换(至少在我当前的时区,太平洋时间):

>> t1 = Time.new(2013, 3, 10, 0, 0, 0)
=> 2013-03-10 00:00:00 -0800  # midnight Mar 3, 2013 Pacific Standard Time
>> t2 = add_days(t1, 1)
=> 2013-03-11 00:00:00 -0700  # midnight Mar 4, 2013 Pacific Daylight Time
>> t2 - t1
=> 82800.0                    # a shorter than usual day

>> u1 = Time.new(2013, 11, 3, 0, 0, 0)
=> 2013-11-03 00:00:00 -0700  # midnight Nov 3, 2013 Pacific Daylight Time
>> u2 = add_days(u1, 1)
=> 2013-11-04 00:00:00 -0800  # midnight Nov 4, 2013 Pacific Standard Time
>> u2 - u1
=> 90000.0                    # a longer than usual day
于 2013-01-31T17:29:48.303 回答
6

ActiveSupport::TimeWithZone似乎处理得很好

> t1 = ActiveSupport::TimeZone['Eastern Time (US & Canada)'].parse('2013-03-10')
 => Sun, 10 Mar 2013 00:00:00 EST -05:00 

注意下面的类类型:

 > t1.class
 => ActiveSupport::TimeWithZone 

注意从上面的 EST 到下面的 EDT 的变化:

> t1 + 1.day
 => Mon, 11 Mar 2013 00:00:00 EDT -04:00 
于 2013-08-21T16:17:10.767 回答
2

这有点横向答案,但是因为在您最初的问题中您并不关心 HMS 部分,所以使用对象不是Time更好吗?Date

require 'date'
t=Time.now
d=Date.parse(t.to_s)
puts d+1 # => gives you tomorrow's day (YMD)

编辑:添加require 'date'以提高答案的全面性,如评论部分所述。

于 2013-12-06T02:41:47.580 回答