存储营业时间/节假日

Posted

技术标签:

【中文标题】存储营业时间/节假日【英文标题】:Storing Open Hours/Holidays 【发布时间】:2010-12-17 20:27:53 【问题描述】:

您建议使用哪种 SQL 模式来存储营业时间和节假日,以及使用哪种查询来检查餐厅是否营业?现在我有这个:

CREATE TABLE hours (
    "restaurant" integer NOT NULL REFERENCES restaurants ON DELETE CASCADE,
    "dow" integer NOT NULL,
    "open" time NOT NULL,
    "close" time NOT NULL
);
CREATE FUNCTION is_open(r integer) RETURNS boolean AS $$
    DECLARE
        h record;
        t time;
    BEGIN
        SELECT open, close INTO h
        FROM hours WHERE restaurant = r AND dow = EXTRACT(dow FROM now());
        IF NOT FOUND THEN
            RETURN false;
        END IF;
        t := current_time;
        IF h.close <= h.open THEN
            RETURN (t < h.close OR t > h.open);
        ELSE
            RETURN (t > h.open AND t < h.close); 
        END IF;
    END;
$$ LANGUAGE plpgsql;

但这并没有真正起作用,因为例如,一家餐厅可能营业到凌晨 2:00,此时我需要检查之前的 dow

为了让事情变得更复杂,我必须处理假期:

CREATE TABLE holidays (
    "restaurant" integer NOT NULL REFERENCES restauraunts ON DELETE CASCADE,
    "day" date NOT NULL
);

这有同样的问题 - 如果餐厅从 15:30 到 2:00 营业,这意味着他们也从午夜到两点关闭。

我一直无法找到一个干净、优雅的解决方案来解决这个问题(一些混乱的解决方案来了又去)。我需要出去散散步,然后再回来——同时,我想我会让你们试一试。

【问题讨论】:

昨天的重复问题: ***.com/questions/4464898/… 没有回答我的问题,那就是如何处理营业到午夜的商店 添加位字段ClosePastMidnight,如果设置为1,则添加一天。 +1 对 JNK 的建议;另一种方法是检查close 是否在open 之前(如果是,则商店在午夜之后营业)。 打开时间的长短是正确解决问题的唯一方法 【参考方案1】:

回答我自己的问题似乎有点错误,但我发现了一些似乎有效的方法,尽管它很混乱:

CREATE FUNCTION is_open(r integer) RETURNS boolean AS $$
    DECLARE
        t time;
        yesterday date;
        dow_today integer;
        dow_yesterday integer;
    BEGIN
        t := current_time;
        yesterday := current_date - 1;
        dow_today := EXTRACT(dow FROM current_date);
        dow_yesterday := EXTRACT(dow FROM yesterday);
        PERFORM * FROM hours
        WHERE restaurant = r AND ((
            dow = dow_today
            AND NOT EXISTS(
                SELECT * FROM holidays 
                    WHERE restaurant = r AND day = current_date
            ) AND (
                (open < close AND t > open AND t < close)
                OR (open >= close AND t > open)
            )
        ) OR (
            open >= close AND dow = dow_yesterday
            AND NOT EXISTS(
                SELECT * FROM holidays 
                WHERE restaurant = r AND day = yesterday
            ) AND t < close
        ));   
        RETURN FOUND;
    END;
$$ LANGUAGE plpgsql;

【讨论】:

【参考方案2】:

总结一下cmets:

1 - 使用通用查询结构from this question.

2 - 为ClosePastMidnightOpenPastMidnight(以最适合您的思维方式的方式)在您的表格中添加一个位标志,表明下一个日历日关闭,并相应地调整您的逻辑。

【讨论】:

感谢您的帮助,但请参阅我上面的评论【参考方案3】:

您的表格设计缺少信息,当您尝试消除关闭和打开的含义时,这些信息会变得很明显。比如 12 比 2。那是 2 小时还是 14 小时?不做假设就没有办法解决。

使用间隔:

例如,如果您的餐厅从下午 1:30 到凌晨 1:30,这可以检查 now() 是否介于两者之间:

test=# select  
  now() > (now()::date || ' 13:30')::timestamp 
  and now() < (now()::date || ' 13:30')::timestamp + interval '12 hours';

 ?column?
----------
 t
(1 row)

这样只有起点很重要,你不应该有任何环绕问题。

【讨论】:

那是什么符号?我以前从未见过now()::date 另外,这仍然存在 current_date 或 now() 无法匹配hours 表中的dow 列的问题。 检查两次即可。在我的示例中,您构建了正确的日期。选择道琼斯指数。将其减回一个。你能用 now() 构造一个区间吗?用当前的星期几再次检查。 12:00 到 2:00?那只能表示 14 小时,除非您的意思是 12:00 到 14:00... 没有歧义,因为时间是 24 小时格式的。

以上是关于存储营业时间/节假日的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ1588][HNOI2002]营业额统计 无旋Treap

HNOI 2002 营业额统计

营业额统计(bzoj1588)

营业额统计 HYSBZ - 1588

如何在flutter firebase中存储和使用营业时间信息?

HNOI 2002 营业额统计