PHP date_create() 函数

date_create() 函数是 DateTime::__construct() 的过程化别名,用于创建一个新的 DateTime 对象。这是处理日期和时间的基础函数,提供了灵活的方式来创建、修改和格式化日期时间。

提示: date_create() 在底层使用 strtotime() 解析日期字符串,因此支持大量自然语言格式。

语法

DateTime|false date_create ([ string $datetime = "now" [, DateTimeZone $timezone = null ]] )

参数说明

参数 描述 必需 默认值
$datetime 日期时间字符串,支持多种格式(见下方) "now"
$timezone DateTimeZone 对象,指定时区 null(使用默认时区)

返回值

  • DateTime 对象 - 创建成功时返回
  • false - 创建失败时返回

支持的日期时间格式

date_create() 支持 strtotime() 可以解析的所有格式,包括:

  • ISO 8601: YYYY-MM-DD
  • ISO 8601 with time: YYYY-MM-DD HH:MM:SS
  • US format: MM/DD/YYYY
  • European format: DD.MM.YYYY
  • Relative formats: tomorrow, next week
  • Unix timestamp: @timestamp
  • Natural language: first day of next month
  • Date with timezone: 2024-03-15T14:30:00+08:00
  • RFC 2822: Fri, 15 Mar 2024 14:30:00 +0800
  • Simple date: 15 March 2024

示例代码

示例 1:基本用法

<?php
// 创建当前时间的 DateTime 对象
$now = date_create();
echo "当前时间: " . $now->format('Y-m-d H:i:s') . "<br>";

// 创建指定时间的 DateTime 对象
$specificDate = date_create('2024-03-15');
echo "指定日期: " . $specificDate->format('Y-m-d') . "<br>";

// 创建带时间的 DateTime 对象
$dateWithTime = date_create('2024-03-15 14:30:45');
echo "带时间日期: " . $dateWithTime->format('Y-m-d H:i:s');
/*
输出示例:
当前时间: 2024-03-15 10:30:00
指定日期: 2024-03-15
带时间日期: 2024-03-15 14:30:45
*/
?>

示例 2:使用相对时间格式

<?php
// 相对时间格式
$tomorrow = date_create('tomorrow');
echo "明天: " . $tomorrow->format('Y-m-d') . "<br>";

$nextWeek = date_create('next week');
echo "下周今天: " . $nextWeek->format('Y-m-d') . "<br>";

$nextMonth = date_create('first day of next month');
echo "下个月第一天: " . $nextMonth->format('Y-m-d') . "<br>";

$twoDaysAgo = date_create('2 days ago');
echo "两天前: " . $twoDaysAgo->format('Y-m-d') . "<br>";

// 复杂相对时间
$complex = date_create('next friday + 1 week 2 hours');
echo "复杂时间: " . $complex->format('Y-m-d H:i:s');
?>

示例 3:使用时区

<?php
// 创建带时区的 DateTime 对象
$timezoneNY = new DateTimeZone('America/New_York');
$dateNY = date_create('2024-03-15 14:30:00', $timezoneNY);

$timezoneTokyo = new DateTimeZone('Asia/Tokyo');
$dateTokyo = date_create('2024-03-15 14:30:00', $timezoneTokyo);

echo "纽约时间: " . $dateNY->format('Y-m-d H:i:s e') . "<br>";
echo "东京时间: " . $dateTokyo->format('Y-m-d H:i:s e') . "<br>";

// 转换为UTC
$dateNY->setTimezone(new DateTimeZone('UTC'));
echo "纽约时间(UTC): " . $dateNY->format('Y-m-d H:i:s e') . "<br>";

// 比较两个时间(同一时刻在不同时区)
echo "是否同一时刻: " . ($dateNY->getTimestamp() === $dateTokyo->getTimestamp() ? '是' : '否');
/*
输出示例:
纽约时间: 2024-03-15 14:30:00 America/New_York
东京时间: 2024-03-15 14:30:00 Asia/Tokyo
纽约时间(UTC): 2024-03-15 18:30:00 UTC
是否同一时刻: 否
*/
?>

示例 4:错误处理

<?php
// 错误处理示例
function safeDateCreate($datetime) {
    $date = date_create($datetime);
    if ($date === false) {
        return "无法解析日期时间字符串: '{$datetime}'";
    }
    return $date->format('Y-m-d H:i:s');
}

// 测试各种输入
$testCases = [
    '2024-03-15',           // 有效
    'invalid-date',         // 无效
    '2024-02-30',           // 无效(2月没有30日)
    'next month',           // 有效
    '2024-13-01',           // 无效(月份错误)
    '@1700000000',          // 有效(Unix时间戳)
];

foreach ($testCases as $test) {
    echo "'{$test}': " . safeDateCreate($test) . "<br>";
}

