Подводя итог, что представляют собой общие классы времени в рубине:
Time
Это базовый класс времени в рубине для рабочей лошадки.
- Имеет дату иатрибуты времени (год, месяц, день, час, мин, сек, подсек)
- На основе секундных интервалов с плавающей запятой с эпохи Unix (1970-01-01)
- Может обрабатывать отрицательные временадо эпохи unix
- Может обрабатывать арифметику времени в секундах
- Работает в UTC или локальном (системном часовом поясе)
На самом деле 3виды объектов Time, когда дело доходит до работы с часовыми поясами, давайте посмотрим на летнее время, чтобы показать летнее время:
utc = Time.utc(2012,6,1) # => 2012-12-21 00:00:00 UTC
utc.zone # => "UTC"
utc.dst? # => false
utc.utc? # => true
utc.utc_offset # => 0
local = Time.local(2012,6,1) # => 2012-06-01 00:00:00 -0700
local.zone # => "PDT"
local.dst? # => true
local.utc? # => false
local.utc_offset # => -25200
nonlocal = Time.new(2012,6,1,0,0,0, "-07:00") # => 2012-06-01 00:00:00 -0700
nonlocal.zone # => nil
nonlocal.dst? # => false
nonlocal.utc? # => false
nonlocal.utc_offset # => -25200
Последние 2 выглядят похожими, но будьте осторожны: вы не должны делать арифметику снелокальное время .Это просто время со смещением UTC и без зоны, поэтому он не знает правил DST.Добавление времени за границу летнего времени не изменит смещения, и полученное время суток будет неправильным.
ActiveSupport::TimeWithZone
Это стоит упомянуть здесь, поскольку оно используется вRails.То же, что и время, плюс:
- Может обрабатывать любой часовой пояс
- Относится к летнему времени
- Может конвертировать время между зонами
Я вообщевсегда достигайте этого, когда ActiveSupport доступен, поскольку он заботится обо всех ловушках часового пояса.
Date
- Имеет только атрибуты даты (год, месяц, день)
- На основе целочисленных интервалов целого дня из произвольного "нулевого дня" (-4712-01-01)
- Может обрабатывать арифметику дат в единицах целых дней
- Может преобразовывать междудаты от древнего юлианского календаря до современного григорианского
Дата более полезна, чем Время, когда вы имеете дело с целыми днями: никаких часовых поясов, чтобы беспокоиться!(Я удивлен, что это не относится к современному персидскому календарю, так как он знает об устаревшем юлианском календаре столетия назад.)
DateTime
- Имеет дату и времяатрибуты (год, месяц, день, час, мин, сек)
- На основе долей интервалов целого дня от произвольного "нулевого дня" (-4712-01-01)
- Можетобрабатывать арифметику дат в единицах целых дней или долей
Лично у меня никогда нет причин использовать это: это медленно, оно обрабатывает время без учета часовых поясов и имеетпротиворечивый интерфейс.Я считаю, что это приводит к путанице, когда вы предполагаете, что у вас есть объект, подобный времени, но на самом деле он ведет себя как дата вместо этого:
Time.new(2012, 12, 31, 0, 0, 0) + 1 == Time.new(2012, 12, 31, 0, 0, 1)
DateTime.new(2012, 12, 31, 0, 0, 0) + 1 == DateTime.new(2013, 1, 1, 0, 0, 0)
Кроме того, он имеет бессмысленную «зону»атрибут (обратите внимание, что нелокальные объекты времени предупреждают вас об этом zone == nil
), и вы не можете больше ничего знать о нем, прежде чем сначала превратить его во время:
dt = DateTime.new(2012,12,6, 1, 0, 0, "-07:00")
dt.zone # => "-07:00"
dt.utc? # => NoMethodError: undefined method `utc?'
dt.dst? # => NoMethodError: undefined method `dst?'
dt.utc_offset # => NoMethodError: undefined method `utc_offset'
Работа с микросекундами для проверкиокругление тоже немного странно.Вы можете подумать, что, поскольку у него нет атрибута usec
, он имеет дело только с целыми числами, но вы ошибаетесь:
DateTime.now.usec # => NoMethodError: undefined method `usec'
DateTime.now.to_time.usec => 629399
Короче говоря, если вы не имеете дело с астрономическими событиямив древнем прошлом и необходимости конвертировать юлианскую дату (со временем дня) в современный календарь, пожалуйста, не используйте DateTime.Если у кого-то есть реальный вариант использования этого класса, я бы с удовольствием прочитал ваши комментарии.