Intereting Posts

Организация дат со временем и часовыми поясами. (Преобразование в точную метку времени.)

Я собираюсь в своем мозгу пару дней со следующей загадкой.

У меня в основном следующая сложная таблица mySQL:

| ID | TITLE | DESCRIPTION | EVENT | DATE | |----|--------------|-------------------|-------|-------------------------| | 1 | Big painting | 3-day work | No | 03/10/2013 | | 2 | Meeting | With reps. | Yes | 02/15/2013 09:00 -05:00 | | 3 | Presentation | 5 paintings | Yes | 08/02/2013 22:00 +02:00 | | 4 | Round paint. | One week | No | 04/05/2013 | | 5 | Conference | On Picasso | Yes | 04/22/2013 18:00 -05:00 | 

(EDIT: Возможно, мне нужно уточнить, что столбец DATE не задан как DATE или DATETIME [из-за необходимости включать Timezone в данные], а скорее как VARCHAR, поэтому организация с самого начала сложна.)

Как вы можете видеть, это таблица, которая включает в себя все элементы «Что нового» для художника, например. Идея заключается в том, что на этом веб-сайте художника PHP выведет ценности, чтобы отобразить их как «What's New».

Все основные положения есть, но я попадаю в ловушку.

    Сначала я хотел бы фильтровать и заказывать свои данные на этапе SELECT, но у меня были проблемы с этим. Как вы можете видеть, бот событиям и событиям, не связанным с событиями, относятся даты, но элементы, не связанные с событием, просто используют их для организации общих данных. Конкретная дата и время важны только для событий, потому что таким образом пользователь сможет узнать, когда происходят эти вещи. Таким образом, основная идея заключалась бы в том, чтобы вывести из таблицы определенное количество ПОСЛЕДНИХ пунктов. Таким образом, все элементы будут считаны из таблицы, помещены в порядке DATE, а затем, скажем, из них 20 будут выведены.

    Как я уже сказал, изначально я делал это на стадии SELECT, но я думаю, что это может быть слишком сложно. Поэтому я просто извлек все элементы и установил после них PHP-код, чтобы отфильтровать их.

    Поэтому появляется ошибка, когда я пытаюсь заказать даты. Я пытаюсь преобразовать даты в timestamps для процесса заказа, а затем вернуться к датам для отображения. Тем не менее, я не могу заставить преобразовать дату или временную метку (или оба) для работы. У меня всегда заканчиваются даты, которые отличаются от тех, с которых я начинал.

    Как вы можете видеть, все это становится более сложным из-за часовых поясов, которые очень важны, поскольку пользователь должен знать, где эти вещи происходят или, точнее, в какое время в зависимости от того, где они происходят.

    Я пробовал просто конвертировать туда и обратно так:

      $timestamped = strtotime($date); $datetimed = date('m/d/Y h:i P',$timestamped); 

    И это не работает, поэтому я догадался, что это связано с форматом даты, который я использую в своей таблице.

    Итак, я попробовал это:

      $var = DateTime::createFromFormat('m/d/YH:i P',$date)->getTimestamp(); 

    Безрезультатно, пока …

    Я думаю, что, возможно, я должен установить временную метку в начале процесса, то есть при вставке элементов данных. Но, здесь также, мне нужно будет преобразовать «человеческую» дату в метку времени, и если я не смогу правильно это сделать, ничто не будет работать должным образом.

    Я понимаю, что этот вопрос сложный, и, возможно, мое объяснение не самое ясное! Возможно, пример вывода может помочь. То, что я пытаюсь достичь, – это «Что нового», тиккер новостей, который включает в себя список вещей, которые происходят: некоторые из них – только информация (например, обновления статуса, скажем) без видимых дат (здесь даты относятся только к внутренней организации , здесь появляется столбец EVENT, поскольку он фильтрует, какие элементы должны показывать свои даты, а какие не должны), другие, фактические события, к которым приглашен пользователь, и которые отображают свои даты для пользователя. У меня даже есть код, который вычисляет, является ли дата и время в прошлом или будущем, чтобы отобразить тег «ВВЕРХ» для тех событий, которые еще не прошли. Однако у меня возникли проблемы с обработкой дат и их упорядочением.

    Это то, что этот пример должен быть более или менее похож на конец:

    Пример готовой продукции

    Любая помощь будет НАСТОЯТЕЛЬНО оценена! (Как и отзывы о том, что вы, ребята, думаете, будет самым практичным и самым чистым / элегантным / профессиональным способом обработки этого процесса поиска / организации данных … если при вводе данных, если на этапе mySQL SELECT, если позже и т. Д. )

    PS Я могу добавить, что в той же таблице я обрабатываю другие данные. Эти специфические данные «Что нового» выбирают с помощью функции SELECT, которая ищет определенный столбец WHATSNEW, чтобы иметь значение TRUE в любой строке, которая будет извлекаться для этого конкретного «What's New» тикера новостей.


    РЕШЕНИЕ (НЕ ОТВЕТ)

    Поскольку вопрос состоял в том, чтобы организовать время и временные интервалы как одну строку, так сказать, тогда я не уверен, что могу отметить любой из этих двух великих ответов как правильный для этой конкретной проблемы. То, что я делал, делало снятие временных интервалов и помещение их в отдельный столбец. Затем я отформатировал свой столбец даты как Datetime. Поэтому я решил это, потому что mySQL Select мог позаботиться о заказе для меня. Теперь, о часовых поясах, я в конечном итоге обманывал: я полагал, что наш «художник» не может быть в двух событиях в двух разных часовых поясах одновременно, так что, действительно, довольно маловероятно, что нам нужно будет заказать два события, которые так близки друг к другу, что временные точки каждого из них имеют реальную разницу, которая на первом месте. Поэтому я просто заказываю сам по датам, а затем взбиваю фрагмент, чтобы позаботиться о часовых поясах и превратить их в «GMT + 1», «GMT-5», чтобы пользователи знали, где находится это место местное время. Я закончил использование DateTime::createFromFormat()->getOffset() , который я теперь видел, когда мой второй ответчик рекомендовал, и сказал, что я на правильном пути, поэтому я счастлив, что я его там оставил. Чтобы уточните это, я добавил столбец «Место», где веб-мастер сможет указать город, скажем «Париж», скажем «Лондон» и т. д. Таким образом, у пользователя будет нечто похожее на то, что показано в моем примере, за исключением того, что он скажет ... (Paris, GMT+1) и так далее.

    В любом случае, для тех, у кого есть одна и та же проблема, и заканчивает тем, что думает о одних и тех же вещах, и что этот выход более практичен, вот в чем заключается суть кода, в котором я оказался. Остальное – это просто «заполнение». Наслаждайтесь! И благодаря любимым людям, которые так любезны отнять время со своих дней, чтобы помочь мне найти решение по этому вопросу! (Может быть, у меня есть дополнительные } … извините за это. Повторное форматирование, когда вы вставляете его в SO, действительно утомительно! Я дважды пересмотрел код и не могу найти никаких проблем.)

     if(isset($item) && $item['event'] == '1') { $event = $item['event']; $date = $item['date']; $date_array = date_parse($date); $minute = $date_array['minute']; if($minute<10) { $minute = '0'.$minute; } $timezone = $item['timezone']; if($timezone!=='') { $timezone = DateTime::createFromFormat('P',$timezone)->getOffset(); $timezone = $timezone/-3600; if($timezone<0) { $timezone = $timezone; } else if($timezone==0) { $timezone = '-0'; } else { $timezone = '+'.$timezone; } $timezone = 'Etc/GMT'.$timezone; $timezone_real = $item['timezone']; $timezone_real = DateTime::createFromFormat('P',$timezone)->getOffset(); $timezone_real = $timezone_real/-3600; if($timezone_real<0) { $timezone_real = str_replace('-','+',$timezone_real);//.':00'; } else if($timezone_real==0) { $timezone_real = '+0';//:00'; } else { $timezone_real = '-'.$timezone_real;//.':00'; } $timezone_real = 'GMT'.$timezone_real; date_default_timezone_set($timezone); } $today = date('n/j/YG:i', time()); $today = strtotime($today); $event_date = $date_array['month'].'/'.$date_array['day'].'/'.$date_array['year'].' '.$date_array['hour'].':'.$minute; $event_date_unformatted = strtotime($event_date); if($date_array['hour'] == '0') { $hour_convert = '12'; $hour_suffix = 'am'; } else if($date_array['hour']<12) { $hour_convert = $date_array['hour']; $hour_suffix = 'am'; } else if($date_array['hour'] == '12') { $hour_convert = $date_array['hour']; $hour_suffix = 'pm'; } else { $hour_convert = $date_array['hour']-12; $hour_suffix = 'pm'; } $date_convert = array('1' => 'January', '2' => 'February', '3' => 'March', '4' => 'April', '5' => 'May', '6' => 'June', '7' => 'July', '8' => 'August', '9' => 'September', '10' => 'October', '11' => 'November', '12' => 'December'); $event_date = $date_convert[$date_array['month']].' '.$date_array['day'].', '.$date_array['year'].', '.$hour_convert.':'.$minute.' '.$hour_suffix; if(($event_date_unformatted-$today)>0) { echo '<h5>UPCOMING:</h5>'; echo '<h6>'.$item['location'].', '.$event_date.' <sup>('.$timezone_real.')</sup></h6>'; } } 

    Related of "Организация дат со временем и часовыми поясами. (Преобразование в точную метку времени.)"

    Вы говорите, что DateTime::createFromFormat не работает, но не сообщите нам, что такое сообщение об ошибке. Я предполагаю, потому что ваша строка формата не соответствует формату, который вы передаете. См. Страницу руководства для приемлемых форматов.

    Сказав это, я считаю, что вы были на правильном пути с DateTime::createFromFormat , это подход, который я бы взял. У кого-то с более мощным SQL foo, чем у меня, возможно, возникнет способ сделать это с помощью запроса, но вот мой чисто PHP-подход для получения массива событий, отсортированных по дате:

     //first we connect to our database $dsn = 'mysql:dbname=stackoverflow;host=127.0.0.1'; $user = '********'; $password = '*********'; try { $dbh = new PDO($dsn, $user, $password); } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); } //then we get our list of events from the table $sql = "select * from datetable"; $select = $dbh->prepare($sql); $select->execute(); //We now have an associative array of events, but in the wrong order. $results = $select->fetchAll(PDO::FETCH_ASSOC); $events = array(); //we want to sort on date, so lets get the dates into a format we can sort on foreach($results as $result){ $event = $result; $date = explode(' ', $result['date']); if(isset($date[1])){ $event['date'] = \DateTime::createFromFormat('m/d/YH:i', $date[0] . ' ' . $date[1]); $event['tz'] = $date[2]; } else { $event['date'] = \DateTime::createFromFormat('m/d/Y', $date[0]); } $events[] = $event; } //our sorting function $byDate = function(array $eventA, array $eventB){ return $eventB['date'] > $eventA['date'] ? -1 : 1; }; //sort the array usort($events, $byDate); //we now have our array sorted correctly var_dump($events); 

    Результат: –

     array (size=5) 0 => array (size=6) 'id' => string '2' (length=1) 'title' => string 'Meeting' (length=7) 'description' => string 'With reps.' (length=10) 'event' => string 'Yes' (length=3) 'date' => object(DateTime)[4] public 'date' => string '2013-02-15 09:00:00' (length=19) public 'timezone_type' => int 3 public 'timezone' => string 'Europe/London' (length=13) 'tz' => string '-05:00' (length=6) 1 => array (size=5) 'id' => string '1' (length=1) 'title' => string 'Big painting' (length=12) 'description' => string '3-day work' (length=10) 'event' => string 'No' (length=2) 'date' => object(DateTime)[3] public 'date' => string '2013-03-10 23:18:05' (length=19) public 'timezone_type' => int 3 public 'timezone' => string 'Europe/London' (length=13) 2 => array (size=5) 'id' => string '4' (length=1) 'title' => string 'Round paint.' (length=12) 'description' => string 'One week' (length=8) 'event' => string 'No' (length=2) 'date' => object(DateTime)[6] public 'date' => string '2013-04-05 23:18:05' (length=19) public 'timezone_type' => int 3 public 'timezone' => string 'Europe/London' (length=13) 3 => array (size=6) 'id' => string '5' (length=1) 'title' => string 'Conference' (length=10) 'description' => string 'On Picasso' (length=10) 'event' => string 'Yes' (length=3) 'date' => object(DateTime)[7] public 'date' => string '2013-04-22 18:00:00' (length=19) public 'timezone_type' => int 3 public 'timezone' => string 'Europe/London' (length=13) 'tz' => string '-05:00' (length=6) 4 => array (size=6) 'id' => string '3' (length=1) 'title' => string 'Presentation' (length=12) 'description' => string '5 paintings' (length=11) 'event' => string 'Yes' (length=3) 'date' => object(DateTime)[5] public 'date' => string '2013-08-02 22:00:00' (length=19) public 'timezone_type' => int 3 public 'timezone' => string 'Europe/London' (length=13) 'tz' => string '+02:00' (length=6) 

    Основной вопрос, который по-прежнему остается нерешенным, – это временные интервалы. В вашей базе данных хранятся смещения, а не часовые пояса. На SO есть некоторые вопросы по этому вопросу ( например , это так), поэтому я не буду удваивать эти усилия здесь, но смещения доступны в массиве, если вы найдете для них способ.

    В ваших комментариях я заметил, что вы рассматриваете возможность добавления столбца часового пояса, это хорошая идея. Тем не менее, я бы посоветовал вам хранить их как строки TZ из этого списка , затем они могут быть переданы непосредственно в конструктор DateTimeZone, чтобы дать вам преимущества, такие как учет летнего сбережения и т. Д.

    SQL-запрос должен быть

      $data= mysql_query( "SELECT * FROM (table name) ORDER BY date ASC") 

    Я добавляю алгоритм с учетом ваших последних комментариев.

    Во-первых: Тип данных для столбца DATE должен быть однородным. Если он имеет формат даты и времени, он должен правильно упорядочить данные.

    Эта ссылка предоставляет вам полный список функций даты и времени. Стоит прочитать, чтобы дать вам лучшее представление о решении вашей проблемы.

    http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html

    См. Эту ссылку, которая касается правильного форматирования дат – (однако для более чистой таблицы я предлагаю вам иметь только один формат, который будет принят в вашу таблицу):

    Порядок по дате поступления – месяц, день и год

    Для использования в Интернете: я думаю, что вам нужно либо «стандартизировать» часовые пояса. Временная метка может быть создана в пределах того же часового пояса для всех событий, пользователь может просматривать эти времена в соответствии с их выбранной временной зоной., Следовательно, все времена настраиваются для каждого пользователя.

    эта ссылка обсуждает переменные сеанса для часовых поясов: http://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html

    Часовой пояс за соединение. Каждый клиент, который подключается, имеет свой собственный часовой пояс, заданный переменной session_zone. Первоначально переменная сеанса принимает свое значение из глобальной переменной time_zone, но клиент может изменить свой собственный часовой пояс с помощью этого оператора:

    mysql> SET time_zone = часовой пояс;

    Однако для локального использования, когда лицо может получить листовку обновлений, с целью их посещения, вам необходимо отобразить часовой пояс для этой местности с указанной местностью. Добавление, например, GMT +2.00, не дает многим пользователям указание времени со ссылкой на их собственный часовой пояс, они, как правило, должны сами его преобразовать. Это добавляет разочарования для пользователя. Было бы целесообразно преобразовать его для них или предложить некоторое объяснение различий во времени, поэтому пользователь может получить четкое представление о том, «когда» это событие происходит в отношении их часового пояса.

    Чтобы иметь дело с часовыми поясами, стоит перейти по этой ссылке: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_convert-tz

    CONVERT_TZ () преобразует значение dt-времени dt из часового пояса, заданного from_tz, в часовой пояс, заданный to_tz, и возвращает результирующее значение. Часовой пояс указан, как описано в Разделе 10.6 «Поддержка часовых поясов сервера MySQL». Эта функция возвращает NULL, если аргументы недействительны.

    Если значение отклоняется от поддерживаемого диапазона типа TIMESTAMP при преобразовании из from_tz в UTC, конверсия не происходит. Диапазон TIMESTAMP описан в разделе 11.1.2 «Обзор типа даты и времени».

    mysql> SELECT CONVERT_TZ ('2004-01-01 12:00:00', 'GMT', 'MET'); -> '2004-01-01 13:00:00' mysql> SELECT CONVERT_TZ ('2004-01-01 12:00:00', '+ 00:00', '+ 10:00'); -> '2004-01-01 22:00:00' Примечание. Чтобы использовать названные часовые пояса, такие как «MET» или «Европа / Москва», таблицы часовых поясов должны быть правильно настроены. Инструкции см. В разделе 10.6 «Поддержка часового пояса сервера MySQL».

    Я думаю, что если вы добавите дополнительный столбец, это поможет вашей проблеме.

    Я думаю,

    1. проверка типов данных
    2. стандартизация ваших часовых поясов
    3. Добавление другого столбца для отображения часового пояса

    вам не составит труда заказать ваш стол.

    Надеюсь, это поможет. Пожалуйста, дайте мне знать.