PHP Velho Oeste 2024

date_parse

(PHP 5 >= 5.2.0, PHP 7, PHP 8)

date_parse返回指定日期/时间的详细信息的关联数组

说明

date_parse(string $datetime): array

date_parse() 根据与 strtotime()DateTimeImmutable::__construct() 相同的规则解析指定 datetime 字符串。它不返回 Unix 时间戳(使用 strtotime())或者 DateTimeImmutable 对象(使用 DateTimeImmutable::__construct()),而是返回包含在指定 datetime 字符串中检测到相关信息的关联数组。

如果找不到某组元素的信息,那么这些数组元素将会设置为 false 或缺失。如果需要从相同的 datetime 字符串构建时间戳或者 DateTimeImmutable 对象,需要将更多字段设置为非 false 值。查看以下示例以了解情况。

参数

datetime

DateTimeImmutable::__construct() 接受的日期/时间格式。

返回值

返回 array,包含解析日期/时间的信息。

返回的数组存在以下键 yearmonthdayhourminutesecondfractionis_localtime

如果存在 is_localtime,则 zone_type 表示时区类型。类型 1(UTC 时差),添加 zoneis_dst;类型 2(时区缩写),添加 tz_abbris_dst;类型 3(时区标识符),添加 tz_abbrtz_id

如果 datetime 字符串存在类似 +3 days 这样的相对时间元素,则返回的数组则包含键为 relative 的嵌套数组。然后此数组将包含如下键 yearmonthdayhourminutesecond,如果必要还会包含 weekdayweekdays,具体取决于传入的字符串。

数组包含 warning_countwarnings 字段。第一个表示发现了多少警告。元素 warnings 的键表示指定 datetime 发生警告的位置,值为字符串,描述警告本身。

数组也包含 error_counterrors 字段。第一个表示发现了多少错误。元素 errors 的键表示指定 datetime 发生错误的位置,值为字符串,描述错误本身。

警告

如果同一个位置存在多个警告/错误,那么 warningserrors 数组中元素的数量可能会少于 warning_count 或者 error_count

错误/异常

date/time 的格式有错误时,返回数组的 'errors' 键将包含错误信息。

更新日志

版本 说明
7.2.0 返回数组的 zone 键现在代表秒,而不是分钟。并且正负符号已反转,例如:之前是 -120 现在是 7200

示例

示例 #1 具有全面的 datetime 字符串的 date_parse() 示例

<?php
var_dump
(date_parse("2006-12-12 10:00:00.5"));
?>

以上示例会输出:

array(12) {
  ["year"]=>
  int(2006)
  ["month"]=>
  int(12)
  ["day"]=>
  int(12)
  ["hour"]=>
  int(10)
  ["minute"]=>
  int(0)
  ["second"]=>
  int(0)
  ["fraction"]=>
  float(0.5)
  ["warning_count"]=>
  int(0)
  ["warnings"]=>
  array(0) {
  }
  ["error_count"]=>
  int(0)
  ["errors"]=>
  array(0) {
  }
  ["is_localtime"]=>
  bool(false)
}

如果在指定 datetime 字符串中出现时区元素,那才会展示。在这种情况下,总会存在 zone_type 和更多元素,具体取决于其值。

示例 #2 带时区缩写信息的 date_parse()

<?php
var_dump
(date_parse("June 2nd, 2022, 10:28:17 BST"));
?>

以上示例会输出:

array(16) {
  ["year"]=>
  int(2022)
  ["month"]=>
  int(6)
  ["day"]=>
  int(2)
  ["hour"]=>
  int(10)
  ["minute"]=>
  int(28)
  ["second"]=>
  int(17)
  ["fraction"]=>
  float(0)
  ["warning_count"]=>
  int(0)
  ["warnings"]=>
  array(0) {
  }
  ["error_count"]=>
  int(0)
  ["errors"]=>
  array(0) {
  }
  ["is_localtime"]=>
  bool(true)
  ["zone_type"]=>
  int(2)
  ["zone"]=>
  int(0)
  ["is_dst"]=>
  bool(true)
  ["tz_abbr"]=>
  string(3) "BST"
}

