Ruby: combine Date and Time objects into a DateTime

后端 未结 6 1632
伪装坚强ぢ
伪装坚强ぢ 2020-12-08 13:18

Simple question, but I can\'t find a good or definitive answer. What is the best and most efficient way to combine Ruby Date and Time objects (objects, not

相关标签:
6条回答
  • 2020-12-08 14:01

    I found this, but it's not as elegant you would hope:

    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)
    

    By the way, the ruby Time object also stores a year, month, and day, so you would be throwing that away when you create the DateTime.

    0 讨论(0)
  • 2020-12-08 14:04

    If you are using Ruby on Rails, this works great.

    I built a method to extend the DateTime class to combine a date and a time. It takes the zone from the date so that it does not end up an hour off with daylight savings time.

    Also, for convenience, I like being able to pass in strings as well.

    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
    

    So you can do:

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

    or

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

    etc...

    0 讨论(0)
  • 2020-12-08 14:06

    If using Rails, try any of these:

    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
    
    0 讨论(0)
  • 2020-12-08 14:11

    I found another way, I hope this is correct.

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

    Any thoughts? Please share.

    0 讨论(0)
  • 2020-12-08 14:12

    Simple:

    Date.new(2015, 2, 10).to_datetime + Time.parse("16:30").seconds_since_midnight.seconds
    
    # => Object: Tue, 10 Feb 2015 16:30:00 +0000
    

    You gotta love Ruby!

    0 讨论(0)
  • 2020-12-08 14:19

    When using seconds_since_midnight, changes in daylight savings time can lead to unexpected results.

    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
    

    Here's an alternative, similar to @selva-raj's answer above, using string interpolation, strftime, and parse. %F is equal to %Y-%m-%d and %T is equal to %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
    
    0 讨论(0)
提交回复
热议问题