为什么加一个月只加了31天而没有加一个月份



确实是一个非常奇怪的错误。我有一个项目,它每个月都会克隆自己,将下一个对象设置为具有scheduled_on日期,即将来的+ 1.months

但后来发生了这样的事情:

Sun, 01 Apr 2012 16:00:00 PDT -07:00
Tue, 01 May 2012 16:00:00 PDT -07:00
Fri, 01 Jun 2012 16:00:00 PDT -07:00
Sun, 01 Jul 2012 16:00:00 PDT -07:00
Wed, 01 Aug 2012 16:00:00 PDT -07:00
Fri, 31 Aug 2012 17:00:00 PDT -07:00 # <--- What in the..

代码:

def clone_object
  objects = []
  Time.zone = account.timezone
  Chronic.time_class = Time.zone
  now = last_scheduled_on.to_time # <- this would have been Wed, 01 Aug 2012 16:00:00 PDT -07:00
  new_date = now + 1.months
  new_schedule = Time.zone.parse new_date.strftime('%Y-%m-%d' + ' ' + original_scheduled_on.strftime('%H:%M:%S'))
  objects << clone!(:scheduled_on => new_schedule, :recurring_job_id => id)
end

这是实际代码的一个非常截断的版本。但它包括了我合理影响这个问题的所有部分。

所以问题是……这个错误怎么可能发生呢?

更新

我确信这与时区有关。

以下是UTC中的日期:

In UTC :
Sun, 01 Apr 2012 23:00:00 UTC +00:00
Tue, 01 May 2012 23:00:00 UTC +00:00
Fri, 01 Jun 2012 23:00:00 UTC +00:00
Sun, 01 Jul 2012 23:00:00 UTC +00:00
Wed, 01 Aug 2012 23:00:00 UTC +00:00
Sat, 01 Sep 2012 00:00:00 UTC +00:00
Sun, 30 Sep 2012 23:00:00 UTC +00:00

在这里,它们被转换为太平洋:

In Pacific
Sun, 01 Apr 2012 16:00:00 PDT -07:00
Tue, 01 May 2012 16:00:00 PDT -07:00
Fri, 01 Jun 2012 16:00:00 PDT -07:00
Sun, 01 Jul 2012 16:00:00 PDT -07:00
Wed, 01 Aug 2012 16:00:00 PDT -07:00
Fri, 31 Aug 2012 17:00:00 PDT -07:00
Sun, 30 Sep 2012 16:00:00 PDT -07:00

我还注意到,我在这里输入的代码对我的服务器不准确。服务器将Time.zone设置为最后一个作业,并且不是帐户的时区。这意味着(或者至少我认为这意味着),时区是浮动的和动态的。但这也让我感到困扰,因为加州的夏令时要到11月才能切换,而不是9月。

发生这种情况的原因是,当您添加两个DateTime时,DateTime对象将按天数添加,并使时区不可信。

将两个时间对象添加到一起时,它们将按小时添加,并包括任何时区差异。

小时差异的出现是因为两个DateTime加在一起违反了时区更改。然后,时间以UTC作为相同的数字保存到数据库中,尽管稍后在各自的时区中解析时,时间将偏移一个小时。

你试过下个月吗?http://api.rubyonrails.org/classes/Time.html#method-i-months自以来

时间计算总是有问题的。1个月可能是30天,31天,28天,或介于两者之间的任何时间。这取决于添加的月份、添加的内容等等。因此,在进行日期计算时,类似这样的错误很不幸也很常见。

为了纠正这个代码,我总是确保它为你所在的月份选择月初,就像这样:

new_date = (now + 1.months).beginning_of_month

那将永远是一个月的第一天。

相关内容

  • 没有找到相关文章

最新更新