示例 #3 带时区标识符信息的 date_parse()

<?php
var_dump
(date_parse("June 2nd, 2022, 10:28:17 Europe/London"));
?>

以上示例会输出:

array(14) {
  ["year"]=>
  int(2022)
  ["month"]=>
  int(6)
  ["day"]=>
  int(2)
  ["hour"]=>
  int(10)
  ["minute"]=>
  int(28)
  ["second"]=>
  int(17)
  ["fraction"]=>
  float(0)
  ["warning_count"]=>
  int(0)
  ["warnings"]=>
  array(0) {
  }
  ["error_count"]=>
  int(0)
  ["errors"]=>
  array(0) {
  }
  ["is_localtime"]=>
  bool(true)
  ["zone_type"]=>
  int(3)
  ["tz_id"]=>
  string(13) "Europe/London"
}

如果解析的 datetime 字符串越小,那么可用的信息就越少。再本示例中,所有时间部分都返回为 false

示例 #4 带最小字符串的 date_parse()

<?php
var_dump
(date_parse("June 2nd, 2022"));
?>

以上示例会输出:

array(12) {
  ["year"]=>
  int(2022)
  ["month"]=>
  int(6)
  ["day"]=>
  int(2)
  ["hour"]=>
  bool(false)
  ["minute"]=>
  bool(false)
  ["second"]=>
  bool(false)
  ["fraction"]=>
  bool(false)
  ["warning_count"]=>
  int(0)
  ["warnings"]=>
  array(0) {
  }
  ["error_count"]=>
  int(0)
  ["errors"]=>
  array(0) {
  }
  ["is_localtime"]=>
  bool(false)
}

相对格式不会影响从绝对格式格式化的值,但会被解析为“relative”元素。

示例 #5 带相对格式的 date_parse()

<?php
var_dump
(date_parse("2006-12-12 10:00:00.5 +1 week +1 hour"));
?>

以上示例会输出:

array(13) {
  ["year"]=>
  int(2006)
  ["month"]=>
  int(12)
  ["day"]=>
  int(12)
  ["hour"]=>
  int(10)
  ["minute"]=>
  int(0)
  ["second"]=>
  int(0)
  ["fraction"]=>
  float(0.5)
  ["warning_count"]=>
  int(0)
  ["warnings"]=>
  array(0) {
  }
  ["error_count"]=>
  int(0)
  ["errors"]=>
  array(0) {
  }
  ["is_localtime"]=>
  bool(false)
  ["relative"]=>
  array(6) {
    ["year"]=>
    int(0)
    ["month"]=>
    int(0)
    ["day"]=>
    int(7)
    ["hour"]=>
    int(1)
    ["minute"]=>
    int(0)
    ["second"]=>
    int(0)
  }
}

在某些时候,比如 Thursday 将会设置字符串的时间部分设置为 0。如果 Thursday 传递给 DateTimeImmutable::__construct() 也会导致小时,分钟,秒和小数部分设置为 0。下面的示例中,year 元素将设置为 false

示例 #6 date_parse() with side-effects

<?php
var_dump
(date_parse("Thursday, June 2nd"));
?>

以上示例会输出:

array(13) {
  ["year"]=>
  bool(false)
  ["month"]=>
  int(6)
  ["day"]=>
  int(2)
  ["hour"]=>
  int(0)
  ["minute"]=>
  int(0)
  ["second"]=>
  int(0)
  ["fraction"]=>
  float(0)
  ["warning_count"]=>
  int(0)
  ["warnings"]=>
  array(0) {
  }
  ["error_count"]=>
  int(0)
  ["errors"]=>
  array(0) {
  }
  ["is_localtime"]=>
  bool(false)
  ["relative"]=>
  array(7) {
    ["year"]=>
    int(0)
    ["month"]=>
    int(0)
    ["day"]=>
    int(0)
    ["hour"]=>
    int(0)
    ["minute"]=>
    int(0)
    ["second"]=>
    int(0)
    ["weekday"]=>
    int(4)
  }
}

