转换为/从日期时间和Ruby中的时间
您需要两个略有不同的转换。
从Time
转换为DateTime
你可以修改时间类,如下所示:
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
类似的调整时间会让你转换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
请注意,您必须选择本地时间和GM/UTC时间。
上述代码片段均取自O'Reilly的Ruby Cookbook。他们的代码重用policy允许这样做。
这将在1.9上中断,其中DateTime#sec_fraction返回一秒中的毫秒数。对于1.9你想要使用:usec = dest.sec_fraction * 10 ** 6 – dkubb 2011-03-14 21:52:17
require 'time'
require 'date'
t = Time.now
d = DateTime.now
dd = DateTime.parse(t.to_s)
tt = Time.parse(d.to_s)
+1这可能不是最有效的执行,但它的工作原理,简洁并且非常可读。 – 2009-06-16 22:20:18
不幸的是,这只在处理当地时间时才有效。如果以具有不同时区的DateTime或Time开始,则解析函数将转换为本地时区。你基本上失去了原来的时区。 – Alkaline 2010-08-18 14:20:28
不幸的是,DateTime.to_time, Time.to_datetime
和Time.parse
功能不保留时区信息。在转换过程中,所有内容都转换为本地时区。日期算术仍然有效,但您将无法使用其原始时区显示日期。上下文信息通常很重要。例如,如果我想看期间在纽约营业时间进行交易,我可能更愿意看到他们显示在原来的时区,在澳大利亚不是我的本地时区(这比纽约早12个小时)。
下面的转换方法确实保留了tz信息。
对于Ruby 1.8,请看Gordon Wilson's answer。这是来自古老可靠的Ruby Cookbook。
对于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
的完整的原始日期时间信息包括时区保持。
作为对Ruby生态系统状态的更新,Date
,DateTime
和Time
现在具有在各种类之间转换的方法。使用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
提高戈登·威尔逊的解决方案,这是我的尝试:
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的同时,失去的时区(不幸)
另外,如果你有红宝石1.9,只是尝试to_time
方法
我不知道这应该是一个单独的问题,但你如何转换日期和时间? – 2010-07-15 04:31:50
在现代版本的Ruby中,被接受且评分最高的答案不再是最准确的答案。看到的答案[由@theTinMan](http://*.com/a/8511699/405017)和[由@PatrickMcKenzie]以下(http://*.com/a/280026/405017)。 – Phrogz 2012-03-07 20:16:34