web-dev-qa-db-ja.com

PHP日時から経過した時間を見つける方法

2010-04-28 17:25:43のような日付のタイムスタンプから経過した時間を見つける方法、最終出力テキストはxx Minutes Ago/xx Days Agoのようになります

90

ほとんどの答えは、日付を文字列から時間に変換することに焦点を当てているようです。日付を「5日前」形式などにすることを主に考えているようです。

これは私がそれを行う方法です:

$time = strtotime('2010-04-28 17:25:43');

echo 'event happened '.humanTiming($time).' ago';

function humanTiming ($time)
{

    $time = time() - $time; // to get the time since that moment
    $time = ($time<1)? 1 : $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':'');
    }

}

私はそれをテストしていませんが、うまくいくはずです。

結果は次のようになります

event happened 4 days ago

または

event happened 1 minute ago

乾杯

227
arnorhs

人間が読める時間形式のような文法的に正しいFacebookをもたらすphp関数を共有したい。

例:

echo get_time_ago(strtotime('now'));

結果:

1分未満

function get_time_ago($time_stamp)
{
    $time_difference = strtotime('now') - $time_stamp;

    if ($time_difference >= 60 * 60 * 24 * 365.242199)
    {
        /*
         * 60 seconds/minute * 60 minutes/hour * 24 hours/day * 365.242199 days/year
         * This means that the time difference is 1 year or more
         */
        return get_time_ago_string($time_stamp, 60 * 60 * 24 * 365.242199, 'year');
    }
    elseif ($time_difference >= 60 * 60 * 24 * 30.4368499)
    {
        /*
         * 60 seconds/minute * 60 minutes/hour * 24 hours/day * 30.4368499 days/month
         * This means that the time difference is 1 month or more
         */
        return get_time_ago_string($time_stamp, 60 * 60 * 24 * 30.4368499, 'month');
    }
    elseif ($time_difference >= 60 * 60 * 24 * 7)
    {
        /*
         * 60 seconds/minute * 60 minutes/hour * 24 hours/day * 7 days/week
         * This means that the time difference is 1 week or more
         */
        return get_time_ago_string($time_stamp, 60 * 60 * 24 * 7, 'week');
    }
    elseif ($time_difference >= 60 * 60 * 24)
    {
        /*
         * 60 seconds/minute * 60 minutes/hour * 24 hours/day
         * This means that the time difference is 1 day or more
         */
        return get_time_ago_string($time_stamp, 60 * 60 * 24, 'day');
    }
    elseif ($time_difference >= 60 * 60)
    {
        /*
         * 60 seconds/minute * 60 minutes/hour
         * This means that the time difference is 1 hour or more
         */
        return get_time_ago_string($time_stamp, 60 * 60, 'hour');
    }
    else
    {
        /*
         * 60 seconds/minute
         * This means that the time difference is a matter of minutes
         */
        return get_time_ago_string($time_stamp, 60, 'minute');
    }
}

function get_time_ago_string($time_stamp, $divisor, $time_unit)
{
    $time_difference = strtotime("now") - $time_stamp;
    $time_units      = floor($time_difference / $divisor);

    settype($time_units, 'string');

    if ($time_units === '0')
    {
        return 'less than 1 ' . $time_unit . ' ago';
    }
    elseif ($time_units === '1')
    {
        return '1 ' . $time_unit . ' ago';
    }
    else
    {
        /*
         * More than "1" $time_unit. This is the "plural" message.
         */
        // TODO: This pluralizes the time unit, which is done by adding "s" at the end; this will not work for i18n!
        return $time_units . ' ' . $time_unit . 's ago';
    }
}
16
Aman

私はあなたが望むことをするべき機能を持っていると思います:

function time2string($timeline) {
    $periods = array('day' => 86400, 'hour' => 3600, 'minute' => 60, 'second' => 1);

    foreach($periods AS $name => $seconds){
        $num = floor($timeline / $seconds);
        $timeline -= ($num * $seconds);
        $ret .= $num.' '.$name.(($num > 1) ? 's' : '').' ';
    }

    return trim($ret);
}

