PHP strtotime()函数

strtotime() 函数将任何英文文本的日期时间描述解析为 Unix 时间戳。这个函数非常强大,能够理解多种自然语言格式的日期时间字符串。

它是 PHP 中最常用的日期时间处理函数之一,特别适合处理用户输入的相对日期时间。

语法

strtotime(string $datetime [, int $baseTimestamp = time()]) : int|false

参数说明

参数 描述
datetime

必需。 日期/时间字符串。可以是绝对时间(如 "2023-08-15")或相对时间(如 "next Monday")。

支持多种格式,详见下面的格式示例表。

baseTimestamp

可选。 用作计算相对日期的基准时间戳。默认为当前时间 time()。

如果提供此参数,相对日期(如 "+1 day")将从该时间戳开始计算。

返回值

成功时返回 Unix 时间戳(整数),失败时返回 false

支持的日期时间格式

格式类型 示例 说明
绝对日期 2023-08-15, 15-08-2023 标准日期格式
绝对时间 10:30:45, 10:30 24小时制或12小时制
组合日期时间 2023-08-15 10:30:45 日期和时间组合
自然语言日期 tomorrow, yesterday, next Monday 相对当前时间的描述
相对时间 +1 day, -2 weeks, +3 months 相对某个基准时间
特殊日期 first day of, last day of 月份的特殊日期
时区 next Monday 8am UTC 包含时区信息

示例

示例 1:解析绝对日期

<?php
// 解析标准日期格式
echo strtotime("2023-08-15") . "<br>";
echo date("Y-m-d", strtotime("2023-08-15")) . "<br>";

echo strtotime("15 August 2023") . "<br>";
echo date("Y-m-d", strtotime("15 August 2023")) . "<br>";

echo strtotime("08/15/2023") . "<br>";  // 美国格式 (MM/DD/YYYY)
echo date("Y-m-d", strtotime("08/15/2023")) . "<br>";

echo strtotime("2023-08-15 10:30:45") . "<br>";
echo date("Y-m-d H:i:s", strtotime("2023-08-15 10:30:45")) . "<br>";

// 输出类似:
// 1692057600
// 2023-08-15
// 1692057600
// 2023-08-15
// 1692057600
// 2023-08-15
// 1692064245
// 2023-08-15 10:30:45
?>

示例 2:自然语言日期(相对当前时间)

<?php
// 相对当前时间的日期
echo "今天: " . date("Y-m-d", strtotime("today")) . "<br>";
echo "明天: " . date("Y-m-d", strtotime("tomorrow")) . "<br>";
echo "昨天: " . date("Y-m-d", strtotime("yesterday")) . "<br>";
echo "后天: " . date("Y-m-d", strtotime("+2 days")) . "<br>";
echo "大前天: " . date("Y-m-d", strtotime("-3 days")) . "<br>";

echo "下周一: " . date("Y-m-d", strtotime("next Monday")) . "<br>";
echo "上周日: " . date("Y-m-d", strtotime("last Sunday")) . "<br>";
echo "下个月: " . date("Y-m-d", strtotime("+1 month")) . "<br>";
echo "明年: " . date("Y-m-d", strtotime("+1 year")) . "<br>";

// 输出类似:
// 今天: 2023-08-15
// 明天: 2023-08-16
// 昨天: 2023-08-14
// 后天: 2023-08-17
// 大前天: 2023-08-12
// 下周一: 2023-08-21
// 上周日: 2023-08-13
// 下个月: 2023-09-15
// 明年: 2024-08-15
?>

示例 3:相对时间计算

<?php
// 各种相对时间计算
echo "1小时后: " . date("H:i:s", strtotime("+1 hour")) . "<br>";
echo "30分钟后: " . date("H:i:s", strtotime("+30 minutes")) . "<br>";
echo "2小时后: " . date("H:i:s", strtotime("+2 hours")) . "<br>";
echo "1天前: " . date("Y-m-d H:i:s", strtotime("-1 day")) . "<br>";
echo "1周后: " . date("Y-m-d", strtotime("+1 week")) . "<br>";
echo "2周3天4小时5分钟后: " . date("Y-m-d H:i:s", strtotime("+2 weeks 3 days 4 hours 5 minutes")) . "<br>";

