我的时间戳有什么问题?

时间:2013-07-11 10:39:37

标签: php mysql unix timezone timestamp

基本上,我几天前玩过我的MySQL数据库,我将时区设置为MST以匹配我的PHP脚本服务器(我还将PHP服务器时区设置为MST) (date_default_timezone_set("MST"))与数据库匹配)。我有一个需要一个参数的函数,那是一个UNIX时间戳。

function time_elapsed_string($time)
{
    $time = time() - $time;

    $tokens = array(
        31536000 => 'year',
        2592000 => 'month',
        604800 => 'week',
        86400 => 'day',
        3600 => 'hour',
        60 => 'minute',
        1 => 'second'
    );

    foreach($tokens as $unit => $text)
    {
        if($time < $unit) continue;
        $numberOfUnits = floor($time / $unit);
        return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':'');
    }
}

这个功能的作用是$time。它获取当前时间和$ time之间的时间差,并将$time设置为差异。然后它计算$time可能存在的最大可能时间戳并回应它。如果它是复数(2周,5个月等),它会在最后添加 s

但是,如果我将当前时间作为$time - 参数,它将回显' [SPACE]前'。我已经用$time = time() - $time;替换行$time = (time() + 80) - $time;暂时解决了这个问题,我将当前数字 80 改为5或10,以使其准确无误。

简短说明: 在计算差值时,我必须在当前时间添加秒数,以便它不会回显“ [SPACE]前”。

当我在页面上更新状态时,我正在使用此函数,插入查询被发送到数据库(没有填充时间列),并且因为timestamp列是默认情况下的当前时间戳设置为当前时间戳。

我该如何解决这个问题,因为我真的明白,每天增加5或10个将来都不会稳定。

PS。我不认为我可以重新启动MySQL服务器,因为我在webhost上,我想我没有权利这样做。

EDIT1: 看起来插入的时间戳大约是1分钟,然后是现实生活中。这会导致它吗?

EDIT2: 现在,几个星期后,我需要在100和100之间添加额外200秒以确保 time ago 功能准确无误。

5 个答案:

答案 0 :(得分:1)

我不清楚 你是如何将时间戳存储在MySQL中的。至少有三种方法可以在MySQL中存储日期:

  1. 作为int - 来自time()的输出
  2. 作为DATETIME
  3. 作为TIMESTAMP
  4. 前两个选项甚至不考虑数据库服务器的时区。你甚至没有真正说出如何设置时区。

    假设您正在使用TIMESTAMP,您可以使用UNIX_TIMESTAMP(date)函数从MySQL获取unix时间戳。

    在MySQL服务器上设置时区设置时,通常最好每个会话进行一次,如下所示:

    $sql = "SET names $charset, time_zone='".date("P")."'";
    

    问题的根源似乎是功能本身。每年没有完全“31536000”秒,一个月内也没有“2592000”秒。这是因为一个月内有不同的天数,闰年等等。

    这是基于我很久以前写的一个函数(重写它以使其更容易阅读)。希望它对你有用:

    function relativeTime($time)
    {
        $date = getdate($time);
        $today = getdate();
        $daydiff = $today["mday"]-$date["mday"];
        $text = "";
    
        if ($today["mon"] === $date["mon"] && $today["year"] === $date["year"] && $daydiff < 2) {
            if ($daydiff === 1) {
                $text =  sprintf('Yesterday, %s', date('g:i A T', $time));
            } else if ($today["hours"] == $date["hours"]) {
                $min = $today["minutes"] - $date["minutes"];
                if ($min > 1) {
                    $text = sprintf('%s minutes ago', $min);
                } else {
                    $text = 'A minute ago';
                }
            } else {
                $text = sprintf('Today, %s', date('g:i A T', $time));
            }
        } else {
            $text = date('j F Y - g:i A T', $time);
        }
        return $text;
    }
    

    上述功能仅执行“#minutes ago”和“Today”,“Yesterday”,然后是日期。当然,您可以添加它以使其更加精确。

答案 1 :(得分:1)