time()strtotime('2010-04-28 17:25:43')の違いにそれを適用するだけです:

print time2string(time()-strtotime('2010-04-28 17:25:43')).' ago';
8
JoeR

Php Datetimeクラスを使用する場合は、次を使用できます。

function time_ago(Datetime $date) {
  $time_ago = '';

  $diff = $date->diff(new Datetime('now'));


  if (($t = $diff->format("%m")) > 0)
    $time_ago = $t . ' months';
  else if (($t = $diff->format("%d")) > 0)
    $time_ago = $t . ' days';
  else if (($t = $diff->format("%H")) > 0)
    $time_ago = $t . ' hours';
  else
    $time_ago = 'minutes';

  return $time_ago . ' ago (' . $date->format('M j, Y') . ')';
}
3
Tessmore

注意してください、数学的に計算された例の大部分は2038-01-18日付の厳しい制限があり、架空の日付では動作しません。

DateTimeおよびDateIntervalベースの例が不足していたため、OPのニーズを満たす複合目的の機能と、1 month 2 days agoなどの複合経過期間を必要とする他の機能を提供したかったのです。経過時間の代わりに日付を表​​示したり、経過時間の結果の一部を除外したりする制限など、他の多くのユースケースとともに。

さらに、例の大部分は、経過が現在の時刻からであると想定しています。ここでは、以下の関数を使用して、目的の終了日で上書きすることができます。

/**
 * multi-purpose function to calculate the time elapsed between $start and optional $end
 * @param string|null $start the date string to start calculation
 * @param string|null $end the date string to end calculation
 * @param string $suffix the suffix string to include in the calculated string
 * @param string $format the format of the resulting date if limit is reached or no periods were found
 * @param string $separator the separator between periods to use when filter is not true
 * @param null|string $limit date string to stop calculations on and display the date if reached - ex: 1 month
 * @param bool|array $filter false to display all periods, true to display first period matching the minimum, or array of periods to display ['year', 'month']
 * @param int $minimum the minimum value needed to include a period
 * @return string
 */
function elapsedTimeString($start, $end = null, $limit = null, $filter = true, $suffix = 'ago', $format = 'Y-m-d', $separator = ' ', $minimum = 1)
{
    $dates = (object) array(
        'start' => new DateTime($start ? : 'now'),
        'end' => new DateTime($end ? : 'now'),
        'intervals' => array('y' => 'year', 'm' => 'month', 'd' => 'day', 'h' => 'hour', 'i' => 'minute', 's' => 'second'),
        'periods' => array()
    );
    $elapsed = (object) array(
        'interval' => $dates->start->diff($dates->end),
        'unknown' => 'unknown'
    );
    if ($elapsed->interval->invert === 1) {
        return trim('0 seconds ' . $suffix);
    }
    if (false === empty($limit)) {
        $dates->limit = new DateTime($limit);
        if (date_create()->add($elapsed->interval) > $dates->limit) {
            return $dates->start->format($format) ? : $elapsed->unknown;
        }
    }
    if (true === is_array($filter)) {
        $dates->intervals = array_intersect($dates->intervals, $filter);
        $filter = false;
    }
    foreach ($dates->intervals as $period => $name) {
        $value = $elapsed->interval->$period;
        if ($value >= $minimum) {
            $dates->periods[] = vsprintf('%1$s %2$s%3$s', array($value, $name, ($value !== 1 ? 's' : '')));
            if (true === $filter) {
                break;
            }
        }
    }
    if (false === empty($dates->periods)) {
        return trim(vsprintf('%1$s %2$s', array(implode($separator, $dates->periods), $suffix)));
    }

    return $dates->start->format($format) ? : $elapsed->unknown;
}

注意すべき点が1つあります。指定されたフィルター値に対して取得された間隔は、次の期間に引き継がれません。フィルターは、指定された期間の結果値を表示するだけで、期間を再計算して目的のフィルター合計のみを表示することはありません。


