在Ruby中转换为DateTime和Time

如何在Ruby中的DateTime和Time对象之间进行转换?

您将需要两个稍有不同的转换。

要从Time转换为DateTime Time ,您可以按如下所示修改时间类:

 require 'date' class Time def to_datetime # Convert seconds + microseconds into a fractional number of seconds seconds = sec + Rational(usec, 10**6) # Convert a UTC offset measured in minutes to one measured in a # fraction of a day. offset = Rational(utc_offset, 60 * 60 * 24) DateTime.new(year, month, day, hour, min, seconds, offset) end end 

对Date的类似调整可以让你将DateTime转换为Time

 class Date def to_gm_time to_time(new_offset, :gm) end def to_local_time to_time(new_offset(DateTime.now.offset-offset), :local) end private def to_time(dest, method) #Convert a fraction of a day to a number of microseconds usec = (dest.sec_fraction * 60 * 60 * 24 * (10**6)).to_i Time.send(method, dest.year, dest.month, dest.day, dest.hour, dest.min, dest.sec, usec) end end 

请注意,您必须select本地时间和GM / UTC时间。

上面的代码片段都来自O'Reilly的Ruby Cookbook 。 他们的代码重用策略允许这个。

 require 'time' require 'date' t = Time.now d = DateTime.now dd = DateTime.parse(t.to_s) tt = Time.parse(d.to_s) 

作为对Ruby生态系统状态的更新, DateDateTimeTime现在有了在各个类之间进行转换的方法。 使用Ruby 1.9.2+:

 pry [1] pry(main)> ts = 'Jan 1, 2000 12:01:01' => "Jan 1, 2000 12:01:01" [2] pry(main)> require 'time' => true [3] pry(main)> require 'date' => true [4] pry(main)> ds = Date.parse(ts) => #<Date: 2000-01-01 (4903089/2,0,2299161)> [5] pry(main)> ds.to_date => #<Date: 2000-01-01 (4903089/2,0,2299161)> [6] pry(main)> ds.to_datetime => #<DateTime: 2000-01-01T00:00:00+00:00 (4903089/2,0,2299161)> [7] pry(main)> ds.to_time => 2000-01-01 00:00:00 -0700 [8] pry(main)> ds.to_time.class => Time [9] pry(main)> ds.to_datetime.class => DateTime [10] pry(main)> ts = Time.parse(ts) => 2000-01-01 12:01:01 -0700 [11] pry(main)> ts.class => Time [12] pry(main)> ts.to_date => #<Date: 2000-01-01 (4903089/2,0,2299161)> [13] pry(main)> ts.to_date.class => Date [14] pry(main)> ts.to_datetime => #<DateTime: 2000-01-01T12:01:01-07:00 (211813513261/86400,-7/24,2299161)> [15] pry(main)> ts.to_datetime.class => DateTime 

不幸的是, DateTime.to_time, Time.to_datetimeTime.parse函数不保留时区信息。 在转换过程中,一切都转换为本地时区。 datealgorithm仍然有效,但您将无法使用其原始时区显示date。 情境信息通常很重要。 例如,如果我想查看在纽约工作时间进行的交易,我可能更愿意看到它们显示在原来的时区,而不是我在澳大利亚的当地时区(比纽约快12小时)。

下面的转换方法确实保留了tz的信息。

对于Ruby 1.8,请看Gordon Wilson的答案 。 这是来自古老可靠的ruby食谱。

对于Ruby 1.9来说,它稍微简单一些。

 require 'date' # Create a date in some foreign time zone (middle of the Atlantic) d = DateTime.new(2010,01,01, 10,00,00, Rational(-2, 24)) puts d # Convert DateTime to Time, keeping the original timezone t = Time.new(d.year, d.month, d.day, d.hour, d.min, d.sec, d.zone) puts t # Convert Time to DateTime, keeping the original timezone d = DateTime.new(t.year, t.month, t.day, t.hour, t.min, t.sec, Rational(t.gmt_offset / 3600, 24)) puts d 

这将打印以下内容

 2010-01-01T10:00:00-02:00 2010-01-01 10:00:00 -0200 2010-01-01T10:00:00-02:00 

保留包括时区在内的全部原始DateTime信息。

改进Gordon Wilson解决scheme,这里是我的尝试:

 def to_time #Convert a fraction of a day to a number of microseconds usec = (sec_fraction * 60 * 60 * 24 * (10**6)).to_i t = Time.gm(year, month, day, hour, min, sec, usec) t - offset.abs.div(SECONDS_IN_DAY) end 

你会得到UTC的同一时间,丢失时区(不幸的是)

另外,如果你有ruby1.9,只要尝试to_time方法