来自PHP的MySQL日期字段中的可选月份或日期

时间:2011-02-10 00:20:36

标签: php mysql date

我有一个问题,我需要处理月份和日期部分是可选的日期。例如,年份将始终为人所知,但有时日期或月份和日期将是未知的。

在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

或者我是否需要编写一个特殊的函数来处理它?<​​/ p>

以下不起作用:

<?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中使用的日期?

最后,这是最好的方法吗?还是有“最佳实践”方法?


编辑:

以下是我目前正在做的事情:

日期字段可以接受YYYY,YYYY-MM或YYYY-MM-DD格式的日期,在发送到数据库之前,它将在此函数中处理:

/**
* 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 个答案:

答案 0 :(得分:2)

  

我有一个问题,我需要处理月份和日期部分是可选的日期。   例如,年份将始终是已知的,但有时会是日,月和日   未知的。

在很多情况下,我们确实需要这样的“或多或少精确”的日期,我使用的日期为2011-04-01(精确),以及2011-04(= 2011年4月)和{{归档元数据中的1}}(仅年份日期)。正如你所提到的,MySQL日期字段容忍'2011-00-00',虽然没有FAQ告诉它,它没关系。
   但是,我必须通过2011和日期字段连接MySQL database 正确翻译,除了“容忍”日期(例如:'2011-04-00'在生成的MySQL-ODBC连接的ACCESS数据库中结果为空。
  出于这个原因,我得出结论,MySQL日期字段可以在普通ODBC字段中转换:只要我们不需要特定的MySQL日期函数,它就可以正常工作,当然,我们可以仍然使用php日期函数和你的好date_php2mysql()函数。

我想说的是需要MySQL日期字段的唯一情况 当需要复杂的SQL查询时,在查询本身中使用VARCHAR(10)日期函数。 (但是这些查询不再适用于“或多或少精确”的日期!......)

结论:对于“或多或少精确”的日期, 我目前丢弃MySQL日期字段并使用普通MySQL字段 使用VARCHAR(10)格式化数据。简单就是美丽。

答案 1 :(得分:0)

由于数据部分都是可选的,将月,日和年份部分存储在单独的整数字段中是否繁琐?或者在VARCHAR字段中? 2011-02-00不是一个有效的日期,我不认为mysql或PHP会对此感到兴奋。用str_to_time测试一下,看看你得到了什么样的结果,你是否验证了MySQL中的排序是否正常?如果文档说需要1到31,并且它是00,那么你可能依赖于本质上是一个bug。

由于2011-02-00不是有效日期,因此PHP的格式化功能都不会为您提供此结果。如果它处理它,如果你尝试了2001-01-31,我不会感到惊讶。更有理由将其作为字符串存储在数据库中,或将月,日和年放在单独的整数字段中。如果你使用后一种方法,你仍然可以对这些列进行排序。

答案 2 :(得分:0)

我也遇到过这个问题。我最终使用了PEAR Date包。大多数日期类不适用于可选月份或可选日期,但PEAR日期包可以使用。这也意味着您不需要自定义格式化功能,并且可以使用Date包提供的花哨格式化方法。

答案 3 :(得分:0)

答案 4 :(得分:0)

如果你从数据库中提取你的日期,就可以得到它,好像它是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"