使用法

OPが最高期間を表示する必要がある場合(2015-02-24現在)。

echo elapsedTimeString('2010-04-26');
/** 4 years ago */

複合期間を表示し、カスタム終了日を指定するには(指定された時間と架空の日付がないことに注意してください)

echo elapsedTimeString('1920-01-01', '2500-02-24', null, false);
/** 580 years 1 month 23 days ago */

フィルタリングされた期間の結果を表示するには(配列の順序は関係ありません)

echo elapsedTimeString('2010-05-26', '2012-02-24', null, ['month', 'year']);
/** 1 year 8 months ago */

制限に達した場合に、指定された形式(デフォルトではY-m-d)で開始日を表示します。

echo elapsedTimeString('2010-05-26', '2012-02-24', '1 year');
/** 2010-05-26 */

他にも多くのユースケースがあります。また、開始、終了、または制限引数のUNIXタイムスタンプやDateIntervalオブジェクトを受け入れるように簡単に適合させることもできます。

3
fyrye

私はMithunのコードが好きでしたが、より合理的な答えを出すように少し調整しました。

function getTimeSince($eventTime)
{
    $totaldelay = time() - strtotime($eventTime);
    if($totaldelay <= 0)
    {
        return '';
    }
    else
    {
        $first = '';
        $marker = 0;
        if($years=floor($totaldelay/31536000))
        {
            $totaldelay = $totaldelay % 31536000;
            $plural = '';
            if ($years > 1) $plural='s';
            $interval = $years." year".$plural;
            $timesince = $timesince.$first.$interval;
            if ($marker) return $timesince;
            $marker = 1;
            $first = ", ";
        }
        if($months=floor($totaldelay/2628000))
        {
            $totaldelay = $totaldelay % 2628000;
            $plural = '';
            if ($months > 1) $plural='s';
            $interval = $months." month".$plural;
            $timesince = $timesince.$first.$interval;
            if ($marker) return $timesince;
            $marker = 1;
            $first = ", ";
        }
        if($days=floor($totaldelay/86400))
        {
            $totaldelay = $totaldelay % 86400;
            $plural = '';
            if ($days > 1) $plural='s';
            $interval = $days." day".$plural;
            $timesince = $timesince.$first.$interval;
            if ($marker) return $timesince;
            $marker = 1;
            $first = ", ";
        }
        if ($marker) return $timesince;
        if($hours=floor($totaldelay/3600))
        {
            $totaldelay = $totaldelay % 3600;
            $plural = '';
            if ($hours > 1) $plural='s';
            $interval = $hours." hour".$plural;
            $timesince = $timesince.$first.$interval;
            if ($marker) return $timesince;
            $marker = 1;
            $first = ", ";

        }
        if($minutes=floor($totaldelay/60))
        {
            $totaldelay = $totaldelay % 60;
            $plural = '';
            if ($minutes > 1) $plural='s';
            $interval = $minutes." minute".$plural;
            $timesince = $timesince.$first.$interval;
            if ($marker) return $timesince;
            $first = ", ";
        }
        if($seconds=floor($totaldelay/1))
        {
            $totaldelay = $totaldelay % 1;
            $plural = '';
            if ($seconds > 1) $plural='s';
            $interval = $seconds." second".$plural;
            $timesince = $timesince.$first.$interval;
        }        
        return $timesince;

    }
}
2
David Headrick

@arnorhsの答えを改善するために、ユーザーが参加してからたとえば年、月、日、時間を必要とする場合に、より正確な結果を得る機能を追加しました。

返される精度のポイント数を指定できる新しいパラメーターを追加しました。

