Skip to content

php_ref_date

在 Web 开发中,处理日期和时间是一个常见的需求。PHP 提供了强大的工具来获取当前日期和时间、格式化它们、执行计算以及管理时区(timezone)。

最佳实践:虽然 PHP 提供了像 date()、time() 和 strtotime() 这样的过程式函数,但强烈建议在现代 PHP 开发中使用面向对象的 DateTimeImmutable、DateTime、DateInterval 和 DateTimeZone 类。它们提供更好的一致性、时区处理能力,并避免与时间戳(timestamp)操作相关的常见陷阱。

使用 DateTimeImmutable 通常优于 DateTime,因为它在修改时会创建新对象,从而防止意外更改原始日期对象,这有助于避免复杂应用中的 Bug。

注意:除非明确指定,否则所有日期和时间操作都依赖于服务器的默认时区设置。为你的应用设置默认时区至关重要。

核心日期和时间函数和类是 PHP 引擎的一部分。无需额外安装。

为你的应用设置默认时区以确保一致性至关重要。这可以在 php.ini 文件中完成,也可以在运行时使用 date_default_timezone_set() 函数来完成。

在 php.ini 中:

date.timezone = "UTC"

或者在你的脚本开头:

<?php
date_default_timezone_set('UTC'); // 推荐:使用 UTC 或你的应用主时区
?>

未设置时区将导致 PHP 发出警告,并依赖于服务器的系统时区,这可能不是你期望的结果。

以下是使用 DateTimeImmutable 的基本示例:

<?php
date_default_timezone_set('Europe/London');
// 为当前时间创建一个新的 DateTimeImmutable 对象
$now = new DateTimeImmutable();
echo $now->format('Y-m-d H:i:s'); // 输出伦敦的当前日期和时间
// 从特定字符串和格式创建
$dateString = '2023-10-26 14:30:00';
$specificDate = DateTimeImmutable::createFromFormat('Y-m-d H:i:s', $dateString);
echo "\n" . $specificDate->format(DateTimeInterface::RFC3339); // 输出标准格式
// 修改日期(创建 NEW 对象)
$oneWeekLater = $specificDate->modify('+1 week');
echo "\n一周后: " . $oneWeekLater->format('Y-m-d');
// 计算两个日期之间的差值
$interval = $now->diff($oneWeekLater);
echo "\n差值: " . $interval->format('%R%a days'); // %R 表示正负号,%a 表示总天数
// 处理时区
$tokyoTime = $now->setTimezone(new DateTimeZone('Asia/Tokyo'));
echo "\n东京的当前时间: " . $tokyoTime->format('Y-m-d H:i:s P');
?>

关键概念:

  • new DateTimeImmutable(): 为当前时间创建一个对象。
  • DateTimeImmutable::createFromFormat(): 从匹配特定格式的字符串创建一个对象。
  • format(): 根据指定的格式字符输出日期/时间(更多选项请参见 PHP 文档)。
  • modify(): 返回一个应用了修改的新的 DateTimeImmutable 对象。
  • diff(): 计算两个 DateTimeInterface 对象之间的差值,返回一个 DateInterval 对象。
  • setTimezone(): 返回一个表示同一时间点但在不同时区中的新的 DateTimeImmutable 对象。

虽然面向对象(OO)方法更受青睐,但在旧的代码库或非常简单的任务中,你可能会遇到以下这些函数:

函数描述(遗留)
date()根据时间戳格式化本地日期和时间。
time()返回当前的 Unix 时间戳(自 1970 年 1 月 1 日 UTC 以来的秒数)。
strtotime()将英文日期时间文本描述解析为 Unix 时间戳。可能存在歧义且依赖于区域设置。
mktime() / gmmktime()获取特定日期的 Unix 时间戳(本地/GMT)。
getdate()从时间戳获取日期/时间信息作为关联数组。
checkdate()验证儒略历日期。

使用 date() 的示例:

<?php
date_default_timezone_set('UTC');
echo date('Y-m-d H:i:s'); // 输出当前的 UTC 时间
// 获取特定日期的时间戳(不如 DateTime 可靠)
$timestamp = strtotime('2023-12-25 00:00:00');
if ($timestamp !== false) {
echo "\nChristmas 2023: " . date('l, F jS, Y', $timestamp);
}
?>

常见陷阱:过度依赖 strtotime() 可能会由于日期格式的歧义(例如 m/d/y 与 d/m/y)和区域设置导致意外结果。DateTimeImmutable::createFromFormat() 提供了明确的控制。

PHP 为常见的日期格式提供了预定义常量,可与 DateTimeInterface::format() 一起使用。

常量描述(示例格式)
DateTimeInterface::ATOM (曾用名 DATE_ATOM)Atom 格式 (例如,2023-10-26T15:04:05+01:00)
DateTimeInterface::COOKIE (曾用名 DATE_COOKIE)HTTP Cookie 格式 (例如,Thursday, 26-Oct-2023 15:04:05 GMT)
DateTimeInterface::ISO8601 (曾用名 DATE_ISO8601)ISO-8601 格式 (例如,2023-10-26T15:04:05+0100) - 注意:与 RFC3339 不同
DateTimeInterface::RFC822 (曾用名 DATE_RFC822)RFC 822 格式 (例如,Thu, 26 Oct 23 15:04:05 +0100)
DateTimeInterface::RFC3339RFC 3339 格式 (例如,2023-10-26T15:04:05+01:00) - 通常是 API 的首选格式
DateTimeInterface::RFC3339_EXTENDEDRFC 3339 扩展格式 (例如,2023-10-26T15:04:05.123+01:00)
DateTimeInterface::RSS (曾用名 DATE_RSS)RSS 格式 (例如,Thu, 26 Oct 2023 15:04:05 +0100)
DateTimeInterface::W3C (曾用名 DATE_W3C)W3C 格式 (例如,2023-10-26T15:04:05+01:00)

示例:

<?php
$now = new DateTimeImmutable();
echo $now->format(DateTimeInterface::RFC3339);
?>