我有一个问题,我需要处理月份和日期部分是可选的日期。例如,年份将始终为人所知,但有时日期或月份和日期将是未知的。
在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。
我最终得到了一个有效的数据库日期格式,我有办法在它恢复时再次使用它。
有人想过更好的方法吗?
答案 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"