function get_friendly_time_ago($distant_timestamp, $max_units = 3) {
    $i = 0;
    $time = time() - $distant_timestamp; // to get the time since that moment
    $tokens = [
        31536000 => 'year',
        2592000 => 'month',
        604800 => 'week',
        86400 => 'day',
        3600 => 'hour',
        60 => 'minute',
        1 => 'second'
    ];

    $responses = [];
    while ($i < $max_units && $time > 0) {
        foreach ($tokens as $unit => $text) {
            if ($time < $unit) {
                continue;
            }
            $i++;
            $numberOfUnits = floor($time / $unit);

            $responses[] = $numberOfUnits . ' ' . $text . (($numberOfUnits > 1) ? 's' : '');
            $time -= ($unit * $numberOfUnits);
            break;
        }
    }

    if (!empty($responses)) {
        return implode(', ', $responses) . ' ago';
    }

    return 'Just now';
}
2
Aran

次のリポジトリのいずれかを試してください。

https://github.com/salavert/time-ago-in-words

https://github.com/jimmiw/php-time-ago

私は後者を使い始めたばかりですが、トリックを行いますが、問題の日付が遠すぎるときに正確な日付にstackoverflowスタイルのフォールバックはありませんし、将来の日付のサポートもありません-そしてAPIは少しファンキーですが、少なくともそれは一見問題なく動作し、維持されています...

1
raveren

これを使用すると、取得することができます

    $previousDate = '2013-7-26 17:01:10';
    $startdate = new DateTime($previousDate);
    $endDate   = new DateTime('now');
    $interval  = $endDate->diff($startdate);
    echo$interval->format('%y years, %m months, %d days');

これを参照してください http://ca2.php.net/manual/en/dateinterval.format.php

1
khan Asim

PHPのどのバージョンでも動作するオプションの1つは、既に提案されていることを行うことです。これは次のようなものです。

$eventTime = '2010-04-28 17:25:43';
$age = time() - strtotime($eventTime);

それはあなたに数秒で年齢を与えます。そこから、好きなように表示できます。

ただし、このアプローチの問題の1つは、DSTによるタイムシフトの原因が考慮されないことです。それが心配ではない場合、それのために行きます。そうでない場合は、おそらくDateTimeクラスの diff()メソッド を使用する必要があります。残念ながら、これは少なくともPHP 5.3を使用している場合のオプションにすぎません。

1
mr. w

経過時間を調べるには、通常time()の代わりにdate()とフォーマットされたタイムスタンプを使用します。次に、後者の値と以前の値の差を取得し、それに応じてフォーマットします。 time()date()の代替ではありませんが、経過時間を計算する際に完全に役立ちます。

例:

time()の値は、この1274467343が毎秒増分するようなものです。したがって、$erlierTimeに値1274467343$latterTimeに値1274467500を設定し、$latterTime - $erlierTimeを実行して、秒単位で経過時間を取得できます。

0
Babiker

[saved_date]をタイムスタンプに変換します。現在のタイムスタンプを取得します。

現在のタイムスタンプ-[saved_date]タイムスタンプ。

次に、date()でフォーマットできます。

通常、strtotime()関数を使用して、ほとんどの日付形式をタイムスタンプに変換できます。

0
Evernoob

最近これをしなければならなかった-これが誰かを助けることを願っています。すべての可能性に対応しているわけではありませんが、プロジェクトに対する私のニーズを満たしました。

https://github.com/duncanheron/Twitter_date_format

https://github.com/duncanheron/Twitter_date_format/blob/master/Twitter_date_format.php

0
Duncan

