date('Y-m-d') 以字符串形式返回今天的日期,例如 2026-03-14。第一个参数是格式字符串,其中每个字母代表日期的一部分(Y 是年,m 是月,d 是日,H:i:s 是时间);可选的第二个参数是一个 Unix 时间戳,传入后就格式化这个时间戳,而不是当前时刻。
每次点击“运行”,输出都会变化,因为它是 UTC 的当前日期和时间。格式字符串中的每个字母,以及如何在字母之间插入普通文本,都在 PHP 日期格式页面中。
时间戳:time()、mktime() 和 strtotime()
Unix 时间戳是从 UTC 1970年1月1日零点起经过的秒数。time() 返回当前的时间戳,mktime(hour, minute, second, month, day, year) 用各个部分构造一个时间戳,strtotime() 读取用英文写的日期('2026-03-14'、'+1 week'、'next monday')。任何时间戳都可以作为 date() 的第二个参数传入。strtotime() 的第二个参数是相对短语的计算起点;不传时,从现在开始算。
输出:
1773480600
Sat, 14 Mar 2026 09:30
2027-01-01
tomorrow Sun 2026-03-15
+1 week Sat 2026-03-21
next monday Mon 2026-03-16
last day of this month Tue 2026-03-31
first monday of next month Mon 2026-04-06
bool(false)
mktime() 的自动进位很有用:某个月的第 0 天就是上个月的最后一天,所以 mktime(0, 0, 0, 3, 0, 2026) 是 2月28日。在把结果传给下一步之前,一定要先和 false 比较:date('Y-m-d', false) 会悄悄输出 1970-01-01,这是谁都不想要的日期。
给日期加上天数
除了输出之外的任何操作,都应该使用 DateTimeImmutable。它的 modify() 方法接受和 strtotime() 相同的短语,并返回一个新的日期;add() 接受一个 DateInterval,例如 P7D(7 天的时间段)或 PT90M(90 分钟)。
输出:
2026-03-21
2026-03-13
2026-04-14
11:00
2025-03-14
2026-03-03
2026-02-28
2月31日并不存在,所以 1月31日加上 +1 month 会落到 3月3日。如果你想要的是“下个月的最后一天”,就明确写成 last day of next month。
DateTime 与 DateTimeImmutable
调用 modify()、add() 或 setDate() 时,DateTime 会修改自身,并返回同一个对象。如果你把原始日期保存在一个变量里,这一点会让你大吃一惊:
输出:
2026-03-21
2026-03-21
bool(true)
2026-03-14
2026-03-21
在新代码中优先使用 DateTimeImmutable。两个类的方法相同,也都实现了 DateTimeInterface,所以一个函数可以同时接受两者。
两个日期之间的差值
diff() 返回一个 DateInterval。它的 days 属性是两个日期之间的总天数,而 y、m 和 d 把这段间隔拆分成年、月、日,计算年龄需要的正是这些。修改日期后再运行一次:
输出:
Age: 35
Exactly: 35 years, 7 months, 22 days
Days alive: 13021
286 days to go
9 months and 11 days
-286 days
在 format() 中,%a 是总天数,而 %d 只是“日”这一部分,所以计算“还有几天”时要用 %a。如果只想比较两个日期而不需要差值,普通的运算符就可以直接用于日期对象:$today < $christmas 是 true。
时区
date() 和 new DateTimeImmutable() 使用默认时区,它来自 php.ini 中的 date.timezone(未设置时为 UTC)。用 date_default_timezone_set() 为整个脚本设置时区,或者给单个日期指定它自己的 DateTimeZone,再用 setTimezone() 转换:
输出:
Asia/Tokyo 2026-03-14 18:30 JST +09:00
Europe/Berlin 2026-03-14 10:30 CET +01:00
America/New_York 2026-03-14 05:30 EDT -04:00
Asia/Tokyo
2026-03-14 18:30
时间戳在任何地方都是同一个数字,时区只改变它的显示方式。这就是为什么通常建议用 UTC 存储日期,在显示时再转换。
在网页上显示日历
日期最常被输出到 HTML 中。下面的代码把当前月份画成一个日历,并高亮显示今天。运行它,然后点击 Previous 或 Next:同一个脚本会再次运行,并根据链接设置 $_GET['m'],例如 ?m=2026-04。
format('N') 以 1(星期一)到 7(星期日)给出星期几,这正是 1 号前面需要的空格子数;format('t') 给出该月的天数。'!Y-m' 中的 ! 会重置格式中没有提到的所有字段,所以日期是 1 号,时间是零点。
使用 date() 的常见错误
date() 的第二个参数必须是时间戳,而不是日期字符串。下面这行代码:
<?php
echo date('d/m/Y', '2026-03-14');
会让脚本因 TypeError 而停止:
PHP Fatal error: Uncaught TypeError: date(): Argument #2 ($timestamp) must be of type ?int, string given in /home/index.php:2
先转换字符串,可以用 strtotime(),也可以用对象:
输出:
14/03/2026
14/03/2026
bool(false)
bool(true)
还有两个需要注意的地方:m 是月份,i 是分钟,所以 'H:m' 会在你想显示分钟的位置输出月份;new DateTimeImmutable('garbage') 会抛出异常,而不是返回 false,所以要把用户输入放在 try/catch 中,或者用 DateTimeImmutable::createFromFormat() 解析,它在不匹配时会返回 false。
常见问题
PHP 中怎么获取当前日期?
用格式字符串调用 date():echo date('Y-m-d'); 会输出今天的日期,例如 2026-03-14,date('Y-m-d H:i:s') 还会加上时间。对象版本的写法是 (new DateTimeImmutable())->format('Y-m-d')。
PHP 中怎么给日期加上天数?
对 DateTimeImmutable 使用 modify():(new DateTimeImmutable('2026-03-14'))->modify('+7 days')->format('Y-m-d') 得到 2026-03-21。使用时间戳时,date('Y-m-d', strtotime('+7 days', $timestamp)) 的效果相同。
PHP 中怎么计算两个日期之间的差值?
在一个日期上调用 diff(),传入另一个日期:$a->diff($b) 返回一个 DateInterval。它的 days 属性是总天数,y、m、d 分别保存年、月、日,计算年龄就靠它们。
PHP 中怎么把 Unix 时间戳转换成日期?
把它作为 date() 的第二个参数传入:date('Y-m-d H:i:s', 1773479107) 返回 UTC 时间 2026-03-14 09:05:07。如果要得到对象,使用 new DateTimeImmutable('@1773479107')。
为什么 PHP date() 显示的时间不对?
date() 使用默认时区,它来自 php.ini 中的 date.timezone,通常是 UTC。在脚本开头用 date_default_timezone_set('Europe/Berlin') 设置你自己的时区,或者给 DateTimeImmutable 传入一个 DateTimeZone。