We are building a scheduling application wherein one user may set his "general availability" for all weeks like the following:
Sunday | Monday | ... | Friday | Saturday
When we ask a person A in India to indicate his "availability", we ask him to select from a drop down of values something like this:
12:00am
12:30am
01:00am
...
11:30pm
We ask him to select BOTH the "From" time (starting) and the "Till" time (ending).
What we SAVE in the database is JUST these values (see the following example):
user_id avail_day from to
1 Sunday 12:00:00 12:15:00
2 Monday 12:00:00 12:15:00
So, in essence, it looks like the following (in his LOCAL time zone)
(A)
Sunday | Monday | ... | Friday | Saturday
-----------------------------------------
| | | | 8:30am to 10:30am
As a separate piece of information, we know that he has selected to work in the IST (Indian Standard Time), which is presently GMT + 5:30 hours, so we can assume that the values he chooses are FOR the time zone he's presently in.
Now, for a person B on the East Coast, which is presently GMT - 4 hours (EDT), this time would be actually
Friday, 23:00:00 to Saturday, 01:00:00
We need help in figuring out how to:
(a) convert the earlier "text value" of the person A in IST to the local value of the EST person (NOTE that we know JUST the day and hours of availability as TEXT values)
(b) AND, then, we need to figure out how to display it on a "Standard week" beginning on a Sunday and ending on a Saturday.
What we want displayed should be something like this:
(B)
Sunday | Monday | ... | Friday | Saturday
--------------------------------------------------------------
| | | 11:00pm to 12:00am | 12:00am to 1:00am
Any smart ways of converting (A) into (B)?
Artefacto's code made into a generic function (Revision 2)
// This function should be used relative to a "from_date"
// The $from_timebegin and $from_timeend MUST be for the same day, not rolling over to the next
function shift_timezones_onweek3($from_timezone, $from_date, $from_timebegin, $from_timeend, $to_timezone)
{
$tz1 = new DateTimezone($from_timezone);
$datetime1 = new DateTime("$from_date $from_timebegin", $tz1);
$datetime2 = new DateTime("$from_date $from_timeend", $tz1);
$interval = $datetime1->diff($datetime2);
$indiaAvail = array(
array($datetime1, $datetime2)
);
$tz2 = new DateTimezone($to_timezone);
//convert periods:
$times = array_map(
function (array $p) use ($tz2) {
$res = array();
foreach ($p as $d) {
$res[] = $d->setTimezone($tz2);
}
return $res;
},
$indiaAvail
);
$res = array();
foreach ($times as $t) {
$t1 = reset($t);
$t2 = next($t);
if ($t1->format("d") == $t2->format("d")) {
$res[$t1->format("l")][] = $t1->format("g:ia") . " to ".
$t2->format("g:ia");
}
else {
$res[$t1->format("l")][] = $t1->format("g:ia") . " to 11:59pm";
$res[$t2->format("l")][] = "12:00am to ". $t2->format("g:ia");
}
}
return $res;
}
Use PHP's build-in DateTime class to do timezone conversions. Save the data in UTC to the database. When displaying your standard week schedule, use local timezone. To handle ±23 hours of timezone differences, you'll have to query 9 days (±1 days) from the DB before conversion.
Edit: To convert times to current user's local time, you need to get the timezone of each event. Join the scheduled events to user information for the user who made the event. This way you'll have the timezone from which to convert to the user's timezone.
The following pseudoish PHP will show:
Of course, it would all be a lot simpler if you could save the start and end times with TZ to the DB and let the DB do all the hard work for you.
Your question doesn't make sense considering weekdays in the vacuum. These weekdays must be actual days, because the time conversion rules change along the year (DST) and through the years (politicians sometimes change the timezones and/or the date in which DST starts/ends).
That said, let's say you have you have a week availability plan for the first week of August, here defined as the week Aug 1 to Aug 7 2010:
gives
This may put in the same basket weekdays that are actually different days, but there's obviously no way to avoid it without explicitly indicating the day (or adding something like "Saturday (week after)" and "Saturday (week before)". This appears to be what you want, though.
How about this:
The Pear::Date package may help you doing this:
http://www.go4expert.com/forums/showthread.php?t=3494
Hope this helps, Manuel