49

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

4

6 回答 6

56

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

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)

顺便说一句,ruby Time 对象还存储年、月和日,因此在创建 DateTime 时会丢弃它。

于 2012-08-29T15:55:26.307 回答
32

使用 时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

这是一个替代方案,类似于上面@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
于 2016-11-06T15:22:17.270 回答
23

简单的:

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

# => Object: Tue, 10 Feb 2015 16:30:00 +0000

你必须爱鲁比!

于 2015-02-10T12:20:34.627 回答
13

如果使用 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
于 2014-03-09T23:06:40.030 回答
4

如果您使用的是 Ruby on Rails,这非常有用。

我构建了一个方法来扩展 DateTime 类以组合日期和时间。它从日期中获取区域,以便它不会在夏令时结束一个小时

另外,为了方便起见,我也喜欢能够传入字符串。

class DateTime
  def self.combine(d, t)
    # pass in a date and time or strings
    d = Date.parse(d) if d.is_a? String 
    t = Time.zone.parse(t) if t.is_a? String
    # + 12 hours to make sure we are in the right zone
    # (eg. PST and PDT switch at 2am)
    zone = (Time.zone.parse(d.strftime("%Y-%m-%d")) + 12.hours ).zone
    new(d.year, d.month, d.day, t.hour, t.min, t.sec, zone)
  end
end

所以你可以这样做:

DateTime.combine(3.weeks.ago, "9am")

或者

DateTime.combine("2015-3-26", Time.current)

ETC...

于 2018-01-13T16:44:40.527 回答
1

我找到了另一种方法,我希望这是正确的。

 datetojoin=Time.parse(datetime).strftime("%Y-%m-%d")
       timetojoin=Time.parse(time).strftime("%T")          
       joined_datetime = Time.parse(datetojoin +" "+ timetojoin).strftime("%F %T")

有什么想法吗?请分享。

于 2013-02-27T17:32:44.477 回答