2

基本的に、数日前にMySQLデータベースをいじって、タイムゾーンをMSTに設定して、PHPスクリプトがあるサーバーと一致させました(PHPサーバーのタイムゾーンもMSTに設定しました(date_default_timezone_set("MST"))データベースと一致します)。1 つのパラメーターを必要とする関数があり、それは 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を追加します。

ただし、現在の時刻を - パラメーターとして指定すると、 ' [SPACE]ago$time 'がエコーされます。行を現在の数値80を 5 または 10に増やして正確にすることで、一時的に解決しました。$time = time() - $time;$time = (time() + 80) - $time;

簡単な説明: 「 [SPACE]ago 」 だけがエコーされないように、差を計算するときに現在の時刻に秒を追加する必要があります。

ページのステータスを更新したときにこの関数を使用しています。挿入クエリがデータベースに送信され(時間列が入力されていない)、タイムスタンプ列はデフォルトで現在のタイムスタンプであるため、現在のタイムスタンプ。

毎日5つまたは10を追加することは将来安定しないことを本当に理解しているので、どうすればこれを修正できますか.

PS。私はウェブホスト上にいるため、MySQL サーバーなどを再起動できないと思います。また、再起動するための適切な権限がないと思います。

EDIT1: 挿入されたタイムスタンプが約1分進んでいるように見えますが、実際にはそうです。これが原因でしょうか?

EDIT2:今、数週間後、時間前の機能が正確で あることを確認するために、100〜200秒余分に追加する必要があります.

4

5 に答える 5

1

私には明確ではないのは、タイムスタンプを MySQL に保存する方法です。MySQL に日付を保存するには、少なくとも 3 つの方法があります。

  1. int として - time() からの出力
  2. としてDATETIME
  3. としてTIMESTAMP

最初の 2 つのオプションでは、データベース サーバーのタイムゾーンも考慮されていません。タイムゾーンをどのように設定したかについても、実際には言いません。

今のところ を使用していると仮定すると、 UNIX_TIMESTAMP(date)関数TIMESTAMPを使用して MySQL から UNIX タイムスタンプを取得できます。

MySQL サーバーでタイムゾーンを設定するときは、通常、次のようにセッションごとに設定することをお勧めします。

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

あなたの問題の根源は関数自体にあるようです。毎年正確に「31536000」秒あるわけではなく、1 か月に「2592000」秒もありません。これは、1 か月の日数やうるう年などが異なるためです。

これは、私がずっと前に書いた関数に基づいています (読みやすくするために書き直しました)。うまくいけば、それはあなたに役立つでしょう:

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;
}

上記の関数は、「# 分前」と「今日」、「昨日」、そして日付のみを実行します。もちろん、追加してさらに正確にすることもできます。

于 2013-08-05T23:13:24.333 に答える
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

オプションの 2 番目のパラメーターは、MySQL からの「unix_timestamp」の結果を 2 番目のオプションのパラメーターに渡したり、最適化された差異 (5 から 10 の「動作」が見つかった) をコーディングしたり、単純に PHP の timestamp() 関数を許可したりすることで役立つ秘密です。サーバーが同期されると、上記で既に実装されているようにデフォルトになります。

いずれにしても、次のように関数を簡単に更新します。

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
于 2013-08-08T18:56:36.880 に答える
0

あなたが書いた:

" ただし、現在の時刻を $time-parameter として指定すると、'[SPACE]ago' がエコーされます。"

したがって、この場合、 $time パラメータは time() と等しくなります。関数本体でこの行:

$time = time() - $time;

実際には $time = time() - time(); になります。(通常) 2 つの time() 呼び出しの間に 1 秒が経過しないため、これは 0 です。

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;
于 2013-08-08T08:09:17.463 に答える
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

人間が読める形式で経過時間を取得するための 2 つの簡単な方法。

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.
**/
于 2013-08-06T17:37:35.503 に答える
0

データを挿入するときに MySQL を使用する代わりに、CURRENT_TIMESTAMPphp を使用して time() から計算すると、それらは一致し、投稿時刻が現在より 60 秒早くなりません。そのように挿入するときは常に time()-1 を使用でき、常に少なくとも 1 秒の差が生じます。

日付から mysql DATETIME 形式を取得するには、これを使用してから、列の値を $date として指定します。

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

ほとんどのホスティング環境では、SQL サーバーと Web サーバーは異なるサーバーであるため、その間に多少の時間のずれが生じる可能性がありますが、確かに 1 分程度であってはなりません。ソルトに値する Web ホストは、それらがすべて同期されていることを保証します。同じタイムサーバーなので、ドリフトはマイクロ秒単位で測定する必要があります

于 2013-07-11T12:43:01.593 に答える