我正在编写一个跟踪学校课程的应用程序。
我需要存储时间表。例如:周一至周五上午 8 点至上午 11 点。
我正在考虑使用一个简单的字符串列,但稍后我需要进行时间计算。
例如,我需要存储 8am 的表示,例如 start_at:8am end_at:11am
那么我应该如何存储时间呢?我应该使用什么数据类型?我应该存储开始时间和秒数或分钟数,然后从那里计算吗?还是有更简单的方法?
我使用 MySQL 进行生产,使用 SQLite 进行开发。
我正在编写一个跟踪学校课程的应用程序。
我需要存储时间表。例如:周一至周五上午 8 点至上午 11 点。
我正在考虑使用一个简单的字符串列,但稍后我需要进行时间计算。
例如,我需要存储 8am 的表示,例如 start_at:8am end_at:11am
那么我应该如何存储时间呢?我应该使用什么数据类型?我应该存储开始时间和秒数或分钟数,然后从那里计算吗?还是有更简单的方法?
我使用 MySQL 进行生产,使用 SQLite 进行开发。
我最近制作了一个必须解决这个问题的应用程序。我决定在一个简单的营业时间模型中存储 open_at 和 closed_at 从午夜开始的几秒钟内。ActiveSupport 包括这个方便的帮助程序,用于查找自午夜以来的时间(以秒为单位):
Time.now.seconds_since_midnight
这样我可以做一个简单的查询来确定场地是否开放:
BusinessHour.where("open_at > ? and close_at < ?", Time.now.seconds_since_midnight, Time.now.seconds_since_midnight)
任何使这更好的提示将不胜感激=)
如果您使用的是 Postgresql,则可以使用time
仅是一天中的时间而没有日期的列类型。然后可以查询
Event.where("start_time > '10:00:00' and end_time < '12:00:00'")
也许 MySQL 有类似的东西
查看 Rails 4 的 gem 'tod'或 Rails 3 的 Time_of_Day。它们都解决了在使用 Active Record 模型时将时间存储在数据库中的问题。
SQL 有时间数据类型,但 Ruby 没有。Active Record 通过使用 Ruby 的 Time 类在规范日期 2000-01-01 上表示时间属性来解决这种差异。所有时间属性都被任意分配相同的日期。虽然可以毫无问题地相互比较属性(日期相同),但当您尝试将它们与其他 Time 实例进行比较时会出现错误。只需对“10:05”之类的字符串使用 Time.parse 即可将今天的日期添加到输出中。
Lailson Bandeira 为这个问题创建了一个已创建的解决方案,即 Rails 3 的 Time_of_Day gem。不幸的是,该 gem 不再维护。请改用 Jack Christensen 的“tod”宝石。它就像一个魅力。
这颗红宝石将一天中的时间转换为自午夜以来的秒数。秒值存储在数据库中,可用于计算和验证。
定义时间属性:
class BusinessHour < ActiveRecord::Base
time_of_day_attr :opening, :closing
end
将设置字符串时的时间转换为自午夜以来的秒数:
business_hour = BusinessHour.new(opening: '9:00', closing: '17:00')
business_hour.opening
=> 32400
business_hour.closing
=> 61200
要转换回一天中的时间:
TimeOfDayAttr.l(business_hour.opening)
=> '9:00'
TimeOfDayAttr.l(business_hour.closing)
=> '17:00'
您也可以在整点省略分钟:
TimeOfDayAttr.l(business_hour.opening, omit_minutes_at_full_hour: true)
=> '9'
我将使用两个整数列将开始时间和持续时间存储在数据库中。
通过检索这两个值,您可以将开始时间转换为(假设您已经知道这一天:
# assuming date is the date of the day, datetime will hold the start time
datetime = date.change({:hour => your_stored_hour_value , :min => 0 , :sec => 0 })
# calculating the end time
end_time = datetime + your_stored_duration.seconds
否则,看看Chronic。宝石使处理时间更容易一些。请注意,该change
方法是 rails 的一部分,在纯 Ruby 中不可用。
DateTime
可以在此处找到有关纯 Ruby的文档。
此外,无论您做什么,都不要开始以 12 小时格式存储日期/时间,您可以I18n
在 Rails 中使用来转换时间:
I18n.l Time.now, :format => "%I.%m %p", :locale => :"en"
I18n.l Time.now + 12.hours, :format => "%I.%m %p", :locale => :"en"
您还可以从此表示法中获得,您可以将持续时间存储为小时,如果需要,您可以通过以下方式轻松转换它们:
your_stored_value.hours
如果存储为整数,即。
不要为此担心特定的数据类型。一个简单的解决方案是:
在数据库中,为start_time添加一个整数类型列,为end_time添加另一个列。每个都将存储自午夜以来的分钟数。
例如:上午 8:30 将存储为 510 (8*60+30)
在表单中,创建一个选择字段(下拉菜单),以时间格式显示所有可用时间:
例如:上午 10 点、上午 10:30 等。
但是保存在数据库中的实际字段值是它们的整数等价物:
例如:600、630 等等(按照上面的示例)
从 SQLite 3网站,
“SQLite 没有专门用于存储日期和/或时间的存储类。相反,SQLite 的内置日期和时间函数能够将日期和时间存储为 TEXT、REAL 或 INTEGER 值:
TEXT 作为 ISO8601 字符串(“YYYY-MM-DD HH:MM:SS.SSS”)。REAL 作为儒略日数字,根据预测的公历,自公元前 4714 年 11 月 24 日格林威治中午以来的天数。INTEGER 作为 Unix 时间,自 1970-01-01 00:00:00 UTC 以来的秒数。应用程序可以选择以任何这些格式存储日期和时间,并使用内置的日期和时间函数在格式之间自由转换。”
然后,您可以使用此处列出的日期和时间函数来操作这些值。
我假设您正在为此使用某种数据库。如果您使用的是 MySQL 或 Postgresql,则可以使用datetime
列类型,Ruby/RailsTime
在读取/写入数据库时会自动将其转换为对象。我不确定 sqlite 是否有类似的东西,但我想它可能有。