【问题标题】:printing restaurant opening hours from a database table in human readable format using php使用 php 从数据库表中以人类可读格式打印餐厅营业时间
【发布时间】:2011-03-07 11:39:20
【问题描述】:

我有一张桌子,上面列出了餐馆的营业时间。这些列是 id、eateries_id、day_of_week、start_time 和 end_time。每个餐馆都在表格中多次出现,因为每天都有一个单独的条目。有关更多详细信息,请参阅上一个问题: determine if a restaurant is open now (like yelp does) using database, php, js

我现在想知道如何从该表中获取数据并以人类可读的格式打印出来。例如,我不想说“M 1-3,T 1-3,W 1-3,Th 1-3,F 1-8”,而是说“M-Th 1-3,F 1-8” .同样,我想要“M 1-3, 5-8”而不是“M 1-3, M 5-8”。如果没有大量 if 语句的蛮力方法,我怎么能做到这一点?

谢谢。

【问题讨论】:

  • “m 1-3”是如何存储在数据库中的?还是时间戳?
  • 这是一个有趣的问题……我会试着考虑一下。它确实让我想起了一些电路简化,其中涉及卡诺图 :) 我假设您关心高级方法并且可以处理与您的确切表格不匹配的答案。顺便说一句,只允许整小时吗?最早可能的时间和最晚的时间是什么时候?
  • 我会从一个哈希表开始,它将一天映射到小时,例如{'M' : set(1,2,3,5,6,7,8), 'T' : set(1,2,3)}{'M' : 'yyynyyyy'}(表示每个小时(这里从 1 开始)是否可用)。这是确定哪 2 天具有相同时间表的第一步,以及计算和简化开放时间的并集。为什么您的示例中的所有时间都以 1 开头?是不是很晚的餐厅?你关心24小时格式吗?你想要上午和下午在那里吗?是否允许以半小时为增量?
  • 回答问题:时间以TIME格式存储,如12:34:05。日期在单独的列中存储为整数(例如 2 代表星期一)。任何时候到秒都是允许的,尽管我有 99.9% 的把握,没有餐厅的营业时间会涉及秒:)。最早的时间是 00:00:00,最晚的是 23:59:59,所以它是 24 小时格式。当我为用户打印时间时,我想使用 am/pm,尽管一旦我弄清楚其余部分,这种转换应该不难。高级方法很好,我只是不知道从哪里开始解决这个问题!
  • MySQL。这就是你要问的,对吧?

标签: php sql database time


【解决方案1】:

我以为我会对此感到高兴。

测试表

CREATE TABLE `opening_hours` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `eateries_id` int(11) DEFAULT NULL,
  `day_of_week` int(11) DEFAULT NULL,
  `start_time` time DEFAULT NULL,
  `end_time` time DEFAULT NULL,
  PRIMARY KEY (`id`)
) 

测试数据

INSERT INTO `test`.`opening_hours`
(
`eateries_id`,
`day_of_week`,
`start_time`,
`end_time`)
SELECT 2 AS eateries_id, 1 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 2 AS eateries_id, 1 AS day_of_week, '17:00' AS start_time, '20:00' as end_time union all
SELECT 2 AS eateries_id, 2 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 2 AS eateries_id, 2 AS day_of_week, '17:00' AS start_time, '20:00' as end_time union all
SELECT 2 AS eateries_id, 3 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 2 AS eateries_id, 4 AS day_of_week, '13:00' AS start_time, '20:00' as end_time union all
SELECT 2 AS eateries_id, 5 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 2 AS eateries_id, 6 AS day_of_week, '13:00' AS start_time, '20:00' as end_time union all
SELECT 2 AS eateries_id, 7 AS day_of_week, '13:00' AS start_time, '21:00' as end_time
                                                                       union all
SELECT 3 AS eateries_id, 1 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 3 AS eateries_id, 2 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 3 AS eateries_id, 3 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 3 AS eateries_id, 4 AS day_of_week, '13:00' AS start_time, '20:00' as end_time union all
SELECT 3 AS eateries_id, 5 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 3 AS eateries_id, 6 AS day_of_week, '13:00' AS start_time, '20:00' as end_time union all
SELECT 3 AS eateries_id, 7 AS day_of_week, '13:00' AS start_time, '21:00'  as end_time

查看定义以合并每天的营业时间

CREATE VIEW `test`.`groupedhours` 
AS 
  select `test`.`opening_hours`.`eateries_id` AS `eateries_id`,
         `test`.`opening_hours`.`day_of_week` AS `day_of_week`,
         group_concat(concat(date_format(`test`.`opening_hours`.`start_time`,'%l'),' - ',date_format(`test`.`opening_hours`.`end_time`,'%l %p')) order by `test`.`opening_hours`.`start_time` ASC separator ', ') AS `OpeningHours` 
         from `test`.`opening_hours` 
         group by `test`.`opening_hours`.`eateries_id`,`test`.`opening_hours`.`day_of_week`

查询以查找具有相同开放时间的连续日子的“岛屿”(基于 Itzik Ben Gan 的一个)