// 复杂的相对时间
echo "下个月的第3天: " . date("Y-m-d", strtotime("first day of +1 month +2 days")) . "<br>";
echo "上个月的最后一天: " . date("Y-m-d", strtotime("last day of previous month")) . "<br>";
echo "下个季度的第一天: " . date("Y-m-d", strtotime("first day of +3 months")) . "<br>";

// 输出类似:
// 1小时后: 11:30:45
// 30分钟后: 11:00:45
// 2小时后: 12:30:45
// 1天前: 2023-08-14 10:30:45
// 1周后: 2023-08-22
// 2周3天4小时5分钟后: 2023-09-01 14:35:45
// 下个月的第3天: 2023-09-03
// 上个月的最后一天: 2023-07-31
// 下个季度的第一天: 2023-10-01
?>

示例 4:使用基准时间戳

<?php
// 使用特定的基准时间戳
$baseTimestamp = strtotime("2023-01-01");

echo "基准时间: " . date("Y-m-d", $baseTimestamp) . "<br>";
echo "基准时间的明天: " . date("Y-m-d", strtotime("+1 day", $baseTimestamp)) . "<br>";
echo "基准时间的下周一: " . date("Y-m-d", strtotime("next Monday", $baseTimestamp)) . "<br>";
echo "基准时间的一个月后: " . date("Y-m-d", strtotime("+1 month", $baseTimestamp)) . "<br>";

// 输出:
// 基准时间: 2023-01-01
// 基准时间的明天: 2023-01-02
// 基准时间的下周一: 2023-01-02
// 基准时间的一个月后: 2023-02-01
?>

示例 5:处理时间

<?php
// 处理时间相关字符串
echo "早上8点: " . date("Y-m-d H:i:s", strtotime("8am")) . "<br>";
echo "晚上8点: " . date("Y-m-d H:i:s", strtotime("8pm")) . "<br>";
echo "中午: " . date("Y-m-d H:i:s", strtotime("noon")) . "<br>";
echo "午夜: " . date("Y-m-d H:i:s", strtotime("midnight")) . "<br>";
echo "现在: " . date("Y-m-d H:i:s", strtotime("now")) . "<br>";

// 组合日期和时间
echo "明天下午3点: " . date("Y-m-d H:i:s", strtotime("tomorrow 3pm")) . "<br>";
echo "下周一上午9:30: " . date("Y-m-d H:i:s", strtotime("next Monday 9:30am")) . "<br>";
echo "上周五下午5点: " . date("Y-m-d H:i:s", strtotime("last Friday 5pm")) . "<br>";

// 输出类似:
// 早上8点: 2023-08-15 08:00:00
// 晚上8点: 2023-08-15 20:00:00
// 中午: 2023-08-15 12:00:00
// 午夜: 2023-08-15 00:00:00
// 现在: 2023-08-15 10:30:45
// 明天下午3点: 2023-08-16 15:00:00
// 下周一上午9:30: 2023-08-21 09:30:00
// 上周五下午5点: 2023-08-11 17:00:00
?>

示例 6:特殊日期和节假日

<?php
// 节假日和特殊日期
echo "今年的圣诞节: " . date("Y-m-d", strtotime("25 December this year")) . "<br>";
echo "下一个圣诞节: " . date("Y-m-d", strtotime("25 December")) . "<br>";
echo "2024年新年: " . date("Y-m-d", strtotime("1 January 2024")) . "<br>";

echo "本月的第一个星期一: " . date("Y-m-d", strtotime("first Monday of this month")) . "<br>";
echo "本月的最后一个星期五: " . date("Y-m-d", strtotime("last Friday of this month")) . "<br>";
echo "下个月的第三个星期三: " . date("Y-m-d", strtotime("third Wednesday of next month")) . "<br>";

// 复活节(需要计算)
echo "2023年复活节: " . date("Y-m-d", strtotime("2023-04-09")) . "<br>";
echo "2024年复活节: " . date("Y-m-d", strtotime("2024-03-31")) . "<br>";

// 输出类似:
// 今年的圣诞节: 2023-12-25
// 下一个圣诞节: 2023-12-25
// 2024年新年: 2024-01-01
// 本月的第一个星期一: 2023-08-07
// 本月的最后一个星期五: 2023-08-25
// 下个月的第三个星期三: 2023-09-20
// 2023年复活节: 2023-04-09
// 2024年复活节: 2024-03-31
?>

