PHP 日期

date() formatting, timestamps, the DateTime class, timezones and intervals.

Beginner
Key PointsA timestamp is UTC seconds; display needs a timezone, and `date()` uses the default one.

Timestamps and formatting

PHP stores Unix timestamps. date() formats them into local time, depending on the default timezone.

PHP
<?php
date_default_timezone_set("Asia/Shanghai");

$ts = 1700000000;

echo date("Y-m-d H:i:s", $ts), "\n";
echo date("Y/m/d", $ts), "\n";
echo date("D, d M Y", $ts), "\n";
echo date("N l", $ts), "\n";
echo date("t", $ts), "\n";
echo date("L", $ts), "\n";
Output
2023-11-15 06:13:20
2023/11/15
Wed, 15 Nov 2023
3 Wednesday
30
0

The same 1700000000 is 2023-11-14 22:13:20 in UTC and 2023-11-15 06:13:20 in Shanghai — different days. The classic cross-timezone bug.

Format characters

CharMeaningExample
Y四位年2023
m两位月11
d两位日15
H24 小时制06
i分13
s秒20
N星期几 1-73
w星期几 0-6(周日为 0)3
t本月天数30
L是否闰年0 / 1
UUnix 时间戳1700000000
cISO 86012023-11-15T06:13:20+08:00

strtotime

strtotime() parses human-readable descriptions into timestamps — handy for relative arithmetic.

PHP
<?php
date_default_timezone_set("Asia/Shanghai");
$ts = 1700000000;

echo strtotime("+1 week", $ts), "\n";
echo date("Y-m-d", strtotime("+1 week", $ts)), "\n";
echo date("Y-m-d", strtotime("-1 day", $ts)), "\n";
echo date("Y-m-d", strtotime("+1 month", $ts)), "\n";
echo date("Y-m-d", strtotime("last day of this month", $ts)), "\n";
echo date("Y-m-d H:i:s", strtotime("2023-11-15 08:00:00")), "\n";
Output
1700604800
2023-11-22
2023-11-14
2023-12-15
2023-11-30
2023-11-15 08:00:00

The DateTime class

DateTime is the OOP approach with chaining, timezones and intervals. Prefer it in new code.

PHP
<?php
$tz = new DateTimeZone("Asia/Shanghai");
$d = new DateTime("2023-11-15 06:13:20", $tz);

echo $d->format("Y-m-d H:i:s"), "\n";

$d->modify("+1 month");
echo $d->format("Y-m-d H:i:s"), "\n";

// 月末加一个月会溢出
$e = new DateTime("2024-01-31");
$e->modify("+1 month");
echo $e->format("Y-m-d"), "\n";

// 日期差
$a = new DateTime("2023-11-15");
$b = new DateTime("2024-02-20");
$diff = $a->diff($b);
echo $diff->days, "\n";
echo $diff->format("%m 个月 %d 天"), "\n";
Output
2023-11-15 06:13:20
2023-12-15 06:13:20
2024-03-02
97
3 个月 5 天
2024-01-31 +1 month yields 2024-03-02 because February has no 31st. For month-end to month-end use modify("last day of +1 month").

Everyday operations

PHP
<?php
$tz = new DateTimeZone("Asia/Shanghai");

// 今天零点
$today = new DateTime("today", $tz);
echo $today->format("Y-m-d H:i:s"), "\n";

// 本周一
$mon = new DateTime("monday this week", $tz);
echo $mon->format("Y-m-d"), "\n";

// 两个日期之间所有天
$start = new DateTime("2023-11-15");
$end   = new DateTime("2023-11-18");
$period = new DatePeriod($start, new DateInterval("P1D"), $end->modify("+1 day"));
foreach ($period as $day) {
    echo $day->format("m-d") . " ";
}
echo "\n";
Output
2023-11-15 00:00:00
2023-11-13
11-15 11-16 11-17 11-18

DatePeriod excludes the end, so modify("+1 day") is needed to include the final day — its most common gotcha.

Timezone rules

  • Store UTC —— keep timestamps or UTC datetimes in the database
  • Convert on display —— render in the user's timezone
  • Set the default —— date_default_timezone_set() or date.timezone in php.ini
  • Don't compare date strings —— use DateTime objects
PHP 8 warns when no default timezone is set. UTC is the safest default; convert at the display layer.

Friends & Partners