【问题标题】:Optional month or day in MySQL date field from PHPPHP 中 MySQL 日期字段中的可选月份或日期
【发布时间】:2011-02-10 00:20:35
【问题描述】:

我有一个问题,我需要处理月份和日期部分是可选的日期。例如,总是可以知道年份,但有时不知道日期或月份和日期。

在 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 中使用?

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


编辑:

这是我目前正在做的事情:

日期字段可以接受格式为 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。

我的数据库最终得到了一个有效的日期格式,当它返回时我有办法再次使用它。

有人想出更好的方法吗?

【问题讨论】:

  • 您对样品的预期结果是什么?
  • 如果 MySQL 样本的格式为 YYYY-MM-DD,无论它们是否有 00,它们都可以工作。 PHP 示例在评论中返回结果,但我希望它在第一个中格式化 2011-00-00,在第二个中格式化 2011-02-00。

标签: php mysql date


【解决方案1】:

我有一个问题,我需要处理月份和日期部分是可选的日期。 例如,总是可以知道年份,但有时会知道日期或月份和日期 未知。

在很多情况下,我们确实需要这种“或多或少精确”的日期,我使用 2011-04-01(精确)、2011-04(= 2011 年 4 月)和 2011(年份-仅日期)在档案元数据中。正如您所提到的,MySQL 日期字段允许“2011-00-00”,尽管没有常见问题解答说明它,这很好。
但是,我不得不通过ODBC 和日期字段连接MySQL database 被正确翻译,除了“容忍”日期(例如:“2011-04-00”在结果 MySQL-ODBC 连接的 ACCESS 数据库中结果为空。
因此,我得出的结论是 MySQL 日期字段可以转换为普通的 VARCHAR(10) 字段:只要我们不需要特定的 MySQL 日期函数,它就可以正常工作,当然,我们仍然可以使用php 日期函数和你的好 date_php2mysql() 函数。

我会说唯一需要 MySQL 日期字段的情况 当需要复杂的 SQL 查询时,在查询本身中使用 MySQL 日期函数。 (但这样的查询在“或多或少精确”的日期不再起作用!...

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

【讨论】:

    【解决方案2】:

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

    因为 2011-02-00 不是一个有效的日期,所以 PHP 的格式化函数都不会给你这个结果。如果它完全处理它,如果你尝试过,如果你得到 2001-01-31,我不会感到惊讶。更有理由将其作为字符串存储在数据库中,或者将月、日和年放在单独的整数字段中。如果您选择后者,您仍然可以对这些列进行排序。

    【讨论】:

    • 我担心我的代码可能依赖于一个错误,并且在将来的某个时候它可能会被“修复”。 :) MySQL 可以与 00 一起使用,但 PHP 不能。过去我有两个字段,一个用于日期,另一个用于格式。因此,如果我只知道年份,我会将 2011-01-01 的格式设置为“Y”,如果我知道月份,它将是 2011-02-01 和“Y-m”。仍然允许我通过日期字段轻松排序并在返回时显示数据。
    • 很公平,尽管我仍然认为三个整数列会更容易处理。它可以轻松地以表单形式呈现,灵活的排序,并且当您想要显示时,您不必与格式跳舞:只需将字段组合在一起并显示那里的内容。
    • 三个整数字段的问题是 MySQL 不知道它是一个日期,所以我不能为它使用日期函数。如果可能的话,我仍然希望保留某种日期格式。
    • cast(concat(yearfield, '-', monthfield, '-', dayfield) as date) 然后你就走了。可能不是特别有效,但它会成功
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:
      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-03
        • 2021-01-07
        • 1970-01-01
        • 1970-01-01
        • 2014-08-22
        • 1970-01-01
        相关资源
        最近更新 更多