Question

In my application users should be able to define dates when they are available. Ie. user joe may define he's available:
- at every monday, wednesday and sunday between 15:00 and 17:00 from 1.09.2009 to 15.11.2009. - at 2.09.2009 between 12:00 and 14:00 and so on...

Dates may be defined maximum 1 year in future.

Users may add, edit and delete defined dates.

Other users may search available users ie. - find all users available 8.09.2009 at 15:30

The problem is how to design sql tables, which allow creating and editing cyclic dates and efficient searching.

I'm using postgresql but rather looking for any guidelines. Maybe someone has experience with similar problem?

Thanks in advance

Was it helpful?

Solution

When I've dealt with data like this before, I've taken a "rules" approach similar to this to accomodate by-day scheduling and block scheduling:

CREATE TABLE availability_rules (
  id SERIAL UNIQUE,
  user_id NOT NULL REFERENCES users(id),
  day_of_week INTEGER CONSTRAINT valid_day_of_week CHECK (day_of_week BETWEEN 0 and 6)
  start_time TIME,
  start_date DATE,
  end_time TIME,
  end_date DATE
);

Note: You would need to add additional constraints to the rules table to make sure that end_date + end_time >= start_date + start_time, etc.

Then, you can create an "availability" view to generate a normalized schedule with user_id, date, start_time, and end_time. Using 8.4, this is easy with the new generate_series datetime capabilities. (http://www.postgresql.org/docs/current/static/functions-srf.html) It is easy enough to write a function that does the same thing if you're on 8.3 or earlier.

OTHER TIPS

Option 1

You would store availability with 3 columns (assuming a single id col to identify a user)

availability_start, availability_end, user_id

searching based on a datetime would then be something like

select
  user_id
from
  availability
where
  desired_datetime > availability_start
and
  desired_datetime < availability_end

you may want to remove past dates depending on the functionality you want to offer. Obviously you'll need to decide how far into the future to store dates based on peoples cyclic date definitions.

Option 2

If it is always as simple as choosing individual days of the week and times for those days. You could store cyclic dates as

user_id, day_of_week, availability_time_start, availability_time_end

The start and end times need no date component to them. Searching based on a day of the week and a time would be something like

select
  user_id
from
  availability
where
  desired_day_of_week = day_of_week
and 
  desired_time > availability_time_start
and
  desired_time < availability_time_end

As an aside, there are libraries which assist with creating such recurring date patterns, where I work we use this (Java), there may well be RFC 2445 implementations in a language suitable to you.

If you use something like that then you won't be storing actual dates, but just the details of the recurrence patterns which won't really help you with your problem. We store these details by pretty simply taking the values from the recurrence definition and persisting them to the db one field to one column.

You could then also store the dates/times for some defined amount of time in the future and recalculate these on any changes to the recurrence definitions, this could obviously become quite a large operation depending on how many schedules people have and how far in the future you want to store data.

You will want to store a users availability in the database and use a programming language to check the availability rather than having any complicated logic in the database itself. Using an ORM tool would make this easier.

A users availability would consist of a list of datetime pairs.

What you could do is have a table that has the following design:

Availability
  - userId, Foreign key to user table
  - startDate, datetime
  - endDate, datetime
  - startTime, datetime
  - endTime, datetime
  - monday, bit
  - tuesday, bit
  - wednesday, bit
  - thursday, bit
  - friday, bit
  - saturday, bit
  - sunday, bit

Now you can check for availability at certain weekdays with the following (MSSQL yntax)

SELECT * FROM User u WHERE EXISTS(
    SELECT 1 FROM Availability WHERE userId = u.id AND
    @startDate >= startDate AND @endDate <= endDate AND
    @startTime >= startTime AND @endTime <= endTime AND
    (monday = 1 OR tuesday = 1)
)

Which would give you all users that are available between @startDate and @endDate at mondays or tuesdays between @startTime and @endTime.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top