Как вы конвертируете между объектом DateTime и Time в Ruby?
Преобразование в/из DateTime и Time в Ruby
Ответ 1
Вам понадобится две несколько разных конверсии.
Чтобы преобразовать из 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
Обратите внимание, что вам нужно выбирать между местным временем и временем GM/UTC.
Оба приведенных выше фрагмента кода взяты из O'Reilly Ruby Cookbook. Их повторное использование кода policy позволяет это.
Ответ 2
require 'time'
require 'date'
t = Time.now
d = DateTime.now
dd = DateTime.parse(t.to_s)
tt = Time.parse(d.to_s)
Ответ 3
Как обновление состояния экосистемы 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
Ответ 4
К сожалению, функции DateTime.to_time, Time.to_datetime
и Time.parse
не сохраняют информацию о часовом поясе. Во время преобразования все преобразуется в локальный часовой пояс. Арифметика даты по-прежнему работает, но вы не сможете отображать даты со своими исходными часовыми поясами. Эта контекстная информация часто важна. Например, если я хочу видеть транзакции, совершаемые в рабочее время в Нью-Йорке, я, вероятно, предпочитаю видеть их в своих оригинальных часовых поясах, а не в моем местном часовом поясе в Австралии (что на 12 часов раньше Нью-Йорка).
Ниже приведены методы преобразования, которые хранят эту информацию.
Для Ruby 1.8, посмотрите ответ Гордона Уилсона. Это от старой доброй надежной рубиновой кулинарной книги.
Для 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, включая часовой пояс, сохраняется.
Ответ 5
Улучшение решения Гордона Уилсона, вот моя попытка:
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, потеряв часовой пояс (к сожалению)
Кроме того, если у вас есть ruby 1.9, просто попробуйте to_time
метод