PHP date_time_set() 函数

date_time_set() 函数是 DateTime::setTime() 的过程化别名,用于设置 DateTime 对象的时间部分(小时、分钟、秒、微秒)。

注意:此函数在 PHP 5.2 及以上版本可用。建议使用面向对象风格的 DateTime::setTime() 方法。

语法

date_time_set(DateTime $object, int $hour, int $minute, int $second = 0, int $microsecond = 0): DateTime

参数

参数 类型 描述
$object DateTime 必需。DateTime对象,时间设置将应用于此对象
$hour int 必需。小时值(0-23)。注意:24小时制,超过23会自动进位到天数
$minute int 必需。分钟值(0-59)。超过59会自动进位到小时
$second int 可选。秒值(0-59)。默认0。超过59会自动进位到分钟
$microsecond int 可选。微秒值(0-999999)。默认0。超过999999会自动进位到秒

返回值

返回修改后的 DateTime 对象。函数会修改原始对象并返回它,因此返回值和原始对象是同一个实例。

示例

示例 1:基本用法 - 设置特定时间

<?php
// 创建一个DateTime对象
$date = date_create('2023-12-25');
echo "原始日期: " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 设置时间为14:30:45
date_time_set($date, 14, 30, 45);
echo "设置时间为14:30:45后: " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 设置时间为09:15(秒和微秒使用默认值)
date_time_set($date, 9, 15);
echo "设置时间为09:15:00后: " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 设置包含微秒的时间
date_time_set($date, 16, 45, 30, 123456);
echo "设置时间为16:45:30.123456后: " . $date->format('Y-m-d H:i:s.u') . "\n";
?>
                            

输出:


原始日期: 2023-12-25 00:00:00
设置时间为14:30:45后: 2023-12-25 14:30:45
设置时间为09:15:00后: 2023-12-25 09:15:00
设置时间为16:45:30.123456后: 2023-12-25 16:45:30.123456
                            
示例 2:时间值自动进位

<?php
// 创建一个DateTime对象
$date = date_create('2023-12-25 10:00:00');
echo "原始日期时间: " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 测试分钟进位到小时
date_time_set($date, 14, 70); // 70分钟 = 1小时10分钟
echo "设置14:70(70分钟自动进位): " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 测试秒进位到分钟
date_time_set($date, 23, 45, 90); // 90秒 = 1分钟30秒
echo "设置23:45:90(90秒自动进位): " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 测试微秒进位到秒
date_time_set($date, 8, 30, 0, 1500000); // 1,500,000微秒 = 1.5秒
echo "设置08:30:00.1500000(微秒自动进位): " . $date->format('Y-m-d H:i:s.u') . "\n";

// 综合测试:所有进位
date_time_set($date, 25, 70, 90, 2000000);
echo "设置25:70:90.2000000(所有进位): " . $date->format('Y-m-d H:i:s.u') . "\n";
echo "实际日期: " . $date->format('Y-m-d H:i:s') . "(注意:25小时进位到天数)\n";
?>
                            

输出:


原始日期时间: 2023-12-25 10:00:00
设置14:70(70分钟自动进位): 2023-12-25 15:10:00
设置23:45:90(90秒自动进位): 2023-12-25 23:46:30
设置08:30:00.1500000(微秒自动进位): 2023-12-25 08:30:01.500000
设置25:70:90.2000000(所有进位): 2023-12-26 02:11:32.000000
实际日期: 2023-12-26 02:11:32(注意:25小时进位到天数)
                            
进位规则:date_time_set() 会自动处理时间值的进位:
  • 微秒 ≥ 1,000,000 → 进位到秒
  • 秒 ≥ 60 → 进位到分钟
  • 分钟 ≥ 60 → 进位到小时
  • 小时 ≥ 24 → 进位到天数
示例 3:实际应用 - 会议时间安排系统

<?php
/**
 * 安排会议时间
 * @param DateTime $meetingDate 会议日期
 * @param int $startHour 开始小时
 * @param int $startMinute 开始分钟
 * @param int $durationMinutes 持续时间(分钟)
 * @return array 返回会议开始和结束时间
 */
function scheduleMeeting(DateTime $meetingDate, int $startHour, int $startMinute, int $durationMinutes): array {
    // 克隆对象以避免修改原始对象
    $startTime = clone $meetingDate;
    $endTime = clone $meetingDate;

    // 设置开始时间
    date_time_set($startTime, $startHour, $startMinute);

    // 计算结束时间(添加持续时间)
    date_time_set($endTime, $startHour, $startMinute + $durationMinutes);

    return [
        'start' => $startTime,
        'end' => $endTime,
        'duration_minutes' => $durationMinutes
    ];
}

/**
 * 检查时间冲突
 * @param array $meeting1 第一个会议
 * @param array $meeting2 第二个会议
 * @return bool 是否冲突
 */
function checkTimeConflict(array $meeting1, array $meeting2): bool {
    $start1 = $meeting1['start']->getTimestamp();
    $end1 = $meeting1['end']->getTimestamp();
    $start2 = $meeting2['start']->getTimestamp();
    $end2 = $meeting2['end']->getTimestamp();

    return !($end1 <= $start2 || $start1 >= $end2);
}

// 使用示例:安排一天的会议
$day = date_create('2023-12-25');

// 安排多个会议
$meetings = [
    scheduleMeeting($day, 9, 0, 60),   // 9:00-10:00
    scheduleMeeting($day, 10, 30, 90), // 10:30-12:00
    scheduleMeeting($day, 14, 0, 120), // 14:00-16:00
    scheduleMeeting($day, 15, 30, 30), // 尝试安排15:30-16:00(会冲突)
];

