Необязательный месяц или день в поле даты MySQL из PHP - PullRequest
3 голосов
/ 10 февраля 2011

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

В MySQL я могу создать таблицу с полем даты, и хотя я не могу найти какую-либо ссылку в MySQLВ ручном режиме допустимо следующее:

(YYYY-MM-DD format):
2011-02-10    // Current date
2011-02-00    // Day unknown so replaced with 00
2011-00-00    // Day and month unkown so replaced with 00-00

Тестовые расчеты из базы данных работают нормально, поэтому я все еще могу легко сортировать результаты.В руководстве говорится, что месяц должен быть между 01 и 12, а день между 01 и 31 - но он принимает 00.

Первый вопрос: у меня возникнут проблемы с использованием 00 в месяце иличасти дня или это вполне приемлемо?

Следующий вопрос: существует ли функция PHP (или команда форматирования MySQL), которая автоматически форматирует следующие даты в требуемую строку формата?

2011      becomes   2011-00-00
2011-02   becomes   2011-02-00

Или мне нужно написать специальную функцию для обработки этого?

Следующее не работает:

<?php
$date = date_create_from_format('Y-m-d', '2011-00-00');
echo date_format($date, 'Y-m-d');
// Returns 2010-11-30

$date = date_create_from_format('Y-m-d', '2011-02-00');
echo date_format($date, 'Y-m-d');
// Returns 2011-01-31 
?>

Третий вопрос: есть ли функция PHP (или команда MySQL) для форматированиядаты для использования в PHP?

Наконец, это лучший подход?Или есть метод «наилучшей практики»?


РЕДАКТИРОВАТЬ:

Вот что я сейчас делаю:

Поле даты может принимать дату вв формате ГГГГ, ГГГГ-ММ или ГГГГ-ММ-ДД, и перед отправкой в ​​базу данных он обрабатывается в этой функции:

/**
* Takes a date string in the form:
*   YYYY or
*   YYYY-MM or
*   YYYY-MM-DD
* and validates it
* 
* Use date_format($date, $format); to reverse.
* 
* @param string $phpDate Date format [YYYY | YYYY-MM | YYYY-MM-DD]
* 
* @return array 'date' as YYYY-MM-DD, 'format' as ['Y' | 'Y-m' | 'Y-m-d'] or returns false if invalid
*/
function date_php2mysql($phpDate) {
    $dateArr = false;
    // Pattern match
    if (preg_match('%^(?P<year>\d{4})[- _/.]?(?P<month>\d{0,2})[- _/.]?(?P<day>\d{0,2})%im', trim($phpDate), $parts)) {
        if (empty($parts['month'])) {
            // Only year valid
            $date = $parts['year']."-01-01";
            $format = "Y";
        } elseif (empty($parts['day'])) {
            // Year and month valid
            $date = $parts['year']."-".$parts['month']."-01";
            $format = "Y-m";
        } else {
            // Year month and day valid
            $date = $parts['year']."-".$parts['month']."-".$parts['day'];
            $format = "Y-m-d";
        }
        // Double check that it is a valid date
        if (strtotime($date)) {
            // Valid date and format
            $dateArr = array('date' => $date, 'format' => $format);
        }
    } else {
        // Didn't match
        // Maybe it is still a valid date
        if (($timestamp = strtotime($phpDate)) !== false) {
            $dateArr = array('date' => date('Y-m-d', $timestamp), 'format' => "Y-m-d");
        }
    }
    // Return result
    return $dateArr;
}

Таким образом, шаблон соответствует входу $ phpDate, где он должен начинаться с 4цифры, затем необязательно пары цифр для месяца и дня.Они хранятся в массиве $ parts.

Затем он проверяет, существуют ли месяцы или дни, указывая строку формата и создавая дату.

Наконец, если все проверяется, он возвращаетдействительная дата, а также строка формата.В противном случае он возвращает FALSE.

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

Кто-нибудь придумает лучший способсделать это?

Ответы [ 5 ]

2 голосов
/ 04 мая 2011

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

