PHP date_date_set() 函数

date_date_set() 函数是 DateTime::setDate() 的过程化别名,用于设置 DateTime 对象的日期部分(年、月、日),同时保持时间部分不变。

提示: 这个函数特别适用于需要单独修改日期部分而不改变时间的场景,比如修改用户的出生日期但保持时间不变。

语法

DateTime date_date_set ( DateTime $object , int $year , int $month , int $day )

参数说明

参数 描述 必需
$object DateTime 对象,表示要修改的日期时间
$year 年份(1-32767)
$month 月份(1-12)
$day 日期(1-31,根据月份和闰年自动调整)

返回值

  • 返回修改后的 DateTime 对象
  • 原始 DateTime 对象也会被修改
  • 支持链式调用

示例代码

示例 1:基本用法 - 修改日期

<?php
// 创建 DateTime 对象
$date = date_create('2024-03-15 14:30:45');

echo "原始日期: " . date_format($date, 'Y-m-d H:i:s') . "<br>";

// 修改日期部分(保持时间不变)
date_date_set($date, 2025, 6, 20);

echo "修改后日期: " . date_format($date, 'Y-m-d H:i:s');
// 输出:
// 原始日期: 2024-03-15 14:30:45
// 修改后日期: 2025-06-20 14:30:45
?>

示例 2:处理月末日期

<?php
// PHP会自动处理超出范围的天数
$date = date_create('2024-01-31 10:00:00');

// 尝试设置到2月30日(无效日期)
date_date_set($date, 2024, 2, 30);

// PHP会自动调整为2月的最后一天
echo "调整后日期: " . $date->format('Y-m-d H:i:s');
// 输出:2024-02-29 10:00:00(2024年是闰年)

// 另一个例子
$date2 = date_create('2024-03-31');
date_date_set($date2, 2024, 2, 31); // 2月没有31天
echo "<br>另一个例子: " . $date2->format('Y-m-d');
// 输出:2024-02-29(自动调整为2月最后一天)
?>

示例 3:链式调用

<?php
// 链式调用
$date = date_create('2024-03-15 09:30:00');

// 修改日期并格式化输出
$result = date_date_set($date, 2025, 12, 25)
    ->format('l, F j, Y \\a\\t g:i A');

echo "新的日期时间: " . $result;
// 输出:Thursday, December 25, 2025 at 9:30 AM

// 继续修改
echo "<br>";
date_date_set($date, 2023, 7, 4);
echo "再次修改: " . $date->format('Y-m-d H:i:s');
// 输出:2023-07-04 09:30:00
?>

示例 4:与DateTime::setDate()比较

<?php
// 使用date_date_set()函数
$date1 = date_create('2024-03-15 14:30:00');
date_date_set($date1, 2025, 6, 20);
echo "date_date_set: " . $date1->format('Y-m-d H:i:s') . "<br>";

// 使用DateTime::setDate()方法
$date2 = new DateTime('2024-03-15 14:30:00');
$date2->setDate(2025, 6, 20);
echo "DateTime::setDate: " . $date2->format('Y-m-d H:i:s') . "<br>";

// 两种方法输出相同:2025-06-20 14:30:00

// 使用date_modify()作为替代
$date3 = date_create('2024-03-15 14:30:00');
date_modify($date3, '2025-06-20');
echo "date_modify: " . $date3->format('Y-m-d H:i:s');
// 注意:date_modify会重置时间为00:00:00,除非指定时间
?>

示例 5:错误处理

<?php
// 错误处理示例
$date = date_create('2024-03-15 14:30:00');

// 无效的月份
try {
    date_date_set($date, 2024, 13, 1); // 月份超出范围
} catch (Exception $e) {
    echo "错误: " . $e->getMessage() . "<br>";
}

// PHP 8.0+ 会抛出异常,PHP 7.x 会尝试自动调整
// PHP 8.0+ 输出:DateTime::setDate(): Argument #2 ($month) must be between 1 and 12

// 负数值处理
$date2 = date_create('2024-03-15');
try {
    date_date_set($date2, 2024, -1, 1); // 负月份
    echo "处理后的日期: " . $date2->format('Y-m-d') . "<br>";
} catch (Exception $e) {
    echo "负值错误: " . $e->getMessage();
}

// 在PHP 8.0+中,负值会抛出异常
?>

示例 6:实用场景

<?php
// 场景1:调整活动日期
function rescheduleEvent($originalDateTime, $newYear, $newMonth, $newDay) {
    $date = date_create($originalDateTime);
    date_date_set($date, $newYear, $newMonth, $newDay);
    return $date;
}

