将日期从Unix Epoch转换为YMD正在增加额外的一天

时间:2014-05-26 01:53:25

标签: php date datetime

我有两个函数可以将日期从Ymd(YYYYMMDD)格式化为U(Unix纪元日期):

<?php
date_default_timezone_set('America/New_York');

function date_to_unix($date){
    // converts 20140526 - 1401062400
    $date = DateTime::createFromFormat('Ymd', $date);
    return (int) $date->format('U');
}

function unix_to_date($unix){
    // converts 1401062400 - 20140526
    $date = DateTime::createFromFormat('U', $unix);
    return (int) $date->format('Ymd');
}

意外结果 - 从第25位开始,到第26位结束:

$date = date("Ymd");
echo "date $date\n"; // date 20140525

$time = time();
echo "time $time\n"; // time 1401069030

$unix = date_to_unix($date);
echo "unix $unix\n"; // unix 1401069030

$date = unix_to_date($unix);
echo "date $date\n"; // date 20140526

每次我使用unix_to_date时,似乎都会增加一天,

2 个答案:

答案 0 :(得分:1)

来自DateTime::create_from_format()

的PHP手册
  

当time参数包含UNIX时间戳(例如946684800)或指定时区(例如2010-01-28T15:00:00 + 02:00)时,将忽略timezone参数和当前时区。

这意味着当您从Unix时间戳(始终为UTC)创建DateTime对象时,新对象也是UTC。

您需要使用DateTime::setTimezone()将新对象设置为当地区域以获取当地时间。

由于现在纽约时间晚上10点左右,UTC时间将提前一天。

答案 1 :(得分:0)

你的代码,它会给你一些奇怪的错误和你的评论: -

  

我减去5 * 60 * 60 + 10,这似乎解决了它。 (为了好运,额外10个)

表示你不明白你做错了,(非)解决方案只会加剧你的错误。

让我们先看看你的date_to_unix()功能。

function date_to_unix($date){
    // converts 20140526 - 1401062400
    $date = DateTime::createFromFormat('Ymd', $date);
    return (int) $date->format('U');
}

$date是日期字符串,格式为&#39; Ymd&#39;并使用它来创建DateTime对象。现在,每个DateTime对象都有一个时间组件和一个日期组件,如果未指定,则默认为当前系统时间。如果您不打算使用时间部分,我建议始终将其设置为00:00:00以避免任何奇怪的结果,但这是个人偏好,对您的用例可能不是必需的。

话虽如此,这个函数看起来很好,除了你想要将一个时间戳作为int返回。您可以使用DateTime :: getTimestamp()直接返回时间戳,而不是从DateTime :: format()返回的字符串进行强制转换,但这样做非常挑剔: -

function date_to_unix($date){
    $date = DateTime::createFromFormat('Ymd', $date);
    return $date->getTimestamp();
}

你的第二个功能是你的真正问题,也就是你的错误所在。

function unix_to_date($unix){
    // converts 1401062400 - 20140526
    $date = DateTime::createFromFormat('U', $unix);
    return (int) $date->format('Ymd');
}

直接从unix时间戳创建DateTime对象并返回其值。但是,此DateTime实例是UTC,并且您的函数的目的是将其返回到本地时间,但您错过了该步骤,因此您的错误。您需要在返回之前将时间戳更改回本地时间: -

function unix_to_date($unix){
    $date = DateTime::createFromFormat('U', $unix);
    $date->setTimezone(new DateTimeZone(date_default_timezone_get()));
    return $date->format('Ymd');
}

测试当然是,您的函数可以获取日期,将其转换为时间戳,然后将该时间戳转换回相同的日期。你可以see that working here

我希望这会对你有所帮助。