由于您根据MySQL中存储的内容做了不同,因此您的选择是:

  1. 在您的服务器中使用网络时间协议(请参阅http://pool.ntp.org/),并希望获得最佳效果......
  2. 或者在以下选项中使用UNIX_TIMESTAMP()从MySQL中获取时间:

      在您的查询中
    • SELECT *, UNIX_TIMESTAMP() AS unix_timestamp FROM table
    • 或单独调用:SELECT UNIX_TIMESTAMP() AS unix_timestamp
  3. 可选的第二个参数是秘密,它可以通过将MySQL的“unix_timestamp”结果传递到第二个可选参数,编码优化的差异(您发现5到10'工作'),或者只是允许PHP时间戳来提供帮助()函数成为服务器同步时上面已经实现的默认值。

    无论哪种方式都可以像这样对函数进行简单的更新:

    function time_elapsed_string($time, $time0 = NULL)
    {
        if ($time0 === NULL) 
        {
            $time0 = time();
        }
        $time = $time0 - $time;
        ...
    

    示例使用:

    time_elapsed_string($recordTimeStamp);                         // as-is
    time_elapsed_string($recordTimeStamp, time() + 5);             // an "optimized" difference
    time_elapsed_string($recordTimeStamp, $recordUnixTimeStamp);   // from MySQL addition
    time_elapsed_string($recordTimeStamp, $databaseUnixTimeStamp); // from separate query
    

答案 2 :(得分:0)

当您插入数据时,如果使用php从time()计算它们,它们将匹配,而不是在现在提前60秒发布时间,而不是使用MySQL CURRENT_TIMESTAMP。您可以随时使用time() - 1,当您插入时,始终存在至少1秒的差异。

要从日期获取mysql DATETIME格式,请使用此格式,然后将列的值指定为$ date。

$date = date('Y-m-d H:i:s', (time()-1));

在大多数托管环境中,sql server和web服务器是不同的服务器,因此它们之间可能会有一段时间的漂移,但它肯定不应该在一分钟之内,任何值得他们的盐的Web主机都将确保它们都与同一时间服务器同步,因此任何漂移都应以微秒为单位进行测量

答案 3 :(得分:0)

你遇到的问题是因为如果$ time小于1,那么就没有任何较小的面额。

我用if语句修复它,并重命名了一个变量

function time_elapsed_string($time)
{
    $time_diff = time() - $time;

    $tokens = array(
        31536000 => 'year',
        2592000 => 'month',
        604800 => 'week',
        86400 => 'day',
        3600 => 'hour',
        60 => 'minute',
        1 => 'second',
    );

    if ($time_diff < 1)
        return '0 seconds';

    foreach($tokens as $unit => $text)
    {
        if($time_diff < $unit) continue;
        $numberOfUnits = floor($time_diff / $unit);
        return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':'');
    }
}

您还可以从PHP文档中逐字使用以下内容: 资料来源:http://php.net/manual/en/function.time.php

以人类可读的形式获得时间的两种快速方法。

function time_elapsed_A($secs){
    $bit = array(
        'y' => $secs / 31556926 % 12,
        'w' => $secs / 604800 % 52,
        'd' => $secs / 86400 % 7,
        'h' => $secs / 3600 % 24,
        'm' => $secs / 60 % 60,
        's' => $secs % 60
        );

    foreach($bit as $k => $v)
        if($v > 0)$ret[] = $v . $k;

    return join(' ', $ret);
    }


function time_elapsed_B($secs){
    $bit = array(
        ' year'        => $secs / 31556926 % 12,
        ' week'        => $secs / 604800 % 52,
        ' day'        => $secs / 86400 % 7,
        ' hour'        => $secs / 3600 % 24,
        ' minute'    => $secs / 60 % 60,
        ' second'    => $secs % 60
        );

    foreach($bit as $k => $v){
        if($v > 1)$ret[] = $v . $k . 's';
        if($v == 1)$ret[] = $v . $k;
        }
    array_splice($ret, count($ret)-1, 0, 'and');
    $ret[] = 'ago.';

    return join(' ', $ret);
    }




$nowtime = time();
$oldtime = 1335939007;

echo "time_elapsed_A: ".time_elapsed_A($nowtime-$oldtime)."\n";
echo "time_elapsed_B: ".time_elapsed_B($nowtime-$oldtime)."\n";

/** Output:
time_elapsed_A: 6d 15h 48m 19s
time_elapsed_B: 6 days 15 hours 48 minutes and 19 seconds ago.
**/

答案 4 :(得分:0)

您写道:

“但是,如果我将当前时间作为$ time-parameter,它将回显'[SPACE]前”。

所以在这种情况下你的$ time参数将等于time()。 在你的函数体中这一行:

$time = time() - $time;

实际上是$ time = time() - time(); 这是0,因为两次time()调用之间不会经过1秒(通常)。

我认为如果你使用php DateTime对象会更好。

$now = new DateTime();

$timeObject = new DateTime();
$timeObject->setTimestamp($time);

// DateInterval object created by DateTime::diff()
$diff = $now->diff($timeObject);

// Number of years.
echo $diff->y;

// Number of months.
echo $diff->m;

// Number of days.
echo $diff->d;

// Number of hours.
echo $diff->h;

// Number of minutes.
echo $diff->i;

// Number of seconds.
echo $diff->s;