$originalEvent = '2024-03-15 19:00:00';
$rescheduledEvent = rescheduleEvent($originalEvent, 2024, 5, 10);
echo "活动重新安排: " . $rescheduledEvent->format('Y-m-d H:i:s') . "<br>";

// 场景2:生日日期修正(保持出生时间)
function correctBirthDate($birthDateTime, $correctYear, $correctMonth, $correctDay) {
    $birthDate = date_create($birthDateTime);
    date_date_set($birthDate, $correctYear, $correctMonth, $correctDay);
    return $birthDate;
}

$birthRecord = '2000-00-00 08:30:00'; // 数据库中的占位符日期
$correctedBirth = correctBirthDate($birthRecord, 1990, 6, 15);
echo "修正出生日期: " . $correctedBirth->format('Y-m-d H:i:s') . "<br>";

// 场景3:季度末日期设置
function setQuarterEndDate($date, $year, $quarter) {
    $quarterEndMonths = [
        1 => 3,   // Q1: 3月
        2 => 6,   // Q2: 6月
        3 => 9,   // Q3: 9月
        4 => 12,  // Q4: 12月
    ];

    if (!isset($quarterEndMonths[$quarter])) {
        return false;
    }

    $month = $quarterEndMonths[$quarter];
    $lastDay = date_create("$year-$month-01")
        ->modify('last day of this month')
        ->format('d');

    $newDate = date_create($date);
    date_date_set($newDate, $year, $month, $lastDay);
    return $newDate;
}

$currentDate = '2024-03-15 14:30:00';
$q1End = setQuarterEndDate($currentDate, 2024, 1);
echo "第一季度末: " . $q1End->format('Y-m-d H:i:s');
// 输出:2024-03-31 14:30:00
?>

与其他日期修改函数比较

函数/方法 描述 是否改变时间部分 示例
date_date_set() 仅修改日期部分(年、月、日) date_date_set($date, 2025, 6, 20)
date_time_set() 仅修改时间部分(时、分、秒) 是(只改时间) date_time_set($date, 15, 30, 0)
date_modify() 使用字符串修改日期时间 可能改变 date_modify($date, '+1 day')
DateTime::setTimestamp() 设置Unix时间戳 是(完全改变) $date->setTimestamp(1700000000)

注意事项

重要提示:
  • date_date_set() 会修改原始 DateTime 对象(mutable)
  • 对于无效日期(如2月30日),PHP会自动调整到有效日期
  • 时间部分(时、分、秒、微秒)保持不变
  • 在PHP 8.0+中,无效参数会抛出异常;在PHP 7.x中,会尝试自动调整
  • 要创建不修改原对象的新对象,可以先克隆原对象:clone $date
  • 函数返回修改后的对象本身,支持链式调用

PHP版本差异

PHP版本 行为 说明
PHP 7.x 自动调整无效参数 月份13会调整为1(下一年1月),天数32会调整为下月1日
PHP 8.0+ 抛出异常 无效参数(如月份13)会抛出ValueError异常
所有版本 时间部分保持不变 只修改日期部分,时间部分不受影响
<?php
// PHP版本兼容性示例
$date = date_create('2024-03-15 14:30:00');

try {
    // 在PHP 7.x中:这会将日期调整为2025-01-01 14:30:00
    // 在PHP 8.0+中:这会抛出异常
    date_date_set($date, 2024, 13, 1);
    echo "PHP 7.x行为: " . $date->format('Y-m-d H:i:s') . "<br>";
} catch (Exception $e) {
    echo "PHP 8.0+行为: " . $e->getMessage() . "<br>";
}

// 安全的方式:先验证参数
function safeDateSet($date, $year, $month, $day) {
    // 验证月份
    if ($month < 1 || $month > 12) {
        throw new InvalidArgumentException("月份必须在1-12之间");
    }

    // 验证日期
    if (!checkdate($month, $day, $year)) {
        throw new InvalidArgumentException("无效的日期");
    }

    return date_date_set($date, $year, $month, $day);
}

try {
    $safeDate = date_create('2024-03-15 14:30:00');
    safeDateSet($safeDate, 2024, 6, 15);
    echo "安全设置: " . $safeDate->format('Y-m-d H:i:s');
} catch (Exception $e) {
    echo "安全设置错误: " . $e->getMessage();
}
?>

相关函数

函数 描述
date_time_set() 设置DateTime对象的时间部分
date_modify() 使用相对/绝对字符串修改DateTime对象
DateTime::setDate() 面向对象的日期设置方法
DateTime::setTimestamp() 通过Unix时间戳设置DateTime对象
checkdate() 验证日期的有效性