// 使用try-catch处理DateTime异常
try {
    $date = date_create('this is not a valid date');
    if ($date === false) {
        throw new Exception('日期创建失败');
    }
} catch (Exception $e) {
    echo "<br>异常捕获: " . $e->getMessage();
}
?>

示例 5:与面向对象方法比较

<?php
// 过程化风格 - date_create()
$date1 = date_create('2024-03-15');
$date1->modify('+1 day');
echo "date_create: " . $date1->format('Y-m-d') . "<br>";

// 面向对象风格 - new DateTime()
$date2 = new DateTime('2024-03-15');
$date2->modify('+1 day');
echo "new DateTime: " . $date2->format('Y-m-d') . "<br>";

// 两种方法等价,输出相同:2024-03-16

// 使用静态方法
$date3 = DateTime::createFromFormat('Y-m-d', '2024-03-15');
echo "createFromFormat: " . $date3->format('Y-m-d') . "<br>";

// 比较对象类型
echo "date1类型: " . get_class($date1) . "<br>";
echo "date2类型: " . get_class($date2) . "<br>";
echo "是否相同类: " . (get_class($date1) === get_class($date2) ? '是' : '否');
?>

示例 6:实用应用场景

<?php
// 场景1:计算年龄
function calculateAge($birthDate) {
    $birth = date_create($birthDate);
    $now = date_create();
    $interval = date_diff($now, $birth);
    return $interval->y;
}

echo "年龄计算: " . calculateAge('1990-05-20') . "岁<br>";

// 场景2:计算工作日
function addBusinessDays($startDate, $days) {
    $date = date_create($startDate);
    $added = 0;
    while ($added < $days) {
        $date->modify('+1 day');
        $weekday = $date->format('N'); // 1-7 (1=Monday, 7=Sunday)
        if ($weekday <= 5) {
            $added++;
        }
    }
    return $date->format('Y-m-d');
}

echo "5个工作日后: " . addBusinessDays('2024-03-15', 5) . "<br>";

// 场景3:生成日期范围
function generateDateRange($start, $end) {
    $startDate = date_create($start);
    $endDate = date_create($end);
    $dates = [];

    while ($startDate <= $endDate) {
        $dates[] = $startDate->format('Y-m-d');
        $startDate->modify('+1 day');
    }

    return $dates;
}

$range = generateDateRange('2024-03-10', '2024-03-15');
echo "日期范围: " . implode(', ', $range);
?>

注意事项

重要提示:
  • date_create() 返回的 DateTime 对象可以被修改(mutable)
  • 无效的日期时间字符串会返回 false,而不是抛出异常
  • 时区敏感:如果不指定时区,使用默认时区(php.ini中的date.timezone)
  • 对于严格的日期格式验证,建议使用 date_create_from_format()
  • 相对时间格式可能因PHP版本和地区设置而异
  • DateTime 对象实现了 DateTimeInterface 接口

常见问题

date_create() 是过程化编程风格,new DateTime() 是面向对象风格。两者功能完全相同,选择取决于个人编程风格偏好。在面向对象的代码中,建议使用 new DateTime()。
date_create() 在遇到无效日期时会返回 false。应该总是检查返回值:
$date = date_create('invalid-date');
if ($date === false) {
    // 处理错误
    echo '日期无效';
} else {
    // 正常处理
    echo $date->format('Y-m-d');
}
日期计算可能因时区、夏令时和月末日期处理而产生差异。建议:
  1. 始终明确指定时区
  2. 使用DateTime对象的方法进行计算(如add、sub)
  3. 对于月末日期,PHP会自动调整(如1月31日+1个月=2月28/29日)
  4. 使用date_diff()计算日期差异

性能考虑

<?php
// 性能比较:date_create() vs new DateTime()
function benchmark($iterations = 10000) {
    // date_create()
    $start = microtime(true);
    for ($i = 0; $i < $iterations; $i++) {
        $date = date_create('2024-03-15');
    }
    $time1 = microtime(true) - $start;

    // new DateTime()
    $start = microtime(true);
    for ($i = 0; $i < $iterations; $i++) {
        $date = new DateTime('2024-03-15');
    }
    $time2 = microtime(true) - $start;

    echo "date_create(): " . number_format($time1, 6) . " seconds<br>";
    echo "new DateTime(): " . number_format($time2, 6) . " seconds<br>";
    echo "差异: " . number_format(($time1 - $time2) * 1000, 3) . " ms";
}

benchmark(10000);
// 两种方法性能几乎相同,差异可以忽略不计
?>

相关函数

函数 描述
date_create_from_format() 根据指定格式创建DateTime对象
date_add() 向DateTime对象添加时间间隔
date_sub() 从DateTime对象减去时间间隔
date_diff() 计算两个日期之间的差异
date_format() 格式化DateTime对象
strtotime() 将英文文本日期时间解析为Unix时间戳