在数据库中存储营业时间

时间:2009-06-24 05:56:40

标签: database database-design

我目前正在尝试找出在数据库中存储业务时间的最佳方法。

例如:

商家A有以下营业时间

  • 星期一:上午9点至下午5点
  • 星期二:上午9点至下午5点
  • 星期三:上午9点至下午5点
  • 星期四:上午9点至下午5点
  • 星期五:上午9点至下午5点
  • 星期六:上午9点至中午12点
  • 星期日:关闭

目前我的数据模型类似于以下

CREATE TABLE "business_hours" (
    "id" integer NOT NULL PRIMARY KEY,
    "day" varchar(16) NOT NULL,
    "open_time" time,
    "close_time" time
)

其中“日”仅限于代码中一周7天的选择(通过ORM)。要测试某个企业是否在某一天关闭,它会检查open_time和close_time是否为NULL。它通过中间表(多对多关系)与业务相关。

是否有人对此数据库方案有任何建议?关于它的一些事情对我来说似乎不对。

6 个答案:

答案 0 :(得分:45)

总的来说,我认为这没有错。除了...

  1. 我会使用您的本机编程语言使用的任何编号系统(在其库中)将星期几存储为整数。这将减少数据库的大小,并从代码中删除字符串比较。

  2. 我可能会在此表中将外键放到业务表中。这样你就不需要链接表了。

  3. 所以我想我会这样做:

    CREATE TABLE "business_hours" (
         "id" integer NOT NULL PRIMARY KEY,
         "business_id" integer NOT NULL FOREIGN KEY REFERENCES "businesses",
         "day" integer NOT NULL,
         "open_time" time,
         "close_time" time
    )
    

    在我的业务逻辑中,我会强制执行约束,即每个“业务”至少 7个“营业时间”。 (至少因为Jon Skeet是对的,你可能想要休假时间。)虽然你可能想要放松这个约束,只需在业务关闭的几天内停止“营业时间”。

答案 1 :(得分:21)

此架构未涵盖的一种情况是一天中的几个开放时段。例如,当地酒吧的营业时间为12:00-14:30和17:00-23:00。

也许剧院票房可以进行日场演出和晚会演出。

此时您需要决定同一天是否可以有多个条目,或者您是否需要在同一行中表示不同的小时数。

跨越午夜的开放时间怎么样?比如说酒吧营业时间为19:00-02:00。您不能只将开始和结束时间与您想要测试的时间进行比较。

答案 2 :(得分:10)

这取决于您需要存储的内容以及现实世界数据的外观 如果您需要能够确定业务是否在某个时间点开放,那么查询该方案可能有点尴尬。更重要的是,您是否需要迎合中午关闭?

一些选项包括;

  • 一个类似你所拥有的方案,但可以选择在同一天拥有多个句点。它可以满足午休时间的需要,但是会让你查看给定日期的开放时间,比如向用户展示,这会让你很尴尬。
  • 位图风格方法; 9-5的“000000000111111110000000”。这种方法的缺点是你必须选择一个特定的粒度,即整个小时或半小时,或者实际上是几分钟。粒度越精细,人类就越难读取数据。您可以使用按位运算符将此值存储为单个数字而不是整数字符串,但同样会损害易读性。

答案 3 :(得分:8)

我了解到,如果您想让Google数据标记识别您的数据,您应该遵循以下准则:

https://schema.org/openingHours

http://schema.org/OpeningHoursSpecification包含“有效日期”,这对某些商家非常有用。

https://schema.org/docs/search_results.html#q=hours

没有主键你应该没事,除非你允许企业与联盟表共享相同的时间 - 有趣的是最终你将拥有有限数量的组合;我不确定会有多少:p

在我的一个项目中,我使用了列:

  

[uInt] business_id,[uTinyInt] day,[char(11)] timeRange

如果您想支持OpeningHoursSpecification,则需要添加validFrom和validThrough。

时间范围的格式如下:hh:mm-hh:mm

这是一个解析它的函数, 如果将它们作为数据库中的单独列保留,您也可以修改此函数以解析单个打开/关闭。

根据我的经验,我建议您在一天内允许多次,允许告诉他们当天是明确关闭,还是24小时或24/7开放。 我曾经说过,如果数据库中缺少一天,那么业务当天就关闭了。

/**
 * parseTimeRange
 * parses a time range in the form of
 * '08:55-22:00'
 * @param $timeRange 'hh:mm-hh:mm' '08:55-22:00'
 * @return mixed ['hourStart'=>, 'minuteStart'=>, 'hourEnd'=>, 'minuteEnd'=>]
 */
function parseTimeRange($timeRange)
{
    // no validating just parsing
    preg_match('/(?P<hourStart>\d{1,2}):(?P<minuteStart>\d{2})-(?P<hourEnd>\d{1,2}):(?P<minuteEnd>\d{2})/', $timeRange, $matches);

    return $matches;
}

答案 4 :(得分:1)

大多数结果在给定的情况下都可以正常工作,但是如果您的期间要经过数天,那么效果就不会那么好。 8:00 AM〜2:00 AM,那么我建议您使用多周期设计。

   0: [
         id: 1,
         business_id: 1,
         open: true,
         day: 1,
         periods: [
             0: { open: 08:00, close: 23:59 }
         ]
      ],
   1: [
         id: 2,
         business_id: 1,
         open: true,
         day: 2,
         periods: [
             0: { open: 00:00, close: 02:00 }
             1: { open: 08:00, close: 23:59 }
         ]
      ]

答案 5 :(得分:0)

可以考虑通过在月份/月份/月份的月份中添加其他字段来考虑假期。一周中有一些小的子句“最后”可以是例如第4周或第5周,具体取决于年份。