PHP date_timestamp_set() 函数

date_timestamp_set() 函数是 DateTime::setTimestamp() 的过程化别名,用于设置 DateTime 对象的 Unix 时间戳。

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

语法

date_timestamp_set(DateTime $object, int $timestamp): DateTime

参数

参数 类型 描述
$object DateTime 必需。DateTime对象,时间戳设置将应用于此对象
$timestamp int 必需。Unix时间戳,表示从 Unix 纪元(1970-01-01 00:00:00 UTC)以来的秒数

返回值

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

示例

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

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

// 设置Unix时间戳(2023-12-25 10:30:45 UTC)
$timestamp = 1703500245;
date_timestamp_set($date, $timestamp);
echo "设置时间戳 {$timestamp} 后: " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 验证时间戳
echo "获取时间戳验证: " . date_timestamp_get($date) . "\n";

// 使用负时间戳(1970年之前)
$negativeTimestamp = -3600; // 1969-12-31 23:00:00
date_timestamp_set($date, $negativeTimestamp);
echo "设置负时间戳 {$negativeTimestamp} 后: " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 设置未来的时间戳(2050年)
$futureTimestamp = 2556057599; // 2050-12-31 23:59:59
date_timestamp_set($date, $futureTimestamp);
echo "设置未来时间戳 {$futureTimestamp} 后: " . date_format($date, 'Y-m-d H:i:s') . "\n";
?>
                            

输出:


原始日期: 2023-01-01 00:00:00
设置时间戳 1703500245 后: 2023-12-25 10:30:45
获取时间戳验证: 1703500245
设置负时间戳 -3600 后: 1969-12-31 23:00:00
设置未来时间戳 2556057599 后: 2050-12-31 23:59:59
                            
示例 2:常见时间戳操作

<?php
// 创建当前时间的DateTime对象
$date = date_create();

echo "当前时间: " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 1. 设置为Unix纪元
date_timestamp_set($date, 0);
echo "Unix纪元: " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 2. 设置为2038年问题的时间戳(32位系统最大值)
$y2038Timestamp = 2147483647;
date_timestamp_set($date, $y2038Timestamp);
echo "2038年问题时间戳: " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 3. 设置为Y2K时间戳
$y2kTimestamp = 946684800;
date_timestamp_set($date, $y2kTimestamp);
echo "Y2K时间戳: " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 4. 设置为PHP 8.0发布时间
$php8Timestamp = 1606780800; // 2020-11-26 00:00:00
date_timestamp_set($date, $php8Timestamp);
echo "PHP 8.0发布时间: " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 5. 计算并设置明天此时的时间戳
$tomorrowTimestamp = time() + 86400; // 当前时间戳 + 24小时
date_timestamp_set($date, $tomorrowTimestamp);
echo "明天此时: " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 6. 使用strtotime转换的时间戳
$christmasTimestamp = strtotime('2023-12-25 00:00:00');
date_timestamp_set($date, $christmasTimestamp);
echo "圣诞节时间戳: " . date_format($date, 'Y-m-d H:i:s') . "\n";
?>
                            

输出:


当前时间: 2023-12-25 10:30:45
Unix纪元: 1970-01-01 00:00:00
2038年问题时间戳: 2038-01-19 03:14:07
Y2K时间戳: 2000-01-01 00:00:00
PHP 8.0发布时间: 2020-11-26 00:00:00
明天此时: 2023-12-26 10:30:45
圣诞节时间戳: 2023-12-25 00:00:00
                            
示例 3:实际应用 - 数据库时间戳转换器

<?php
/**
 * 数据库时间戳转换器
 * 处理不同数据库的时间戳格式
 */
class DatabaseTimestampConverter {
    private $timezone;

    public function __construct(string $timezone = 'UTC') {
        $this->timezone = new DateTimeZone($timezone);
    }

    /**
     * 从MySQL时间戳格式转换为DateTime对象
     * @param string $mysqlTimestamp MySQL格式的时间戳 (Y-m-d H:i:s)
     * @return DateTime
     */
    public function fromMySQL(string $mysqlTimestamp): DateTime {
        $date = date_create($mysqlTimestamp, $this->timezone);
        return $date;
    }

    /**
     * 从Unix时间戳转换为DateTime对象
     * @param int $unixTimestamp Unix时间戳
     * @return DateTime
     */
    public function fromUnixTimestamp(int $unixTimestamp): DateTime {
        $date = date_create('now', $this->timezone);
        date_timestamp_set($date, $unixTimestamp);
        return $date;
    }

    /**
     * 从JavaScript时间戳转换为DateTime对象
     * @param int $jsTimestamp JavaScript时间戳(毫秒)
     * @return DateTime
     */
    public function fromJavaScript(int $jsTimestamp): DateTime {
        $date = date_create('now', $this->timezone);
        // JavaScript使用毫秒,Unix使用秒
        date_timestamp_set($date, intval($jsTimestamp / 1000));
        return $date;
    }

