当用户注册我的某个网站进行免费试用时,我将其帐户到期时间设置为“14.days.from_now”。然后在主页上显示他们剩下多少天,我得到了:
(user.trial_expires - Time.now)/86400
(因为一天有86400秒,即60 * 60 * 24)
有趣的是,这个数字超过了14,所以最多可以调整到15个。在控制台中进行更仔细的调查,这将在未来发生两天(如果你知道我的意思)。例如
>> Time.now
=> Fri Oct 29 11:09:26 0100 2010
>> future_1_day = 1.day.from_now
=> Sat, 30 Oct 2010 11:09:27 BST 01:00
#ten past eleven tomorrow
>> (future_1_day - Time.now)/86400
=> 0.999782301526931
#less than 1, what you'd expect right?
>> future_2_day = 2.day.from_now
=> Sun, 31 Oct 2010 11:09:52 GMT 00:00
>> (future_2_day - Time.now)/86400
=> 2.04162248861183
#greater than 2 - why?
我想也许这与时区有关 - 我注意到从现在起1天的时间是在BST,从现在起2天的时间是在GMT。所以,我尝试使用localtime并得到了相同的结果!
>> future_2_day = 2.day.from_now.localtime
=> Sun Oct 31 11:11:24 0000 2010
>> (future_2_day - Time.now)/86400
=> 2.04160829127315
>> (future_2_day - Time.now.localtime)/86400
=> 2.04058651585648
然后我想知道差异有多大,而且事实证明它 正好一小时了。所以它看起来像一些时区怪异,或者至少与我不理解的时区有关。目前我所在的时区是BST(英国夏令时),此时比UTC晚一个小时(直到这个星期日,它恢复到与UTC相同的时间)。
当我向Time.now添加两天时,似乎会引入额外的小时:检查一下。我从Time.now开始,向它添加两天,减去Time.now,然后从结果中减去两天的秒数,并留下一个小时。
我突然想到,这是在发生这种情况,因为钟表会在星期天早上回归:即星期天早上11点20分将两天一小时现在起。我即将删除所有这篇文章,但后来我注意到了这一点:我想'啊,我可以通过使用(24 * daynum).hours而不是daynum.days来解决这个问题,但我仍然得到相同的结果:即使是我用秒!
>> (Time.now + (2*24).hours - Time.now) - 86400*2
=> 3599.99969500001
>> (Time.now + (2*24*3600).seconds - Time.now) - 86400*2
=> 3599.999855
所以现在我又困惑了。现在怎么能加上两天的价值,减去现在,减去两天的价值是一小时的秒数?额外的小时在哪里潜入?
答案 0 :(得分:19)
正如willcodejavaforfood所述,这是由于夏令时在本周末结束。
添加持续时间时,ActiveSupport中包含一些代码,以补偿开始时间是否为DST且结果时间是否为(反之亦然)。
def since(seconds)
f = seconds.since(self)
if ActiveSupport::Duration === seconds
f
else
initial_dst = self.dst? ? 1 : 0
final_dst = f.dst? ? 1 : 0
(seconds.abs >= 86400 && initial_dst != final_dst) ? f + (initial_dst - final_dst).hours : f
end
rescue
self.to_datetime.since(seconds)
end
如果您有11:09:27并且添加了几天,即使DST已经更改,您在结果日仍然会得到11:09:27。当你在几秒钟内完成计算时,这会导致额外的一小时。
一些想法:
distance_of_time_in_words
帮助程序方法向用户提供试用版中剩余时间的指示。Time.now + (14 * 86400)
而非使用14.days.from_now
- 但有些用户可能会声称他们已经失去了一小时的审判时间。答案 1 :(得分:8)
您可以使用Date课程来计算今天和过期日期之间的天数。
expire_date = Date.new(user.trial_expires.year, user.trial_expires.month, user.trial_expires.day)
days_until_expiration = (expire_date - Date.today).to_i
答案 2 :(得分:5)
使用since
,示例:
14.days.since.to_date