2010-03-25 77 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 
相關問題