参见

  • date_parse_from_format() - Get info about given date formatted according to the specified format,以解析具有特定格式的datetime
  • checkdate() - 验证一个格里高里日期,以便于公历日期验证
  • getdate() - 获取日期/时间信息

add a note add a note

User Contributed Notes 11 notes

up
12
admin at torntech dot com
13 years ago
A warning to others. Some keys will return with a default value where others will return as false if the date string has it omitted. Unsure if this is a bug or feature, but hopefully this will save someone some time.
<?php
///Example
$input = "Feb 2010";
$info = date_parse($input);
var_dump($info);

/*Returns:
array(12) {
    ["year"]=> int(2010)
    ["month"]=> int(2)
    ["day"]=> int(1)    //<---expected false like below
    ["hour"]=> bool(false)
    ["minute"]=> bool(false)
    ["second"]=> bool(false)
    ["fraction"]=> bool(false)
    ["warning_count"]=> int(0)
    ["warnings"]=> array(0) { }
    ["error_count"]=> int(0)
    ["errors"]=> array(0) { }
    ["is_localtime"]=> bool(false)
}*/
?>
up
8
alvaro at demogracia dot com
13 years ago
Be aware that date_parse() is happy with just a time zone and it can be pretty counter-intuitive. E.g.:

<?php
var_dump
( date_parse('Europe/Madrid') );
?>

... prints an array where year, month, day... are FALSE. But so do these:

<?php
var_dump
( date_parse('A') );
var_dump( date_parse('B') );
var_dump( date_parse('X') );
?>

Don't forget to further validate date_parse()'s output even when it isn't FALSE and the 'errors' key is empty.
up
1
edg at greenberg dot org
5 years ago
Passing "YYYY-MM" results in a valid date. Be careful to validate that your submitted date passed YOUR requirements.
up
1
paul at juniperwebcraft dot com
7 years ago
It's sometimes useful to be able to store incomplete dates, for example when all you know of someone's birthdate is the year or the month and day.

date_parse() handles (and MySQL accepts) dates containing zero-value elements such as "2017-00-00" and "0000-03-29", leaving it up to the parent application to determine when to require and how to handle missing date elements. date_parse() correctly reports zero values for zero-value date elements, reports an 'invalid date' warning, and does not report an error.

Example 1: Year only
<?php print_r( date_parse( '2017-00-00' ) );?>
generates:
<?php
Array
(
    [
year] => 2017
   
[month] => 0
   
[day] => 0
   
[hour] =>
    [
minute] =>
    [
second] =>
    [
fraction] =>
    [
warning_count] => 1
   
[warnings] => Array
        (
            [
11] => The parsed date was invalid
       
)

    [
error_count] => 0
   
[errors] => Array
        (
        )

    [
is_localtime] =>
)
?>

Example 2: Month and day only
<?php print_r( date_parse( '0000-03-29' ) )?>
generates:
<?php
Array
(
    [
year] => 0
   
[month] => 3
   
[day] => 29
   
[hour] =>
    [
minute] =>
    [
second] =>
    [
fraction] =>
    [
warning_count] => 1
   
[warnings] => Array
        (
            [
11] => The parsed date was invalid
       
)

    [
error_count] => 0
   
[errors] => Array
        (
        )

    [
is_localtime] =>
)
?>

However, simply omitting date elements gives PHP too much discretion in second-guessing our intentions:

Example 3: Truncated date:
<?php print_r( date_parse( '2017-03' ) )?>
generates:
<?php
Array
(
    [
year] => 2017
   
[month] => 3
   
[day] => 1
   
[hour] =>
    [
minute] =>
    [
second] =>
    [
fraction] =>
    [
warning_count] => 0
   
[warnings] => Array
        (
        )

    [
error_count] => 0
   
[errors] => Array
        (
        )

    [
is_localtime] =>
)
?>
In this case, PHP supplies a day value of 1 and does not report a warning.