SET @rownum = NULL;
SET @rownum2 = NULL;



SELECT S.eateries_id, 
concat(CASE WHEN 
S.day_of_week <> E.day_of_week 
    THEN 
    CONCAT(CASE S.day_of_week 
             WHEN 1 THEN 'Su'
             WHEN 2 THEN 'Mo'     
             WHEN 3 THEN 'Tu'     
             WHEN 4 THEN 'We'
             WHEN 5 THEN 'Th'    
             WHEN 6 THEN 'Fr'    
             WHEN 7 THEN 'Sa'  
            End, ' - ')
    ELSE ''        
END,
CASE E.day_of_week 
     WHEN 1 THEN 'Su'
     WHEN 2 THEN 'Mo'     
     WHEN 3 THEN 'Tu'     
     WHEN 4 THEN 'We'
     WHEN 5 THEN 'Th'    
     WHEN 6 THEN 'Fr'    
     WHEN 7 THEN 'Sa'  
End, ' ', S.OpeningHours) AS `Range`
FROM (

SELECT 
    A.day_of_week,
    @rownum := IFNULL(@rownum, 0) + 1  AS rownum,
    A.eateries_id,
    A.OpeningHours
FROM `test`.`groupedhours` as A
WHERE NOT EXISTS(SELECT * FROM `test`.`groupedhours` B
                 WHERE A.eateries_id = B.eateries_id
                  AND A.OpeningHours = B.OpeningHours
                  AND B.day_of_week = A.day_of_week -1) 
ORDER BY eateries_id,day_of_week) AS S

JOIN (
SELECT 
    A.day_of_week,
    @rownum2 := IFNULL(@rownum2, 0) + 1  AS rownum,
    A.eateries_id,
    A.OpeningHours
FROM `test`.`groupedhours` as A 
WHERE NOT EXISTS(SELECT * FROM `test`.`groupedhours` B
                 WHERE A.eateries_id = B.eateries_id
                  AND A.OpeningHours = B.OpeningHours
                  AND B.day_of_week = A.day_of_week + 1)
ORDER BY eateries_id,day_of_week) AS E

ON  S.eateries_id = E.eateries_id AND
    S.OpeningHours = S.OpeningHours AND 
    S.rownum = E.rownum

结果

eateries_id             Range
2                Su - Mo 1 - 3 PM, 5 - 8 PM
2                Tu 1 - 3 PM
2                We 1 - 8 PM
2                Th 1 - 3 PM
2                Fr 1 - 8 PM
2                Sa 1 - 9 PM
3                Su - Tu 1 - 3 PM
3                We 1 - 8 PM
3                Th 1 - 3 PM
3                Fr 1 - 8 PM
3                Sa 1 - 9 PM

【讨论】:

  • 这很有趣。我的观点是 SQL 应该让您快速获取数据,因为这是它最擅长的。最好使用高级语言(我认为)对其进行按摩。不过,您的 SQL 令人印象深刻。
【解决方案2】:

您希望每天合并一堆间隔。坚持使用 24 小时格式(我猜实际上先将其转换为秒),直到您必须将其转换为更人性化的格式。

http://pyinterval.googlecode.com/svn/trunk/html/index.html

问题在于,当您允许秒数时...会错过提前 1 秒关闭的餐厅 :( 也许您需要允许 15 或 5 分钟的增量。如果必须,请对 DB 中的数据进行四舍五入。所以,方法是:使用间隔数据结构,将给定日期的所有间隔合并在一起。现在反转字典。不是将日期映射到间隔,而是将间隔映射到天。现在找到一种方法来智能地表示这些天组。例如,set(1,2,3) 可以显示为“MW”,所以我建议:对于集合{1,2,3,4,5,6,7}(或{1,2,3,4,5})的每个功率集,找到最好的人类表示(手动)。现在硬编码这个逻辑 -将其保存到字典中,该字典将 sorted 字符串(这很重要)如“1235”映射到人类表示如“MW,F”。显示 1-3 , 5-8 很容易,只要您使用上面链接中描述的区间对象。祝您好运!让我知道您遇到了什么问题。

编辑:

这不是他们拥有的最好的例子(不显示重叠区间的联合),但你关心“|”运营商

unioned:

>>> interval[1, 4] | interval[2, 5]
interval([1.0, 5.0])

>>> interval[1, 2] | interval[4, 5]
interval([1.0, 2.0], [4.0, 5.0])

你可以自己实现这个类,但它可能容易出现错误。

【讨论】:

  • 这里我假设 Mon = 1, Tue = 2, ... Sun = 7,因为这是某些国家/地区的惯例 - 一周从周一开始,到周日结束。 cjvlang.com/Dow/SunMon.html
  • 我想我明白你在说什么.. 虽然不会有超过一百天的组合我必须硬编码吗?
  • 不完全,2^5 = 32; 2^7 = 128 :) 但是,这些可以生成。
猜你喜欢
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 2021-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-04
相关资源
最近更新 更多