ruby-on-rails - Ruby on Rails 从日期时间解析时间,而不是字符串

标签 ruby-on-rails ruby datetime

我正在尝试从 DateTime 对象(在我的示例中表示为“at”)中提取时间分量。我该怎么做,我完全被难住了? (我不想像我在这里所做的那样用 strftime 将它解析为字符串):

@session_date.at.strftime("%H:%M")

我真的很想将小时和分钟作为 Time 对象返回。

最佳答案

您是否有特定原因需要时间对象?

我们很清楚,Time Ruby 中的类不仅仅是“没有日期的 DateTime”。正如“What's the difference between DateTime and Time in Ruby?”所解释的那样,“时间是 POSIX 标准 time_t 的包装器,即自 1970 年 1 月 1 日以来的秒数。”与 DateTime 一样,Time 对象仍然有年、月和日,因此使用 Time 并不能真正获得任何好处。没有真正的方法可以使用 Time 或 DateTime 来表示小时和分钟。

我认为,您可以使用 Time 做的最好的事情是:

date_time = DateTime.now
seconds = date_time.hour * 60 * 60 + date_time.minute * 60

time = Time.at(seconds)
# => 1970-01-01 09:58

...但是您仍然需要调用 time.hourtime.min 来获取小时和分钟。

不过,如果您只是在寻找一种轻量级数据结构来表示小时和分钟对,您不妨自己动手:

HourAndMinute = Struct.new(:hour, :minute) do
  def self.from_datetime(date_time)
    new(date_time.hour, date_time.minute)
  end
end

hm = HourAndMinute.from_datetime(DateTime.now)
# => #<struct HourAndMinute hour=15, minute=58>
hm.to_h
# => { :hour => 15, :minute => 58 }
hm.to_a
# => [ 15, 58 ]

编辑回复:

I have a variable that stores an appointment -- this variable is a DateTime object. I have two table fields that store the start and end times of a location. I need to check if the time scheduled for that appointment lies between the start and end times.

啊,看来你有点XY problem .现在这更有意义了。

如果没有更多信息,我将假设您的“存储位置开始和结束时间的字段”是名为 start_time结束时间。给定 MySQL TIME 列,Rails 将值转换为 Time 对象 with the date component set to 1/1/2000 .因此,如果您的数据库具有值 start_time = '09:00'end_time = '17:00',Rails 将为您提供这样的时间对象:

start_time = Time.new(2000, 1, 1, 9, 0) # => 2000-01-01 09:00:00 ...
end_time = Time.new(2000, 1, 1, 17, 0)  # => 2000-01-01 17:00:00 ...

现在你说你的约会时间是 DateTime,所以我们称它为 appointment_datetime 并假设它是明天上午 10:30:

appointment_datetime = DateTime.new(2014, 11, 18, 10, 30) # => 2014-11-18 10:30:00 ...

现在重新表述您的问题:我们如何判断 appointment_datetimetime 部分是否在 time 部分之间开始时间结束时间。答案是,我们需要更改 start_timeend_timedate 部分以匹配 date 部分appointment_datetime,或者反过来。因为改变一件事比改变两件事更容易,让我们反过来做,改变 appointment_datetime 以匹配 start_timeend_time(并且,因为这两个是 Time 对象,我们将创建一个 Time 对象):

appointment_time = DateTime.new(2000, 1, 1, appointment_datetime.hour, appointment_datetime.minute)
# => 2000-01-01 10:30:00 ...

现在我们可以直接比较它们了:

if appointment_time >= start_time && appointment_time <= end_time
  puts "Appointment time is good!"
end

# Or, more succinctly:
if (start_time..end_time).cover?(appointment_time)
  puts "Appointment time is good!"
end

当然,您可能希望将所有这些都包装在一个方法中,也许在您的 Location 模型中(同样,我假设它有 start_timeend_time属性):

class Location < ActiveRecord::Base
  # ...

  def appointment_time_good?(appointment_datetime)
    appointment_time = DateTime.new(2000, 1, 1,
                         appointment_datetime.hour, appointment_datetime.minute)

    (start_time..end_time).cover?(appointment_time)
  end
end

location = Location.find(12) # => #<Location id: 12, ...>
location.appointment_time_good?(appointment_time) # => true

希望对您有所帮助!

附言实现这一点的另一种方法是完全放弃日期/时间对象并进行直接数字比较:

def appointment_time_good?(appointment_datetime)
  appointment_hour_min = [ appointment_datetime.hour, appointment_datetime.minute ]

  appointment_hour_min >= [ start_time.hour, start_time.min ]
    && appointment_hour_min <= [ end_time.hour, end_time.min ]
end

关于ruby-on-rails - Ruby on Rails 从日期时间解析时间,而不是字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26938734/

相关文章:

ruby-on-rails - Ruby 中的一切都可以在 Rails 中使用吗?

sql - 在 UNION ALL View 创建中使用 JOIN

ruby - 测试这个的最佳方法是什么?

python - 使用部分数据重新采样和逐年计算

php如何对日期进行操作

ruby-on-rails - $http get to a Rails ApplicationController 针对 angular 1.1+ 构建给出 "HTTP Error 406 Not acceptable"

ruby-on-rails - Mongoid 和 counter_cache 列

ruby-on-rails - rails : Return only objects where all associations meet a condition

ruby-on-rails - 用 Prawn 生成 PDF - 如何访问 Prawn.generate 中的变量?

java - 更改一年的第一周