Мы создаем приложение для планирования, в котором один пользователь может установить свою «общую доступность» на все недели, как показано ниже:
Sunday | Monday | ... | Friday | Saturday
Когда мы просим человека А в Индии указать его «доступность», мы просим его выбрать из выпадающего значения что-то вроде этого:
12:00am 12:30am 01:00am ... 11:30pm
Мы просим его выбрать «ОБО» время «От» (начало) и «Время до» (окончание).
Что мы SAVE в базе данных JUST эти значения (см. Следующий пример):
user_id avail_day from to 1 Sunday 12:00:00 12:15:00 2 Monday 12:00:00 12:15:00
Таким образом, по сути, это выглядит следующим образом (в его ЛОКАЛЬНОМ часовом поясе)
(A) Sunday | Monday | ... | Friday | Saturday ----------------------------------------- | | | | 8:30am to 10:30am
Как отдельная информация, мы знаем, что он выбрал работу в IST (индийское стандартное время), в настоящее время GMT + 5:30 часов, поэтому мы можем предположить, что значения, которые он выбирает, относятся к часовому поясу, который он сейчас в.
Теперь, для человека B на Восточном побережье, который сейчас GMT-4 часа (EDT), на этот раз будет фактически
Friday, 23:00:00 to Saturday, 01:00:00
Нам нужна помощь в определении того, как:
(a) конвертировать более раннее «текстовое значение» лица A в IST в локальное значение лица EST (ПРИМЕЧАНИЕ, что мы знаем JUST день и часы доступности как значения TEXT)
(b) И тогда нам нужно выяснить, как отобразить его на «стандартной неделе», начинающейся в воскресенье и заканчивая в субботу. То, что мы хотим отобразить, должно быть примерно таким:
(B) Sunday | Monday | ... | Friday | Saturday -------------------------------------------------------------- | | | 11:00pm to 12:00am | 12:00am to 1:00am
Любые умные способы преобразования (A) в (B)?
Код Artefacto превращен в общую функцию (вариант 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; }
Ваш вопрос не имеет смысла, учитывая будние дни в вакууме. Эти будни должны быть фактическими днями, потому что правила преобразования времени изменяются в течение года (DST) и на протяжении многих лет (политики иногда изменяют часовые пояса и / или дату начала / окончания DST).
Тем не менее, предположим, что у вас есть недельный план доступности на первую неделю августа, здесь определяется как неделя с 1 августа по 7 августа 2010 года:
<?php $tz1 = new DateTimezone("Asia/Calcutta"); $indiaAvail = array( new DatePeriod(new DateTime("2010-08-01 10:00:00", $tz1), new DateInterval("PT2H15M"), 1), new DatePeriod(new DateTime("2010-08-07 03:00:00", $tz1), new DateInterval("PT8H"), 1), ); $tz2 = new DateTimezone("America/New_York"); //convert periods: $times = array_map( function (DatePeriod $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"); } } print_r($res);
дает
массив ( [Sunday] => Array ( [0] => 12:30 утра до 2:45 утра ) [Пятница] => Массив ( [0] => с 17:30 до 23:59 ) [Суббота] => Массив ( [0] => 12:00 с 1:30 утра ) )
Это может привести к тому же дни недели корзины, которые на самом деле разные дни, но, очевидно, нет способа избежать этого, не указывая явным образом день (или добавляя что-то вроде «Суббота (неделя после)» и «Суббота (неделя раньше)». быть тем, что вы хотите.
Как насчет этого:
Пакет Pear :: Date может помочь вам в этом:
http://www.go4expert.com/forums/showthread.php?t=3494
Надеюсь, это поможет, Мануэль
Используйте встроенный класс времени DateTime для преобразования часовых поясов. Сохраните данные в формате UTC в базе данных. При отображении стандартного недельного графика используйте локальный часовой пояс. Чтобы обрабатывать ± 23 часа разницы в часовом поясе, вам нужно будет запросить 9 дней (± 1 дней) из БД перед конверсией.
Изменить. Чтобы преобразовать время в локальное время текущего пользователя, вам нужно получить часовой пояс для каждого события. Присоедините запланированные события к пользовательской информации для пользователя, который сделал это событие. Таким образом, у вас будет часовой пояс, из которого можно конвертировать в часовой пояс пользователя.
Следующий псевдоязычный PHP покажет:
$usersTZ = new DateTimeZone('EDT'); $now = new DateTime("now", $usersTZ); $today = $now->format("Ymd"); $sql = "SELECT A.date, A.start, A.end, B.tz FROM schedule A JOIN users B ON (schedule.user_id = users.user_id) WHERE A.date BETWEEN '$sunday_minus_1_day' AND '$saturday_plus_1_day' ORDER BY A.date, A.start"; foreach ($db->dothequery($sql) as $event) { $eventTZ = new DateTimeZone($event['tz']); $eventStartDate = new DateTime("$today {$event['start']}", $eventTZ); $eventStartDate->setTimeZone($usersTZ); $eventEndDate = /* do the same for the end date */ if ($eventStartDate->format("Ymd") != $eventEndDate->format("Ymd")) { /* create 2 events */ } else { /* save the event to list of events with the new start and end times */ } } /* sort events, their order may be different now */
Конечно, все было бы намного проще, если бы вы могли сохранить время начала и окончания с TZ в БД и позволить БД выполнить всю тяжелую работу для вас.