2010-03-25 82 views
5

我需要将Date对象转换为TimeWithZone对象,该对象表示给定时区中当天的开始。将日期对象转换为TimeWithZone

如下方法的工作原理,但似乎太令人费解,因为它需要我将日期转换为字符串:

?> date = Date.parse("2010-02-17") 
=> Wed, 17 Feb 2010 
>> ActiveSupport::TimeZone['Eastern Time (US & Canada)'].parse(date.to_s) 
=> Wed, 17 Feb 2010 00:00:00 EST -05:00 
>> ActiveSupport::TimeZone['UTC'].parse(date.to_s) 
=> Wed, 17 Feb 2010 00:00:00 UTC 00:00 

有没有更好的办法,我失踪?

编辑:的 人们提示的变化:

?> date.to_datetime.in_time_zone('Eastern Time (US & Canada)').beginning_of_day 
=> Tue, 16 Feb 2010 00:00:00 EST -05:00 

正如你所看到的,这不是一个等价转换,因为它让我在2月16日美国东部时间的开始,而不是开始美国东部时间2月17日

+0

它看起来像你的解决方案可能是去的正确方法。 – 2010-03-26 00:38:42

+0

我编辑了我的回复以解决此问题。 – 2010-03-26 10:28:47

+0

给自己解决方案! =)时间与时区总是混乱。 – John 2010-11-17 19:31:37

回答

0

会这样的工作吗?

'2010-04-01'.to_time.in_time_zone('Eastern Time (US & Canada)').beginning_of_day 
+0

请参阅编辑问题以了解为什么这不起作用 – avaynshtok 2010-03-25 22:14:39

0

减去utc_offset:

d = Date.today 
Time.zone.class.all.map(&:name).map { |tz| dt = d.to_datetime.in_time_zone(tz); dt -= dt.utc_offset } 

使用的ActiveSupport ::时区[TZ]不采取日光节约时间考虑在内。

Time.zone.class.all.map(&:name).map { |tz| o = d.to_datetime.in_time_zone(tz).utc_offset - ActiveSupport::TimeZone[tz].utc_offset } 
4

如果你在Rails的Time.zone集,那么你可以调用Date#at_beginning_of_day(见http://api.rubyonrails.org/classes/Date.html#method-i-at_beginning_of_day)。与Date#to_datetime进行对比:

Time.zone 
=> #<ActiveSupport::TimeZone:0x10cf10858 @tzinfo=#<TZInfo::TimezoneProxy: Etc/UTC>, @utc_offset=nil, @current_period=nil, @name="UTC"> 

date = Date.today 
=> Thu, 31 May 2012 

date.to_datetime 
=> Thu, 31 May 2012 00:00:00 +0000 

date.at_beginning_of_day 
=> Thu, 31 May 2012 00:00:00 UTC +00:00 

Time.zone = 'America/Chicago' 
=> "America/Chicago" 

date.to_datetime 
=> Thu, 31 May 2012 00:00:00 +0000 

date.at_beginning_of_day 
=> Thu, 31 May 2012 00:00:00 CDT -05:00 
+2

'Time.zone' **为**线程安全,它将区域设置为'Thread.current [:time_zone]'。 [源](https://github.com/rails/rails/blob/08754f12e65a9ec79633a605e986d0f1ffa4b251/activesupport/lib/active_support/core_ext/time/zones.rb#L39) – 2014-10-22 23:24:26

+1

感谢您的更正,我删除了该评论,但离开这个所以人们不认为你疯了;) – gtd 2014-11-05 16:13:57

2

我强烈反对,使用to_datetimeto_time日期转换为一个时间,因为这些方法不知道该区域的任何解决方案,和套结in_time_zone到结果,因为一些答案建议,不会追溯解决这个错误。此外,不要尝试使用UTC偏移建立自己的夏令时数学。你一定会弄错的,而且你在做不必要的工作。 。

使用具有这种逻辑时区本身内置

给定的区域和日期,你可以得到一个TimeWithZone一天的开始是这样的:

time = zone.local(date.year, date.month, date.day) 

如果除了开始之外,您需要一天的特定时间,您可以将第4,第5和第6个参数的小时,分​​钟和秒传递给#local

如果zone实际上是系统的本地时区(Time.zone),随后的ActiveSupport会让你缩短上述这样:

time = date.to_time_in_current_zone 

所有上述手柄日光正确节省时间。让我们验证通过查看UTC偏移两次,一个是外DST和一个内DST这就是:

irb(main):009:0> zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] 
=> (GMT-05:00) Eastern Time (US & Canada) 
irb(main):010:0> t1 = zone.local(2013, 1, 1) 
=> Tue, 01 Jan 2013 00:00:00 EST -05:00 
irb(main):011:0> t2 = zone.local(2013, 5, 1) 
=> Wed, 01 May 2013 00:00:00 EDT -04:00 
irb(main):012:0> t1.utc_offset 
=> -18000 
irb(main):013:0> t2.utc_offset 
=> -14400 
+0

删除我的答案,并upvoted你的。 – 2013-05-10 14:49:55

5

,我迟到了,但这仍然是一个很大的问题。 ActiveSupport的in_time_zone是自O.P.开始引入的,但它在不分析字符串(慢)或设置时间的情况下完全按照您的要求进行操作。区(风险):

>> date = Date.parse("2010-02-17") 
=> Wed, 17 Feb 2010 
>> date.in_time_zone('Eastern Time (US & Canada)') 
=> Wed, 17 Feb 2010 00:00:00 EST -05:00 

当然,如果你想在UTC表示一天的开始,你可以这样做:

>> date.in_time_zone('Eastern Time (US & Canada)').utc 
=> 2010-02-17 05:00:00 UTC 
相关问题