Background: where I park my car, during the winter it is cleaning day once a week (=parking is not allowed) so I have to move the car before that to avoid getting a ticket. I want to create an iCal reminder about that but the pattern is very complicated.
The season starts Nov 1 and ends May 15.
Only weekdays are cleaning nights.
There are two repeating patterns, yearly (Nov to May) and every 4/6 days (see the examples below for details)
Examples:
I am parked on a street where Wednesday is the cleaning day (i.e., "Wednesday street") so Tuesday evening I move the car to a street that just was cleaned (i.e., a "Tuesday street"). Every week the day I have to move the car is moved forward one day. The repeating pattern is "every 6th day".
However, if I have parked on a Monday street, the situation is different - then I want to move the car on the Friday, not the Sunday. Suddenly the repeating pattern is "every 4th day".
I have read this question Can iCal schedule an event for the first weekday after BYMONTHDAY if BYMONTHDAY is a weekend? and have figured out a couple things:
I can set BYMONTH=11,12,1,2,3,4,5 to limit it to Nov to May.
BYDAY=MO,TU,WE,TH,FR limits it to weekdays
but after that I am stuck. I have been playing around at http://recurrence-expansion-service.appspot.com/ with different combinations but so far without success.
How do I limit it to mid-May?
How do I write a rule that "skips" the weekends when I have parked on a Monday street?
How do I achieve two repeating patterns (a yearly pattern - Nov to May - and a 4/6 day pattern)?
Does Joda support methods to arrive at due date based on working hours
I was able to use
- the holiday calendar
- configurable working days
to arrive at the due date
However, are there methods in joda to set the working hours as 8AM - 5PM and then calculate the due date ?
Sample scenario:
Time taken to complete a task: 10Hrs
Business working hours: 8AM - 4PM (8 Hrs)
Start Date of Task: 21-NOV-2016 ; 9AM
Expected Due Date of Task: 22-NOV-2016 ; 11AM
(i.e 7hrs of work completed on 21st and 3hrs of work completed on following working day which starts at 8AM)
No. From the Joda-Time documentation:
Joda-Time provides a quality replacement for the Java date and time
classes.
It is not within scope to deal with working hours and scheduling.
I'm building a backend at the moment which has a number of objects which have associated dates and times, which repeat at a fixed interval, for instance:
Object 1: Repeat Weekly on Tuesdays at 17:00 UTC.
Object 2: Repeat on the first Wednesday of the month at 12:00 UTC.
Object 3: Repeat every other week (fortnightly) on Friday at 13:00 UTC from January 1, 1970.
I'm looking for the best way to represent this interval in a database, short of generating a calendar file with the object's repeating date/time info in it.
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.
My needs
support business hours that overlap 2 days. Example, a bar can open at 6pm and close at 3am
support multiple opening hours in the same day
support dates were they are closed
support different cases where the open/close hours are different during a certain period of time
Scenarios
In general, the store #1 will have these open hours
Monday, 9am to 12pm and 1pm to 5pm
Tuesday, 9am to 12pm and 1pm to 5pm
Wednesday, 9am to 12pm and 1pm to 5pm
Thursday, 9am to 12pm and 1pm to 9pm
Friday, 9am to 12pm and 1pm to 9pm
Saturday, 10am to 5pm
Sunday, closed
During the month of december, the opens hours are different
Monday, 9am to 12pm and 1pm to 9pm
Tuesday, 9am to 12pm and 1pm to 9pm
Wednesday, 9am to 12pm and 1pm to 9pm
Thursday, 9am to 12pm and 1pm to 9pm
Friday, 9am to 12pm and 1pm to 9pm
Saturday, 10am to 5pm
Sunday, 10am to 5pm
They are closed on these dates:
december 25
january 1
And for some reasons, they have specials cases were the open hours can be different:
july 10, 1pm to 9pm
september 20, 1pm to 9pm
My solution so far
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
...
The problem that i see
I'm not sure that the BeginDate/EndDate should be in that table. Maybe i should have another table that will define Periods and have a foreign key on the OpenHours table that will link to a period.
Where should i define closed dates (holidays)?
Where should i define a special date where the open/close hours is different? Like an override of what is defined?
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.
Im working on the same problem, and so far I have designed a similar approach to yours. But in regards to your questions.
Yes, it helps to move the start and end dates to a related table, for reasons seen in #3.
Closed dates could just be when the open hour is null
Default hours would have no start and end dates. All special hours would have defined start and end dates. The app looks up which groups of dates include todays date. It calculates the interval of the start and end of all groups. The smallest interval wins.
BTW, I am probably going to store my open hour by minute of the day, and leave formatting for later...
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.
I am trying to add a feature on one of my applications. Here is a sample:
Company ABC
Business hours:
Sunday closed
Monday 7am - 5pm
Tuesday 7am - 5pm
Wednesday 7am - 5pm
Thursday 7am - 5pm
Friday 7am - 5pm
Saturday closed
Company DEF
Sunday 10am - 12pm
Monday 8am - 4pm
Tuesday 8am - 4pm
Wednesday 8am - 4pm
Thursday 8am - 4pm
Friday 8am - 4pm
Saturday closed
Now, what I want to do is to have my users be able to search/filter the business hours. For example, only return businesses who are open during Monday 2PM, or Saturday 1PM, or Monday any time.
My idea is to use datetime in SQL Server, but it appears I may need to create 7 columns for each day (Sunday to Saturday) and different columns for Starting time to open to Closing time to open.
The next idea is to make these columns searchable such that I will be able to filter them. for example, if a user searches for Monday 12PM, the search will be Monday (open time) <= (user search, 12pm) <= (close time).
So basically, it will be similar to:
SELECT *
FROM Companies
WHERE [user_search_time] IS "BETWEEN open_time AND close_time WHERE day=[user_search_day]
I'm having a hard time designing this, let alone how to implement it.
Technology used is C#/ASP.Net and SQL Server 2008.
The problem is how to design/implement this feature using the technologies mentioned above.
Any idea/tips will be appreciated. Thanks!
Might want to push this to codereview, or programmers. I think you are on the right path, but instead of adding columns, add a new table. called business_hours
BUSINESS_HOURS
business (company fk)
open_time (datetime)
close_time (datetime)
day (M,T,W,TH,F,S,Sun) // you can do this however u want 1-7 would work as well
Then your query is almost the same as what you have.
SELECT *
FROM
business_hours
WHERE
business = user_company_id
[user_search_time] IS BETWEEN open_time AND close_time and
day=[user_search_day]
Benefits to a table is it's more denormalized and you could support hours that have breaks in them. I could suport 12-2 as well as 5-8. You would just insert a new record and it would work. I am not a big fan of doing all day by doing a range from 12AM to 12PM but it will work, and keep your design simple.