Я не уверен, что это должен быть отдельный вопрос, но как преобразовать дату и время?
Эндрю Гримм
8
Принятые и получившие самые высокие оценки ответы больше не являются самыми точными в современных версиях Ruby. См. Ответы @theTinMan и @PatrickMcKenzie ниже.
Phrogz
Ответы:
50
Вам понадобятся два немного разных преобразования.
Чтобы преобразовать из Time в, DateTimeвы можете изменить класс Time следующим образом:
require 'date'classTimedef 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)endend
Подобные настройки даты позволят вам преобразовать DateTime в Time .
classDatedef to_gm_time
to_time(new_offset,:gm)enddef 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)endend
Обратите внимание, что вам нужно выбирать между местным временем и временем GM / UTC.
Оба приведенных выше фрагмента кода взяты из Ruby Cookbook от O'Reilly . Их политика повторного использования кода позволяет это.
Это прервется на 1.9, где DateTime # sec_fraction возвращает количество миллисекунд за одну секунду. Для 1.9 вы хотите использовать: usec = dest.sec_fraction * 10 ** 6
dkubb
185
require 'time'
require 'date'
t =Time.now
d =DateTime.now
dd =DateTime.parse(t.to_s)
tt =Time.parse(d.to_s)
+1 Может быть, это не самый эффективный вариант, но работает, кратко и хорошо читается.
Уолт Джонс,
6
К сожалению, это действительно работает только при работе с местным временем. Если вы начнете с DateTime или Time с другим часовым поясом, функция синтаксического анализа преобразуется в местный часовой пояс. Вы в основном теряете исходный часовой пояс.
Бернард
6
Начиная с Ruby 1.9.1, DateTime.parse сохраняет часовой пояс. (У меня нет доступа к более ранним версиям.) Time.parse не сохраняет часовой пояс, потому что он представляет POSIX-стандарт time_t, который, я считаю, является целочисленным отличием от эпохи. Любое преобразование во время должно иметь такое же поведение.
аншул
1
Ты прав. DateTime.parse работает в 1.9.1, но не Time.parse. В любом случае, он менее подвержен ошибкам (согласован) и, вероятно, быстрее будет использовать DateTime.new (...) и Time.new (..). См. Мой ответ для примера кода.
Бернард
1
Привет @anshul. Я не имею в виду, что утверждаю :-). Информация о часовом поясе не сохраняется при использовании Time.parse (). Проверить это легко. В приведенном выше коде просто замените d = DateTime.now на d = DateTime.new (2010,01,01, 10,00,00, Rational (-2, 24)). tt теперь будет показывать дату d, преобразованную в ваш местный часовой пояс. Вы все еще можете выполнять арифметику даты, и все, кроме исходной информации tz, теряется. Эта информация является контекстом для даты и часто важна. См. Здесь: stackoverflow.com/questions/279769/…
Бернард,
63
Как обновление состояния экосистемы Ruby Date, DateTimeи Timeтеперь есть методы для преобразования между различными классами. Использование Ruby 1.9.2+:
К сожалению. Только что понял, что это проблема Ruby on Rails, а не Ruby: stackoverflow.com/questions/11277454/… . Они даже указали ошибку этого метода в строке 2.x и пометили ее как «не исправить». Ужасное решение ИМХО. Поведение Rails полностью нарушает базовый интерфейс Ruby.
Джесси Кларк
12
К сожалению, DateTime.to_time, Time.to_datetimeи Time.parseфункция не сохраняет информацию часового пояса. Во время преобразования все конвертируется в местный часовой пояс. Арифметика дат по-прежнему работает, но вы не сможете отображать даты с их исходными часовыми поясами. Эта контекстная информация часто бывает важной. Например, если я хочу видеть транзакции, выполняемые в рабочее время в Нью-Йорке, я, вероятно, предпочитаю видеть их в исходном часовом поясе, а не в моем местном часовом поясе в Австралии (который на 12 часов опережает Нью-Йорк).
Приведенные ниже методы преобразования сохраняют эту tz-информацию.
Для Ruby 1.8 посмотрите ответ Гордона Уилсона . Это из старого доброго и надежного 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
Время - это сложно, но нет оправдания тому, что нет встроенного преобразования между различными встроенными классами времени. Вы можете создать исключение RangeException, если попытаетесь получить UNIX time_t для 4713 г. до н.э. (хотя отрицательное значение BigNum было бы лучше), но, по крайней мере, предоставьте для этого метод.
Марк Рид
1
Time#to_datetimeкажется, сохраняет tz для меня:Time.local(0).to_datetime.zone #=> "-07:00"; Time.gm(0).to_datetime.zone #=> "+00:00"
Phrogz
@Phrogz Смещение UTC - это не то же самое, что часовой пояс. Один постоянный, другой может меняться в разное время года на летнее время. DateTime не имеет зоны, он игнорирует летнее время. Время это уважает, но только в "локальной" (системной среде) ТЗ.
Эндрю Вит
1
Улучшение решения Гордона Уилсона, вот моя попытка:
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метод
При выполнении таких преобразований следует учитывать поведение часовых поясов при преобразовании одного объекта в другой. Я нашел несколько хороших заметок и примеров в этом сообщении stackoverflow .
Ответы:
Вам понадобятся два немного разных преобразования.
Чтобы преобразовать из
Time
в,DateTime
вы можете изменить класс Time следующим образом:Подобные настройки даты позволят вам преобразовать
DateTime
вTime
.Обратите внимание, что вам нужно выбирать между местным временем и временем GM / UTC.
Оба приведенных выше фрагмента кода взяты из Ruby Cookbook от O'Reilly . Их политика повторного использования кода позволяет это.
источник
источник
Как обновление состояния экосистемы Ruby
Date
,DateTime
иTime
теперь есть методы для преобразования между различными классами. Использование Ruby 1.9.2+:источник
1.9.3p327 :007 > ts = '2000-01-01 12:01:01 -0700' => "2000-01-01 12:01:01 -0700" 1.9.3p327 :009 > dt = ts.to_datetime => Sat, 01 Jan 2000 12:01:01 -0700 1.9.3p327 :010 > dt.to_time => Sat, 01 Jan 2000 12:01:01 -0700 1.9.3p327 :011 > dt.to_time.class => DateTime
К сожалению,
DateTime.to_time, Time.to_datetime
иTime.parse
функция не сохраняет информацию часового пояса. Во время преобразования все конвертируется в местный часовой пояс. Арифметика дат по-прежнему работает, но вы не сможете отображать даты с их исходными часовыми поясами. Эта контекстная информация часто бывает важной. Например, если я хочу видеть транзакции, выполняемые в рабочее время в Нью-Йорке, я, вероятно, предпочитаю видеть их в исходном часовом поясе, а не в моем местном часовом поясе в Австралии (который на 12 часов опережает Нью-Йорк).Приведенные ниже методы преобразования сохраняют эту tz-информацию.
Для Ruby 1.8 посмотрите ответ Гордона Уилсона . Это из старого доброго и надежного Ruby Cookbook.
Для Ruby 1.9 это немного проще.
Это напечатает следующее
Сохраняется полная исходная информация о DateTime, включая часовой пояс.
источник
Time#to_datetime
кажется, сохраняет tz для меня:Time.local(0).to_datetime.zone #=> "-07:00"; Time.gm(0).to_datetime.zone #=> "+00:00"
Улучшение решения Гордона Уилсона, вот моя попытка:
Вы получите то же время в UTC, потеряв часовой пояс (к сожалению)
Также, если у вас Ruby 1.9, просто попробуйте
to_time
методисточник
При выполнении таких преобразований следует учитывать поведение часовых поясов при преобразовании одного объекта в другой. Я нашел несколько хороших заметок и примеров в этом сообщении stackoverflow .
источник