Ruby:将Date和Time对象组合成DateTime

Bre*_*don 38 ruby

简单的问题,但我找不到一个好的或明确的答案.将Ruby Date和Time对象(对象,而不是字符串)组合到单个DateTime对象中的最佳和最有效的方法是什么?

Dav*_*son 48

我找到了这个,但它并不像你希望的那样优雅:

d = Date.new(2012, 8, 29)
t = Time.now
dt = DateTime.new(d.year, d.month, d.day, t.hour, t.min, t.sec, t.zone)
Run Code Online (Sandbox Code Playgroud)

顺便说一句,ruby Time对象也存储了一年,一个月和一天,所以当你创建DateTime时你会扔掉它.


Ale*_*ark 17

使用时seconds_since_midnight,夏令时的变化可能会导致意外结果.

Time.zone = 'America/Chicago'
t  = Time.zone.parse('07:00').seconds_since_midnight.seconds
d1 = Time.zone.parse('2016-11-06').to_date # Fall back
d2 = Time.zone.parse('2016-11-07').to_date # Normal day
d3 = Time.zone.parse('2017-03-12').to_date # Spring forward

d1 + t
#=> Sun, 06 Nov 2016 06:00:00 CST -06:00
d2 + t
#=> Mon, 07 Nov 2016 07:00:00 CST -06:00
d3 + t
#=> Sun, 12 Mar 2017 08:00:00 CDT -05:00
Run Code Online (Sandbox Code Playgroud)

这是一个替代方案,类似于@ selva-raj上面的答案,使用字符串插值strftime,和parse.%F等于%Y-%m-%d%T等于%H:%M:%S.

Time.zone = 'America/Chicago'
t = Time.zone.parse('07:00')
d1 = Time.zone.parse('2016-11-06').to_date # Fall back
d2 = Time.zone.parse('2016-11-07').to_date # Normal day
d3 = Time.zone.parse('2017-03-12').to_date # Spring forward

Time.zone.parse("#{d1.strftime('%F')} #{t.strftime('%T')}")
#=> Sun, 06 Nov 2016 07:00:00 CST -06:00
Time.zone.parse("#{d2.strftime('%F')} #{t.strftime('%T')}")
#=> Sun, 07 Nov 2016 07:00:00 CST -06:00
Time.zone.parse("#{d3.strftime('%F')} #{t.strftime('%T')}")
#=> Sun, 12 Mar 2017 07:00:00 CDT -05:00
Run Code Online (Sandbox Code Playgroud)

  • 这是一个被低估的答案。如果您要合并的日期是夏令时,而当前时间不是夏令时(反之亦然),那么除非您在此答案中使用其中一种方法,否则所得时间将减少一个小时。 (2认同)

kar*_*gen 16

简单:

Date.new(2015, 2, 10).to_datetime + Time.parse("16:30").seconds_since_midnight.seconds

# => Object: Tue, 10 Feb 2015 16:30:00 +0000
Run Code Online (Sandbox Code Playgroud)

你必须爱Ruby!

  • 使用时区和夏令时时,“seconds_since_midnight”可能会导致意外结果。请参阅下面我的回答。 (5认同)

Lan*_*ane 12

如果使用Rails,请尝试以下任何一种:

d = Date.new(2014, 3, 1) 
t = Time.parse("16:30")

dt = d + t.seconds_since_midnight.seconds   
# => ActiveSupport::TimeWithZone

dt = (d + t.seconds_since_midnight.seconds).to_datetime   
# => DateTime

dt = DateTime.new(d.year, d.month, d.day, t.hour, t.min, t.sec)   
# => DateTime
Run Code Online (Sandbox Code Playgroud)

  • `dt = d + t.seconds_since_midnight.seconds ` 解决了我遇到的问题。 (2认同)