DateTimeImmutable::createFromFormat

date_create_immutable_from_format

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

DateTimeImmutable::createFromFormat -- date_create_immutable_from_format根据指定格式解析时间字符串

描述

面向对象风格

public static DateTimeImmutable::createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null): DateTimeImmutable|false

过程式风格

返回一个新的 DateTimeImmutable 对象,该对象表示由 datetime 字符串指定的日期和时间,该字符串以给定的 format 格式化。

参数

format

传递的 string 应该具有的格式。请参阅下面的格式选项。在大多数情况下,可以使用与 date() 相同的字母。

所有字段都用当前日期/时间初始化。在大多数情况下,您可能希望将其重置为“零”(Unix 纪元,1970-01-01 00:00:00 UTC)。您可以通过在 format 中的第一个字符中包含 ! 字符,或在最后一个字符中包含 | 来实现。有关更多信息,请参阅下面每个字符的文档。

格式从左到右解析,这意味着在某些情况下,格式字符出现的顺序会影响结果。在 z(年中的某一天)的情况下,需要先解析年份,例如通过 Yy 字符。

用于解析数字的字母允许广泛的值范围,超出逻辑范围。例如,d(月份中的某一天)接受 0099 范围内的值。唯一限制是数字的数量。当给出超出范围的值时,将使用日期/时间解析器的溢出机制。下面的示例展示了其中的一些行为。

这也意味着为格式字母解析的数据是贪婪的,并且会读取其格式允许的位数。然后这也可能意味着 datetime 字符串中没有足够的字符用于以下格式字符。本页的一个示例也说明了这个问题。