Во многих случаях нам нужны такие «более или менее точные» даты, и я использую такие даты, как 2011-04-01 (точные), а также 2011-04 (= апрель 2011 г.) и 2011 (год- только дата) в архиве метаданных. Как вы упомянули, поле даты MySQL допускает «2011-00-00», хотя об этом не говорится ни в одном из часто задаваемых вопросов, и это нормально.
Но затем мне пришлось связать MySQL database через ODBC и поля даты правильно переведены, за исключением «допустимых» дат (например, результаты «2011-04-00» пусты в результирующей базе данных ACCESS, связанной с MySQL-ODBC.
По этой причине я пришел к выводу, что поле даты MySQL может быть преобразовано в простое поле VARCHAR(10): пока нам не нужны определенные функции даты MySQL, оно работает нормально, и, конечно, мы все еще можем использовать php функции даты и ваша прекрасная функция date_php2mysql ().

Я бы сказал, что единственный случай, когда необходимо поле даты MySQL это когда нужны сложные запросы SQL, используя MySQL функции даты в самом запросе. (Но такие запросы больше не будут работать в «более или менее точные» даты! ...)

Заключение : Для «более или менее точных» дат В настоящее время я сбрасываю поле даты MySQL и использую обычное поле VARCHAR(10) с aaaa-mm-jj форматированными данными. Просто это красиво.

0 голосов
/ 12 июля 2013

Если вы извлекаете свою дату из базы данных по частям, вы можете получить ее, как если бы это было 3 поля.

YEAR(dateField) as Year, MONTH(dateField) as Month, DAY(dateField) as DAY

Затем вставка этих полей в соответствующие поля следующего бита PHP даст вам искомый результат.

$day = 0;
$month = 0;
$year = 2013;


echo $datestring;

$format = "Y";
if($month)
{
    $format .= "-m";
    if($day)
        $format .="-d";
    else
        $day = 1;
}
else
{
    $month = 1;
    $day = 1;
}

$datestring = strval($year)."-".strval($month)."-".strval($day);

$date = date($format, strtotime($datestring));
echo $date; // "2013", if $month = 1, "2013-01", if $day and $month = 1, "2013-01-01"
0 голосов
/ 16 июня 2011

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

http://books.google.co.uk/books?id=s_87mv-Eo4AC&pg=PA145&lpg=PA145&dq=mysql+date+of+death+when+month+unknown&source=bl&ots=tcRGz3UDtg&sig=YkwpkAlDtBP1KKTDtqSyZCl63hs&hl=en&ei=Btf5TbL1NIexhAfkveyTAw&sa=X&oi=book_result&ct=result&resnum=8&ved=0CFMQ6AEwBw#v=onepage&q&f=false

0 голосов
/ 10 февраля 2011

Я также столкнулся с этой проблемой.В итоге я использовал пакет PEAR Date.Большинство классов дат не работают с дополнительными месяцами или дополнительными днями, но пакет PEAR Date работает.Это также означает, что вам не нужны пользовательские функции форматирования и вы можете использовать необычные методы форматирования, предоставляемые пакетом Date.

0 голосов
/ 10 февраля 2011

Поскольку все части данных являются необязательными, было бы утомительно хранить части месяца, дня и года в отдельных целочисленных полях?Или в поле VARCHAR?2011-02-00 не является действительной датой, и я не думаю, что MySQL или PHP будут рады этому.Протестируйте его с помощью str_to_time и посмотрите, какие результаты вы получите, а также проверили ли вы, что сортировка работает правильно в MySQL?Если в документах указано, что от 1 до 31 требуется, а для него требуется 00, возможно, вы полагаетесь на то, что, по сути, является ошибкой.

Поскольку 2011-02-00 не является действительной датой, нетиз функций форматирования PHP даст вам этот результат.Если бы он справился с этим вообще, я бы не удивился, если бы вы получили 2001-01-31, если бы попытались.Все больше причин, чтобы либо сохранить его в виде строки в базе данных, либо поместить месяц, день и год в отдельные целочисленные поля.Если вы пошли по последнему маршруту, вы все равно можете выполнить сортировку по этим столбцам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...