示例 7:处理错误和边界情况

<?php
// 处理可能失败的情况
function safeStrtotime($dateString, $baseTimestamp = null) {
    if ($baseTimestamp === null) {
        $timestamp = strtotime($dateString);
    } else {
        $timestamp = strtotime($dateString, $baseTimestamp);
    }

    if ($timestamp === false) {
        return "无法解析日期: " . htmlspecialchars($dateString);
    }

    return $timestamp;
}

echo safeStrtotime("2023-08-15") . "<br>";
echo safeStrtotime("无效日期字符串") . "<br>";
echo safeStrtotime("2023-13-45") . "<br>";  // 无效日期
echo safeStrtotime("2023-02-30") . "<br>";  // 2月没有30日

// 输出类似:
// 1692057600
// 无法解析日期: 无效日期字符串
// 无法解析日期: 2023-13-45
// 无法解析日期: 2023-02-30
?>

示例 8:时区处理

<?php
// 设置时区
date_default_timezone_set('UTC');

echo "UTC时间: " . date("Y-m-d H:i:s", strtotime("2023-08-15 10:30:45")) . "<br>";

// 转换为其他时区
date_default_timezone_set('Asia/Shanghai');
echo "上海时间: " . date("Y-m-d H:i:s", strtotime("2023-08-15 10:30:45")) . "<br>";

// 包含时区的字符串
date_default_timezone_set('UTC');
echo "带时区的字符串: " . date("Y-m-d H:i:s T", strtotime("2023-08-15 10:30:45 America/New_York")) . "<br>";

// 时区转换
$timestamp = strtotime("2023-08-15 10:30:45 UTC");
date_default_timezone_set('America/Los_Angeles');
echo "洛杉矶时间: " . date("Y-m-d H:i:s T", $timestamp) . "<br>";

// 输出类似:
// UTC时间: 2023-08-15 10:30:45
// 上海时间: 2023-08-15 18:30:45
// 带时区的字符串: 2023-08-15 14:30:45 UTC
// 洛杉矶时间: 2023-08-15 03:30:45 PDT
?>

常用日期时间字符串参考

相对时间
  • now, today
  • yesterday, tomorrow
  • +1 day, -2 days
  • +1 week, -2 weeks
  • +1 month, -3 months
  • +1 year, -2 years
  • next Monday, last Friday
  • first day of, last day of
时间表达
  • midnight, noon
  • 8am, 8pm
  • 10:30, 10:30:45
  • tomorrow 8am
  • next Monday 9:30
  • yesterday 5pm
  • +1 hour, +30 minutes
  • -2 hours, -15 minutes

注意事项

  • strtotime() 返回的是 Unix 时间戳(自 1970-01-01 00:00:00 UTC 以来的秒数)
  • 时区设置会影响 strtotime() 的结果,可以使用 date_default_timezone_set() 设置时区
  • 对于模糊的日期格式(如 01/02/2023),结果可能因地区设置而异(美国:1月2日,欧洲:2月1日)
  • 建议对用户输入的日期进行验证,不要完全依赖 strtotime() 的解析
  • PHP 8.0.0 之前,在某些系统上,strtotime() 可能返回 -1 而不是 false
  • 对于复杂的日期计算,考虑使用 DateTime

性能优化建议

场景 建议
频繁解析相同格式的日期 使用 DateTime::createFromFormat() 替代,性能更好
需要处理时区 使用 DateTime 类,时区处理更完善
处理用户输入 先验证日期格式,再使用 strtotime() 解析
需要高精度日期计算 使用 DateTimeDateInterval
批量处理日期 缓存解析结果,避免重复解析

与 DateTime 类的比较

特性 strtotime() DateTime 类
易用性 非常简单,单行代码 需要创建对象,但功能更丰富
时区支持 依赖于全局时区设置 对象级别的时区控制
错误处理 返回 false,需要手动检查 抛出异常,更容易调试
性能 较快,适合简单解析 稍慢,但功能更强大
日期计算 支持相对时间字符串 支持 DateInterval,更精确

相关函数

  • time() - 返回当前时间的 Unix 时间戳
  • date() - 格式化本地时间/日期
  • mktime() - 取得一个日期的 Unix 时间戳