    /**
     * 从Windows FILETIME转换为DateTime对象
     * @param int $filetime Windows FILETIME(100纳秒间隔)
     * @return DateTime
     */
    public function fromWindowsFileTime(int $filetime): DateTime {
        $date = date_create('now', $this->timezone);
        // Windows FILETIME从1601-01-01开始,转换为Unix时间戳
        $unixTimestamp = ($filetime / 10000000) - 11644473600;
        date_timestamp_set($date, intval($unixTimestamp));
        return $date;
    }

    /**
     * 转换为不同的时间戳格式
     * @param DateTime $date 日期时间对象
     * @param string $format 目标格式
     * @return mixed
     */
    public function convert(DateTime $date, string $format) {
        switch ($format) {
            case 'mysql':
                return $date->format('Y-m-d H:i:s');
            case 'unix':
                return date_timestamp_get($date);
            case 'javascript':
                return date_timestamp_get($date) * 1000;
            case 'iso8601':
                return $date->format(DateTime::ISO8601);
            case 'rfc2822':
                return $date->format(DateTime::RFC2822);
            default:
                return $date->format($format);
        }
    }
}

// 使用示例
$converter = new DatabaseTimestampConverter('Asia/Shanghai');

echo "数据库时间戳转换器演示:\n\n";

// 1. 从MySQL格式转换
$mysqlTime = '2023-12-25 18:30:45';
$dateFromMySQL = $converter->fromMySQL($mysqlTime);
echo "MySQL格式: {$mysqlTime}\n";
echo "转换为DateTime: " . $dateFromMySQL->format('Y-m-d H:i:s') . "\n";
echo "Unix时间戳: " . $converter->convert($dateFromMySQL, 'unix') . "\n\n";

// 2. 从Unix时间戳转换
$unixTime = 1703500245;
$dateFromUnix = $converter->fromUnixTimestamp($unixTime);
echo "Unix时间戳: {$unixTime}\n";
echo "转换为DateTime: " . $dateFromUnix->format('Y-m-d H:i:s') . "\n";
echo "MySQL格式: " . $converter->convert($dateFromUnix, 'mysql') . "\n\n";

// 3. 从JavaScript时间戳转换
$jsTime = 1703500245000; // JavaScript使用毫秒
$dateFromJS = $converter->fromJavaScript($jsTime);
echo "JavaScript时间戳: {$jsTime}\n";
echo "转换为DateTime: " . $dateFromJS->format('Y-m-d H:i:s') . "\n";
echo "ISO8601格式: " . $converter->convert($dateFromJS, 'iso8601') . "\n\n";

// 4. 从Windows FILETIME转换
$filetime = 133216992000000000; // 2023-12-25 18:30:00 的FILETIME
$dateFromFiletime = $converter->fromWindowsFileTime($filetime);
echo "Windows FILETIME: {$filetime}\n";
echo "转换为DateTime: " . $dateFromFiletime->format('Y-m-d H:i:s') . "\n";
echo "RFC2822格式: " . $converter->convert($dateFromFiletime, 'rfc2822') . "\n";

// 5. 批量转换演示
echo "\n批量转换演示:\n";
$timestamps = [1703500245, 946684800, 0, -3600, 2147483647];
foreach ($timestamps as $ts) {
    $date = $converter->fromUnixTimestamp($ts);
    echo "时间戳 {$ts} => " . $date->format('Y-m-d H:i:s') . "\n";
}
?>
                            

输出:


数据库时间戳转换器演示:

MySQL格式: 2023-12-25 18:30:45
转换为DateTime: 2023-12-25 18:30:45
Unix时间戳: 1703500245

Unix时间戳: 1703500245
转换为DateTime: 2023-12-25 18:30:45
MySQL格式: 2023-12-25 18:30:45

JavaScript时间戳: 1703500245000
转换为DateTime: 2023-12-25 18:30:45
ISO8601格式: 2023-12-25T18:30:45+0800

Windows FILETIME: 133216992000000000
转换为DateTime: 2023-12-25 18:30:00
RFC2822格式: Mon, 25 Dec 2023 18:30:00 +0800

批量转换演示:
时间戳 1703500245 => 2023-12-25 18:30:45
时间戳 946684800 => 2000-01-01 08:00:00
时间戳 0 => 1970-01-01 08:00:00
时间戳 -3600 => 1969-12-31 07:00:00
时间戳 2147483647 => 2038-01-19 11:14:07
                            
面向对象风格:DateTime::setTimestamp()

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


<?php
// 创建DateTime对象
$date = new DateTime('2023-01-01');

// 设置时间戳
$timestamp = 1703500245;
$date->setTimestamp($timestamp);
echo "设置时间戳后: " . $date->format('Y-m-d H:i:s') . "\n";

// 链式调用
$newDate = (new DateTime())
    ->setTimestamp(1703500245)
    ->modify('+1 day')
    ->setTimezone(new DateTimeZone('America/New_York'));

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

// 与createFromFormat对比
$dateFromFormat = DateTime::createFromFormat('U', '1703500245');
echo "createFromFormat: " . $dateFromFormat->format('Y-m-d H:i:s') . "\n";

// 处理负时间戳
$pre1970 = new DateTime();
$pre1970->setTimestamp(-3600);
echo "1970年之前: " . $pre1970->format('Y-m-d H:i:s') . "\n";

