Reputation: 2861
I saw a few examples on stackoverflow on how to design a database table to store business hours but they doesn't answer all my needs. They doesn't support defining different hours depending of the periode of the year and also doesn't support holidays and special time of the year were they can be closed.
In general, the store #1 will have these open hours
During the month of december, the opens hours are different
They are closed on these dates:
And for some reasons, they have specials cases were the open hours can be different:
StoreId BeginDate EndDate DayOfWeek OpenHour Duration
1 2015-01-01 2015-11-30 2 09:00 180
1 2015-01-01 2015-11-30 2 13:00 240
1 2015-01-01 2015-11-30 3 09:00 180
1 2015-01-01 2015-11-30 3 13:00 240
...
1 2015-12-01 2015-12-31 2 09:00 180
1 2015-12-01 2015-12-31 2 13:00 480
1 2015-12-01 2015-12-31 3 09:00 180
1 2015-12-01 2015-12-31 3 13:00 480
...
Upvotes: 3
Views: 3906
Reputation: 11
Im working on the same problem, and so far I have designed a similar approach to yours. But in regards to your questions.
null
BTW, I am probably going to store my open hour by minute of the day, and leave formatting for later...
Upvotes: 1
Reputation: 95761
Stop thinking about rules. Think about rows.
This is dead simple if you just store open hours. PostgreSQL has particularly good support for this kind of thing.
create table business_hours (
open tstzrange primary key,
exclude using gist (open with &&)
);
The exclusion constraint guarantees no overlapping open hours. If it takes two rows per day, a year's data is little more than 700 rows. 100 years of data is only 70k rows. This is the most flexible option, development and testing time is almost nil, and a minimum-wage clerk can verify that the hours you're about to advertise match the hours you're going to be open.
The normal hours
-- The "normal" hours for the week starting Apr 13, 2015 (a Monday).
insert into business_hours values
-- Mon
(tstzrange('2015-04-13 09:00', '2015-04-13 12:00')),
(tstzrange('2015-04-13 13:00', '2015-04-13 17:00')),
-- Tue
(tstzrange('2015-04-14 09:00', '2015-04-14 12:00')),
(tstzrange('2015-04-14 13:00', '2015-04-14 17:00')),
-- Wed
(tstzrange('2015-04-15 09:00', '2015-04-15 12:00')),
(tstzrange('2015-04-15 13:00', '2015-04-15 17:00')),
-- Thu
(tstzrange('2015-04-16 09:00', '2015-04-16 12:00')),
(tstzrange('2015-04-16 13:00', '2015-04-16 21:00')),
-- Fri
(tstzrange('2015-04-17 09:00', '2015-04-17 12:00')),
(tstzrange('2015-04-17 13:00', '2015-04-17 21:00')),
-- Sat
(tstzrange('2015-04-18 10:00', '2015-04-18 17:00'));
-- Sun
-- Closed.
It should be clear from inserting just the "normal" hours that this kind of table can accommodate any kind of logic, whether good or bad.
You can wrap that kind of statement in a stored function in such a way that you can generate a week, a month, or a year of "normal" hours at one time. Update as needed.
In other dbms, you can use two timestamp columns and some check constraints. Checking for overlapping rows would probably have to be done as an exception report rather than as a constraint enforced by the dbms.
create table business_hours (
opens timestamp not null,
closes timestamp not null,
check (closes > opens),
primary key (opens, closes)
);
Using the pair of columns as a primary key lets the optimizer use index-only scans.
Upvotes: 3
Reputation: 48297
I would store the opening hours as RFC 5445 RRules and ExRules.
Some libraries have functions to show the rule in English text.
I find it's easy to generate RRules and ExRules using Google Calendar.
Upvotes: 0