echo "2023年12月25日会议安排:\n\n";
foreach ($meetings as $index => $meeting) {
    $meetingNumber = $index + 1;
    echo "会议{$meetingNumber}:\n";
    echo "  开始时间: " . $meeting['start']->format('H:i') . "\n";
    echo "  结束时间: " . $meeting['end']->format('H:i') . "\n";
    echo "  持续时间: " . $meeting['duration_minutes'] . "分钟\n";

    // 检查与前一个会议是否冲突(除了第一个)
    if ($index > 0) {
        $hasConflict = checkTimeConflict($meetings[$index - 1], $meeting);
        echo "  与会议{$index}冲突: " . ($hasConflict ? "是" : "否") . "\n";
    }
    echo "\n";
}

// 验证时间设置是否正确
echo "第一个会议详细信息:\n";
$firstMeeting = $meetings[0];
echo "开始时间: " . $firstMeeting['start']->format('Y-m-d H:i:s') . "\n";
echo "结束时间: " . $firstMeeting['end']->format('Y-m-d H:i:s') . "\n";
?>
                            

输出:


2023年12月25日会议安排:

会议1:
  开始时间: 09:00
  结束时间: 10:00
  持续时间: 60分钟

会议2:
  开始时间: 10:30
  结束时间: 12:00
  持续时间: 90分钟
  与会议1冲突: 否

会议3:
  开始时间: 14:00
  结束时间: 16:00
  持续时间: 120分钟
  与会议2冲突: 否

会议4:
  开始时间: 15:30
  结束时间: 16:00
  持续时间: 30分钟
  与会议3冲突: 是

第一个会议详细信息:
开始时间: 2023-12-25 09:00:00
结束时间: 2023-12-25 10:00:00
                            
面向对象风格:DateTime::setTime()

推荐使用面向对象风格的 DateTime::setTime() 方法,代码更清晰:


<?php
// 创建DateTime对象
$date = new DateTime('2023-12-25');
echo "原始: " . $date->format('Y-m-d H:i:s') . "\n";

// 设置时间
$date->setTime(14, 30, 45);
echo "设置后: " . $date->format('Y-m-d H:i:s') . "\n";

// 链式调用
$date = (new DateTime('2023-12-25'))
    ->setTime(9, 0)        // 设置时间
    ->modify('+1 day');    // 修改日期

echo "链式调用结果: " . $date->format('Y-m-d H:i:s') . "\n";

// 设置带微秒的时间(PHP 7.1+)
$date->setTime(16, 45, 30, 123456);
echo "带微秒: " . $date->format('Y-m-d H:i:s.u') . "\n";
?>
                            

输出:


原始: 2023-12-25 00:00:00
设置后: 2023-12-25 14:30:45
链式调用结果: 2023-12-26 09:00:00
带微秒: 2023-12-26 16:45:30.123456
                            
推荐:在PHP 5.3及以上版本,强烈建议使用面向对象风格的 DateTime::setTime() 方法,代码更易读且支持链式调用。
常见错误和陷阱
1. 未使用克隆导致意外修改

<?php
// 错误示例:未克隆对象
$originalDate = date_create('2023-12-25 10:00:00');
$modifiedDate = $originalDate;

date_time_set($modifiedDate, 14, 30);

// 两个变量都指向同一个对象,都会被修改
echo "原始日期: " . date_format($originalDate, 'Y-m-d H:i:s') . "(也被修改了!)\n";

// 正确做法:使用clone
$originalDate2 = date_create('2023-12-25 10:00:00');
$modifiedDate2 = clone $originalDate2;

date_time_set($modifiedDate2, 14, 30);
echo "克隆后修改 - 原始: " . date_format($originalDate2, 'Y-m-d H:i:s') . "\n";
echo "克隆后修改 - 修改后: " . date_format($modifiedDate2, 'Y-m-d H:i:s') . "\n";
?>
                            
2. 负数参数处理

<?php
// 负数参数会导致意外结果
$date = date_create('2023-12-25 10:00:00');
date_time_set($date, -1, -30); // 负数会导致反向进位

echo "设置-1:-30后: " . date_format($date, 'Y-m-d H:i:s') . "\n";
echo "注意:-1小时 = 前一天的23小时,-30分钟 = 前一个小时的30分钟\n";
?>
                            
与date_modify()比较
date_time_set()
  • 设置绝对时间值
  • 参数:小时、分钟、秒、微秒
  • 直接指定具体时间
  • 适合设置固定时间点

$date = date_create('2023-12-25');
date_time_set($date, 14, 30, 0);
// 结果:2023-12-25 14:30:00
                                    
date_modify()
  • 相对修改时间
  • 参数:相对时间字符串
  • 基于当前时间进行增减
  • 适合时间计算

$date = date_create('2023-12-25');
date_modify($date, '+2 hours 30 minutes');
// 结果:2023-12-25 02:30:00
                                    

注意事项

  • 修改原对象:date_time_set() 会直接修改传入的 DateTime 对象。如果需要保留原始对象,请先使用 clone 关键字克隆对象。
  • 时间值范围:参数支持超过正常范围的值(如70分钟),函数会自动进位处理。
  • 负数处理:负数值会导致反向进位,可能产生意外结果。建议避免使用负数。
  • 微秒支持:微秒参数在 PHP 7.1.0 中引入,低版本PHP不支持。
  • 时区感知:DateTime 对象包含时区信息,时间设置会考虑时区。
  • 性能考虑:频繁创建新对象时,使用 clone 比创建新对象更高效。

相关函数

date_date_set()

设置DateTime对象的日期部分

date_modify()

使用字符串修改DateTime对象

date_timestamp_set()

设置DateTime对象的Unix时间戳

DateTime::setTime()

面向对象风格的设置时间方法

DateTime::setDate()

设置DateTime对象的日期部分

date_create()

创建新的DateTime对象