// 设置DateTimeImmutable(不修改原对象)
$immutable = new DateTimeImmutable('2023-01-01');
$newImmutable = $immutable->setTimestamp(1703500245);
echo "原对象: " . $immutable->format('Y-m-d H:i:s') . "\n";
echo "新对象: " . $newImmutable->format('Y-m-d H:i:s') . "\n";
?>
                            

输出:


设置时间戳后: 2023-12-25 10:30:45
链式调用结果: 2023-12-26 10:30:45 EST
createFromFormat: 2023-12-25 10:30:45
1970年之前: 1969-12-31 23:00:00
原对象: 2023-01-01 00:00:00
新对象: 2023-12-25 10:30:45
                            
推荐:在PHP 5.3及以上版本,强烈建议使用面向对象风格的 DateTime::setTimestamp() 方法,代码更易读且支持链式调用。对于不可变对象,使用 DateTimeImmutable::setTimestamp()
不同时间戳格式比较
格式 示例 精度 范围 特点
Unix时间戳 1703500245 32位:1901-2038
64位:约2920亿年
UTC基准,跨平台兼容
JavaScript时间戳 1703500245000 毫秒 -100,000,000 ~ 100,000,000天 基于Unix时间戳×1000
Windows FILETIME 133216992000000000 100纳秒 1601-01-01 ~ 30828-09-14 Windows系统专用
.NET DateTime 638392914450000000 100纳秒 0001-01-01 ~ 9999-12-31 .NET框架专用
Cocoa时间戳 728956845.0 2001-01-01 ~ 9999-12-31 macOS/iOS专用
常见错误和注意事项
1. 32位系统的时间戳限制

<?php
// 在32位系统上,时间戳超过2147483647会导致问题
$date = date_create();

// 2038年之后的时间戳在32位系统上可能溢出
$post2038Timestamp = 2147483648; // 2038-01-19 03:14:08

// 在32位PHP上,这可能导致不正确的结果
date_timestamp_set($date, $post2038Timestamp);
echo "2038年之后的时间戳: " . date_format($date, 'Y-m-d H:i:s') . "\n";

// 解决方案:确保使用64位PHP或正确处理溢出
if (PHP_INT_SIZE === 4) {
    echo "警告:运行在32位PHP上,时间戳可能溢出\n";
}
?>
                            
2. 时区处理不当

<?php
// Unix时间戳始终是UTC时区
$timestamp = 1703500245; // 2023-12-25 10:30:45 UTC

// 错误:没有设置时区
$date1 = date_create();
date_timestamp_set($date1, $timestamp);
echo "默认时区: " . $date1->format('Y-m-d H:i:s T') . "\n";

// 正确:明确设置时区
$date2 = date_create('now', new DateTimeZone('Asia/Shanghai'));
date_timestamp_set($date2, $timestamp);
echo "上海时区: " . $date2->format('Y-m-d H:i:s T') . "\n";

// 使用UTC时区
$date3 = date_create('now', new DateTimeZone('UTC'));
date_timestamp_set($date3, $timestamp);
echo "UTC时区: " . $date3->format('Y-m-d H:i:s T') . "\n";
?>
                            
3. 浮点数时间戳问题

<?php
// date_timestamp_set()需要整数参数
$date = date_create();

// 错误:传递浮点数
$floatTimestamp = 1703500245.678;
// date_timestamp_set($date, $floatTimestamp); // 会报错

// 正确:转换为整数
$intTimestamp = (int)$floatTimestamp;
date_timestamp_set($date, $intTimestamp);
echo "整数时间戳: " . $date->format('Y-m-d H:i:s') . "\n";

// 如果需要毫秒/微秒精度
$microTimestamp = 1703500245 + (678 / 1000); // 无法直接设置
echo "注意:date_timestamp_set()不支持浮点数,微秒需要其他方法\n";
?>
                            

注意事项

  • 修改原对象:date_timestamp_set() 会直接修改传入的 DateTime 对象。如果需要保留原始对象,请先使用 clone 关键字。
  • 32位系统限制:在32位系统上,时间戳范围是-2147483648到2147483647(1901-2038年)。超出范围会导致溢出。
  • 时区敏感:Unix时间戳始终是UTC时区。DateTime对象可能包含其他时区,设置时间戳时会转换为对象的时区。
  • 整数参数:函数只接受整数时间戳。浮点数时间戳需要先转换为整数。
  • 微秒精度:此函数不支持微秒精度。如需微秒精度,使用 DateTime::createFromFormat('U.u', $timestamp)
  • 性能考虑:频繁设置时间戳时,考虑使用不可变对象或直接创建新对象。
  • 2038年问题:确保应用使用64位PHP以避免2038年问题。

相关函数

date_timestamp_get()

从DateTime对象获取Unix时间戳

DateTime::setTimestamp()

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

strtotime()

将英文文本日期时间解析为Unix时间戳

time()

返回当前的Unix时间戳

date_create()

创建新的DateTime对象

DateTime::createFromFormat()

从指定格式创建DateTime对象