format 参数字符串中识别以下字符
format 字符 描述 示例可解析的值
--- ---
dj 月份中的某一天,两位数,有或没有前导零 0131131。 (大于一个月中的天数的两位数被接受,在这种情况下它们会导致月份溢出。例如,将 33 与 1 月一起使用,表示 2 月 2 日)
Dl 一天的文本表示 MonSunSundaySaturday。如果给定的日期名称与解析(或默认)日期的日期名称不同,则会发生溢出到具有给定日期名称的下一个日期。有关说明,请参见下面的示例。
S 月份中的某一天的英文序数后缀,两位数。在处理过程中,它被忽略。 stndrdth
z 年中的某一天(从 0 开始);必须在 Yy 之前。 0365。 (三位数大于一年中的数字被接受,在这种情况下它们会导致年份溢出。例如,将 366 与 2022 一起使用,表示 2023 年 1 月 2 日)
--- ---
FM 月份的文本表示,例如 January 或 Sept JanuaryDecemberJanDec
mn 月份的数字表示,有或没有前导零 0112112。 (大于 12 的两位数被接受,在这种情况下它们会导致年份溢出。例如,使用 13 表示下一年的 1 月)
--- ---
Xx 年份的完整数字表示,最多 19 位数,可以选择以 +- 为前缀 示例:00557871999-2003+10191
Y 年份的完整数字表示,最多 4 位数 示例:005578719992003
y 年份的两位数表示(假定在 1970-2069 年之间,包含端点) 示例:9903(分别解释为 19992003
时间 --- ---
aA 上午和下午 ampm
gh 12 小时制的小时,有或没有前导零 1120112(大于 12 的两位数被接受,在这种情况下它们会导致日期溢出。例如,使用 14 表示下一个 AM/PM 周期的 02
GH 24 小时制的小时,有或没有前导零 0230023(大于 24 的两位数被接受,在这种情况下它们会导致日期溢出。例如,使用 26 表示下一天的 02:00
i 带前导零的分钟 0059。 (大于 59 的两位数被接受,在这种情况下它们会导致小时溢出。例如,使用 66 表示下一小时的 :06
s 带前导零的秒 0059(大于 59 的两位数被接受,在这种情况下它们会导致分钟溢出。例如,使用 90 表示下一分钟的 :30
v 毫秒级小数(最多三位数) 示例:120.12 秒)、3450.345 秒)
u 微秒级小数(最多六位数) 示例:450.45 秒)、6543210.654321 秒)
时区 --- ---
eOpPT 时区标识符,或与 UTC 的时差(以小时为单位),或与 UTC 的时差(以冒号分隔小时和分钟),或时区缩写 示例:UTCGMTAtlantic/Azores+0200+02:00ESTMDT
完整日期/时间 --- ---
U 自 Unix 纪元(1970 年 1 月 1 日 00:00:00 GMT)以来的秒数 示例:1292177455
空格和分隔符 --- ---
(空格) 零个或多个空格、制表符、NBSP(U+A0)或 NNBSP(U+202F)字符 示例:"\t"" "
# 以下分隔符之一:;:/.,-() 示例:/
;, :, /, ., ,, -, () 指定的字符。 示例:-
? 一个随机字节 示例:^(注意,对于 UTF-8 字符,您可能需要使用多个 ?。在这种情况下,使用 * 可能更合适)
* 从当前位置到下一个分隔符或数字的随机字节 示例:在 Y-*-d 中使用 *,字符串为 2009-aWord-08,则将匹配 aWord
! 将所有字段(年、月、日、时、分、秒、小数部分和时区信息)重置为零值(时、分、秒和小数部分为 0,月和日为 1,年为 1970,时区信息为 UTC 如果没有 !,,所有字段将设置为当前日期和时间。
| 如果字段尚未解析,则将所有字段(年、月、日、时、分、秒、小数部分和时区信息)重置为零值 Y-m-d| 将将年、月和日设置为从要解析的字符串中找到的信息,并将时、分和秒设置为 0。
+ 如果存在此格式说明符,字符串中的尾部数据不会导致错误,而是会发出警告。 使用 DateTimeImmutable::getLastErrors() 确定是否存在尾部数据。

格式字符串中无法识别的字符将导致解析失败,并向返回的结构追加错误消息。您可以使用 DateTimeImmutable::getLastErrors() 查询错误消息。

要在 format 中包含文字字符,您必须使用反斜杠 (\) 对其进行转义。

如果 format 不包含字符 !,则 format 中未指定的生成日期/时间的部分将设置为当前系统时间。

如果 format 包含字符 !,则 format 中未提供的生成日期/时间的部分以及 ! 左侧的值将设置为 Unix 纪元中的相应值。

如果解析了任何时间字符,则所有其他与时间相关的字段都将设置为 "0",除非也进行了解析。

Unix 纪元是 1970-01-01 00:00:00 UTC。

datetime

表示时间的字符串。

timezone

一个 DateTimeZone 对象,表示所需的时区。

如果省略 timezone 或为 null,并且 datetime 不包含时区,则将使用当前时区。

注意:

datetime 参数包含 UNIX 时间戳(例如 946684800)或指定时区(例如 2010-01-28T15:00:00+02:00)时,将忽略 timezone 参数和当前时区。

返回值

返回一个新的 DateTimeImmutable 实例,或在失败时返回 false

错误/异常

datetime 包含空字节时,此方法将抛出 ValueError

变更日志

版本 描述
8.2.9 现在, (空格)说明符也支持 NBSP(U+A0)和 NNBSP(U+202F)字符。
8.2.0 添加了 Xx format 说明符。
8.0.21, 8.1.8, 8.2.0 现在,当 datetime 中传递空字节时,将抛出 ValueError,而之前则会静默忽略。
7.3.0 添加了 v format 说明符。

示例

示例 #1 DateTimeImmutable::createFromFormat() 示例

面向对象风格

<?php
$date
= DateTimeImmutable::createFromFormat('j-M-Y', '15-Feb-2009');
echo
$date->format('Y-m-d');
?>

示例 #2 使用预定义格式常量与 DateTimeImmutable::createFromFormat()

面向对象风格

<?php
$date
= DateTimeImmutable::createFromFormat(DateTimeInterface::ISO8601, '2004-02-12T15:19:21+00:00');
$date = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC3339_EXTENDED, '2013-10-14T09:00:00.000+02:00');
?>

本示例中使用的 格式化常量 包含用于 格式化 DateTimeImmutable 对象的字符字符串。在大多数情况下,这些字母与上述 参数 部分中定义的日期/时间信息的相同元素匹配,但它们往往更宽松。

示例 #3 DateTimeImmutable::createFromFormat() 的复杂性

<?php
echo 'Current time: ' . date('Y-m-d H:i:s') . "\n";

$format = 'Y-m-d';
$date = DateTimeImmutable::createFromFormat($format, '2009-02-15');
echo
"Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";

$format = 'Y-m-d H:i:s';
$date = DateTimeImmutable::createFromFormat($format, '2009-02-15 15:16:17');
echo
"Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";

$format = 'Y-m-!d H:i:s';
$date = DateTimeImmutable::createFromFormat($format, '2009-02-15 15:16:17');
echo
"Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";

$format = '!d';
$date = DateTimeImmutable::createFromFormat($format, '15');
echo
"Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";

$format = 'i';
$date = DateTimeImmutable::createFromFormat($format, '15');
echo
"Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";
?>

上面的示例将输出类似于以下的内容

Current time: 2022-06-02 15:50:46
Format: Y-m-d; 2009-02-15 15:50:46
Format: Y-m-d H:i:s; 2009-02-15 15:16:17
Format: Y-m-!d H:i:s; 1970-01-15 15:16:17
Format: !d; 1970-01-15 00:00:00
Format: i; 2022-06-02 00:15:00

示例 #4 带有文字字符的格式字符串

<?php
echo DateTimeImmutable::createFromFormat('H\h i\m s\s','23h 15m 03s')->format('H:i:s');
?>

上面的示例将输出类似于以下的内容

23:15:03

示例 #5 溢出行为

<?php
echo DateTimeImmutable::createFromFormat('Y-m-d H:i:s', '2021-17-35 16:60:97')->format(DateTimeImmutable::RFC2822);
?>

上面的示例将输出类似于以下的内容

Sat, 04 Jun 2022 17:01:37 +0000

尽管结果看起来很奇怪,但它确实是正确的,因为发生了以下溢出

  1. 97 秒溢出到 1 分钟,剩下 37 秒。
  2. 61 分钟溢出为 1 小时,剩余 1 分钟。
  3. 35 天溢出为 1 个月,剩余 4 天。剩余的天数取决于月份,因为每个月的总天数不同。
  4. 18 个月溢出为 1 年,剩余 6 个月。

示例 #6 溢出日期名称行为

<?php
$d
= DateTime::createFromFormat(DateTimeInterface::RFC1123, 'Mon, 3 Aug 2020 25:00:00 +0000');
echo
$d->format(DateTime::RFC1123), "\n";
?>

上面的示例将输出类似于以下的内容

Mon, 10 Aug 2020 01:00:00 +0000

尽管结果看起来很奇怪,但它确实是正确的,因为发生了以下溢出

  1. 3 Aug 2020 25:00:00 溢出为 (Tue) 4 Aug 2020 01:00
  2. Mon 被应用,这将日期提前到 Mon, 10 Aug 2020 01:00:00。对诸如 Mon 之类的相对关键字的解释在关于 相对格式 的部分中进行了解释。

为了检测日期的溢出,您可以使用 DateTimeImmutable::getLastErrors(),如果发生溢出,它将包含一个警告。

示例 #7 检测溢出日期

<?php
$d
= DateTimeImmutable::createFromFormat('Y-m-d H:i:s', '2021-17-35 16:60:97');
echo
$d->format(DateTimeImmutable::RFC2822), "\n\n";

var_dump(DateTimeImmutable::GetLastErrors());
?>

上面的示例将输出类似于以下的内容

Sat, 04 Jun 2022 17:01:37 +0000

array(4) {
  'warning_count' =>
  int(2)
  'warnings' =>
  array(1) {
    [19] =>
    string(27) "The parsed date was invalid"
  }
  'error_count' =>
  int(0)
  'errors' =>
  array(0) {
  }
}

示例 #8 贪婪解析行为

<?php
print_r
(date_parse_from_format('Gis', '60101'));
?>

上面的示例将输出类似于以下的内容

Array
(
    [year] =>
    [month] =>
    [day] =>
    [hour] => 60
    [minute] => 10
    [second] => 0
    [fraction] => 0
    [warning_count] => 1
    [warnings] => Array
        (
            [5] => The parsed time was invalid
        )

    [error_count] => 1
    [errors] => Array
        (
            [4] => A two digit second could not be found
        )

    [is_localtime] =>
)

G 格式用于解析 24 小时制时间,带或不带前导零。这需要解析 1 或 2 位数字。由于后面有两个数字,它贪婪地将其读取为 60

接下来的 is 格式字符都需要两位数字。这意味着 10 被作为分钟 (i) 传递,然后没有足够的数字留下来解析为秒 (s)。

errors 数组指示了此问题。

此外,60 小时超出了 0-24 的范围,这导致 warnings 数组包含一个警告,表明时间无效。

另请参阅

添加笔记

用户贡献的笔记 3 notes

Andy Walker
1 年前
为了澄清,g/G 是 12/24 小时制时间,不带前导 0,h/H 是 12/24 小时制时间,带前导零,如下所述

https://php.net/manual/en/datetime.format.php
Tessa at AuRiseCreative dot com
6 个月前
由于描述和示例与时区行的匹配不完全,我想澄清每个字符的确切输出格式。

`e` 输出时区标识符,例如 `America/New_York` 或 `Asia/Gaza`

`O` 输出与 UTC 之间的时差,以小时为单位,例如 `-0500` 或 `+0200`

`P` 输出与 UTC 之间的时差,在小时和分钟之间用冒号隔开,例如 `-05:00` 或 `+02:00`

`T` 输出时区缩写,例如 `EST` 或 `EET`
peter dot labos at gmail dot com
6 个月前
如果您对该方法为您进行的广泛转换和修复不满意,或者只想检查日期是否确实与输入相同

```
$datetime = \DateTimeImmutable::createFromFormat('Y-m-d G:i:s', $userDateTimeInput);

if ($datetime && $datetime->format('Y-m-d G:i:s') === $userDateTimeInput) {
// $datetime 不为假,并且我们从用户那里获得了正确格式的正确日期
}
```
To Top