ここでは、日付時刻から経過した時間を見つけるためにカスタム関数を使用しています。

 
 echo Datetodays( '2013-7-26 17:01:10'); 
 
 function Datetodays($ d){
 
 $ date_start = $ d; 
 $ date_end = date( 'Ymd H:i:s'); 
 
 define( 'SECOND'、1); 
 define( 'MINUTE'、SECOND * 60); 
 define( 'HOUR'、MINUTE * 60); 
 define( 'DAY'、HOUR * 24); 
 define( 'WEEK'、DAY * 7); 
 
 $ t1 = strtotime($ date_start); 
 $ t2 = strtotime($ date_end); 
 if($ t1> $ t2){
 $ diffrence = $ t1-$ t2; 
} else {
 $ diffrence = $ t2-$ t1; 
        }

        //エコー "
「。$ date_end。」 「。$ date_start。」 "。$ diffrence; $ results ['major'] = array(); //日時関係のより大きな数を表す整数 $ results1 = array(); $ string = ''; $ results ['major'] ['weeks'] = floor($ diffrence/WEEK); $ results ['major'] [ 'days'] = floor($ diffrence/DAY); $ results ['major'] ['hours'] = floor($ diffrence/HOUR); $ results ['major' ] ['minutes'] = floor($ diffrence/MINUTE); $ results ['major'] ['seconds'] = floor($ diffrence/SECOND); //print_r($results); // Logic: //ステップ1:主要な結果を取得し、生の秒に変換します(差の秒数よりも少なくなります) ) //例:$ result =($ results ['major'] ['weeks'] * WEEK) //ステップ2:小さい数(結果)を差(合計時間) //例:$ minor_result = $ difference-$ result //ステップ3:結果の時間を秒単位で取得し、マイナー形式に変換します //例:floor($ minor_result/DAY) $ results1 ['weeks' ] = floor($ diffrence/WEEK); $ results1 ['days'] = floor((($ diffrence-($ results ['major'] ['weeks'] * WEEK))/ DAY) ); $ results1 ['hours'] = floor((($ diffrence-($ results ['major'] ['days'] * DAY))/ HOUR))); $ results1 ['minutes'] = floor((($ diffrence-($ results ['major'] ['hours'] * HOUR))/ MINUTE)); $ results1 ['seconds'] = floor ((($ diffrence-($ results ['major'] ['minutes'] * MINUTE))/ SECOND)); //print_r($results1); if($ results1 ['weeks']!= 0 && $ results1 ['days'] == 0){ if($ results1 ['weeks'] == 1){ $ string = $ results1 ['weeks']。 'week ago'; } else { if($ results1 ['weeks'] == 2){ $ string = $ results1 ['weeks']。 '週間前'; } else { $ string = '2週間前'; } } } elseif($ results1 [ 'weeks']!= 0 && $ results1 ['days']!= 0){ if($ results1 ['weeks'] == 1){ $ string = $ results1 [ 'weeks']。 'week ago'; } else { if($ results1 ['weeks'] == 2){ $ string = $ results1 ['weeks']。 '週間前'; } else { $ string = '2週間前'; } } } elseif($ results1 [ 'weeks'] == 0 && $ results1 ['days']!= 0){ if($ results1 ['days'] == 1){ $ string = $ results1 [ '日々'] 。 'day ago'; } else { $ string = $ results1 ['days']。 'days ago'; } } elseif($ results1 ['days']!= 0 && $ results1 ['hours']!= 0){ $ string = $ results1 ['days']。 '日と'。 $ results1 ['hours']。 '時間前'; } elseif($ results1 ['days'] == 0 && $ results1 ['hours']!= 0){ if($ results1 ['hours'] == 1){ $ string = $ results1 ['hours']。 '時間前'; } else { $ string = $ results1 ['hours']。 'hours ago'; } } elseif($ results1 ['hours']!= 0 && $ results1 ['minutes']!= 0){ $ string = $ results1 ['hours']。 '時間と'。 $ results1 ['minutes']。 '分前'; } elseif($ results1 ['hours'] == 0 && $ results1 ['minutes']!= 0){ if($ results1 ['minutes'] == 1){ $ string = $ results1 ['minutes']。 '分前'; } else { $ string = $ results1 ['minutes']。 'minutes ago'; } } elseif($ results1 ['minutes']!= 0 && $ results1 ['seconds']!= 0){ $ string = $ results1 ['minutes']。 '分と'。 $ results1 ['seconds']。 'seconds ago'; } elseif($ results1 ['minutes'] == 0 && $ results1 ['seconds']!= 0){ if($ results1 ['seconds'] == 1){ $ string = $ results1 ['seconds']。 'second ago'; } else { $ string = $ results1 ['seconds']。 '秒前'; } } return $ string; } ?>
0
user2622929

アーノスによる機能「humanTiming」の即興演奏。時間文字列を人間が読めるテキストバージョンに「完全に引き伸ばした」変換を計算します。たとえば、「1週間2日1時間28分14秒」のように言う

function humantime ($oldtime, $newtime = null, $returnarray = false)    {
    if(!$newtime) $newtime = time();
    $time = $newtime - $oldtime; // to get the time since that moment
    $tokens = array (
            31536000 => 'year',
            2592000 => 'month',
            604800 => 'week',
            86400 => 'day',
            3600 => 'hour',
            60 => 'minute',
            1 => 'second'
    );
    $htarray = array();
    foreach ($tokens as $unit => $text) {
            if ($time < $unit) continue;
            $numberOfUnits = floor($time / $unit);
            $htarray[$text] = $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':'');
            $time = $time - ( $unit * $numberOfUnits );
    }
    if($returnarray) return $htarray;
    return implode(' ', $htarray);
}
0
Arvind K.

このための関数を直接取得できますWordPressコアファイルはこちらをご覧ください

http://core.trac.wordpress.org/browser/tags/3.6/wp-includes/formatting.php#L2121

function human_time_diff( $from, $to = '' ) {
    if ( empty( $to ) )
        $to = time();

    $diff = (int) abs( $to - $from );

    if ( $diff < HOUR_IN_SECONDS ) {
        $mins = round( $diff / MINUTE_IN_SECONDS );
        if ( $mins <= 1 )
            $mins = 1;
        /* translators: min=minute */
        $since = sprintf( _n( '%s min', '%s mins', $mins ), $mins );
    } elseif ( $diff < DAY_IN_SECONDS && $diff >= HOUR_IN_SECONDS ) {
        $hours = round( $diff / HOUR_IN_SECONDS );
        if ( $hours <= 1 )
            $hours = 1;
        $since = sprintf( _n( '%s hour', '%s hours', $hours ), $hours );
    } elseif ( $diff < WEEK_IN_SECONDS && $diff >= DAY_IN_SECONDS ) {
        $days = round( $diff / DAY_IN_SECONDS );
        if ( $days <= 1 )
            $days = 1;
        $since = sprintf( _n( '%s day', '%s days', $days ), $days );
    } elseif ( $diff < 30 * DAY_IN_SECONDS && $diff >= WEEK_IN_SECONDS ) {
        $weeks = round( $diff / WEEK_IN_SECONDS );
        if ( $weeks <= 1 )
            $weeks = 1;
        $since = sprintf( _n( '%s week', '%s weeks', $weeks ), $weeks );
    } elseif ( $diff < YEAR_IN_SECONDS && $diff >= 30 * DAY_IN_SECONDS ) {
        $months = round( $diff / ( 30 * DAY_IN_SECONDS ) );
        if ( $months <= 1 )
            $months = 1;
        $since = sprintf( _n( '%s month', '%s months', $months ), $months );
    } elseif ( $diff >= YEAR_IN_SECONDS ) {
        $years = round( $diff / YEAR_IN_SECONDS );
        if ( $years <= 1 )
            $years = 1;
        $since = sprintf( _n( '%s year', '%s years', $years ), $years );
    }

    return $since;
}
0
Subodh Ghulaxe

自分で書いた

function getElapsedTime($eventTime)
{
    $totaldelay = time() - strtotime($eventTime);
    if($totaldelay <= 0)
    {
        return '';
    }
    else
    {
        if($days=floor($totaldelay/86400))
        {
            $totaldelay = $totaldelay % 86400;
            return $days.' days ago.';
        }
        if($hours=floor($totaldelay/3600))
        {
            $totaldelay = $totaldelay % 3600;
            return $hours.' hours ago.';
        }
        if($minutes=floor($totaldelay/60))
        {
            $totaldelay = $totaldelay % 60;
            return $minutes.' minutes ago.';
        }
        if($seconds=floor($totaldelay/1))
        {
            $totaldelay = $totaldelay % 1;
            return $seconds.' seconds ago.';
        }
    }
}
0