Similarly, this feature of accepting zero date elements does not carry over to timestamps:

<?php $dDate = strtotime( '2017-03-00' );
print_r( getdate( $dDate ) ); ?>

displays:

<?php Array
(
    [
seconds] => 0
   
[minutes] => 0
   
[hours] => 0
   
[mday] => 28
   
[wday] => 2
   
[mon] => 2
   
[year] => 2017
   
[yday] => 58
   
[weekday] => Tuesday
   
[month] => February
   
[0] => 1488268800
)
?>
In this case, PHP interprets the "zeroth" day of March to be the last day of February.
up
0
y dot adounis at gmail dot com
4 years ago
Developers, be aware that using "now" will return an empty array, ex :

<?php
date_parse
("now");
?>

Will return :

Array
(
    [year] =>
    [month] =>
    [day] =>
    [hour] =>
    [minute] =>
    [second] =>
    [fraction] =>
    [warning_count] => 0
    [warnings] => Array
        (
        )

    [error_count] => 0
    [errors] => Array
        (
        )

    [is_localtime] =>
)
up
0
ryan_a_martin at yahoo dot com
13 years ago
See checkdate() at http://php.net/manual/en/function.checkdate.php for Gregorian date validation.
up
0
gpayne at galenaparkisd com
16 years ago
Careful - date_parse is perfectly happy with something like this:

date_parse("2006-2-31");
up
-2
adamm at extratech dot com
11 years ago
A warning to some
<?php
$time
= "00:14:38"
$parse_date = date_parse($time);
echo
var_dump($parse_date) ."<br>";
//here you will get what you expect

$time = "-00:14:38"
$parse_date = date_parse($time);
echo
var_dump($parse_date) ."<br>";
//here you will recieve hours minutes and seconds as booleans and as false and you will get error set to "Unexpected character"

$time = "00:-14:38"
$parse_date = date_parse($time);
echo
var_dump($parse_date) ."<br>";
//here you will recieve the same as the above

$time = "00:14:-38"
$parse_date = date_parse($time);
echo
var_dump($parse_date) ."<br>";
//here you will receive hours as 00 minutes as 14 and seconds as 0. The error will get set as the same as above. Meaning "Unexpected character"
?>
up
-5
alan at wilcoxengineering dot com
14 years ago
Caution: date_parse expects months 1..12 only.

date_parse("13/1/5769")  for  month=13, Ehul in Jewish calendar, results in  month==3 instead of month==13.

It does, however, report the error array showing "Unexpected Character."

It would be nice if date_parse could handle the months properly (just report back a "13" for the month). The older approach of substr() is my workaround.
up
-4
eugene at ultimatecms dot co dot za
14 years ago
<?php

$ida
= '091122671325';
$idb = '091123671325';

// This function will match the identity number up to the day, but only for a maximum of 99years+364days.
// Will not work when checking persons older than 100years-1day.

function idtodate($id)
{
       
$year = date("Y");
       
$month = date("m");
       
$day = date("d");

       
$nc = substr($year, 0, 2);
       
$ny = substr($year, 2, 2);

       
$y = substr($id, 0, 2);
       
$m = substr($id, 2, 2);
       
$d = substr($id, 4, 2);

        if(
$y.$m.$d <= $ny.$month.$day-1) {
               
$newc = $nc;
        } else {
               
$newc = $nc-1;
        }

       
$new = $newc.$y;

        return array(
'year' => $new, 'month' => $m, 'day' => $d);
}

echo
'ID: '.$ida.'<br>';
print_r(idtodate($ida));

echo
'<br><br>';

echo
'ID: '.$idb.'<br>';
print_r(idtodate($idb));

?>

Output:
1. If the year-month-day is smaller than today (2009-11-23), but bigger than 1999: year => 2009
ID: 091122671325
Array ( [year] => 2009 [month] => 11 [day] => 22 )

2. If the year-month-day is the same as, or bigger than today, but smaller than 2000: year => 1909
ID: 091123671325
Array ( [year] => 1909 [month] => 11 [day] => 23 )
To Top