PHP: damgaları dan üreten göreceli tarih / saati

6 Cevap php

Ben temelde geçmiş ve gelecek tarih ile uyumlu hem de bir göreceli tarih / zaman için bir Unix zaman damgası (time () fonksiyonu) dönüştürmek çalışıyorum. Yani çıkışlar olabilir:

2 hafta önce

1 saat ve 60 dakika önce

15 dakika ve 54 saniye önce

10 dakika ve 15 saniye sonra

Öncelikle bu kod çalıştı, ama büyük bir unmaintainable işlevini yaptı ve sonra birkaç saat için internet arama, ama ben bulabileceğiniz tüm zaman sadece bir kısmını (eh üretmek komut vardır: "1 saat önce" olmadan dakika).

Zaten bunu yapan bir script var mı?

6 Cevap

Bu fonksiyon size 'şimdi' ve 'özel damgası' arasındaki sonuçları gibi "1 saat önce" ya da "Yarın" verir.

function time2str($ts)
{
    if(!ctype_digit($ts))
        $ts = strtotime($ts);

    $diff = time() - $ts;
    if($diff == 0)
        return 'now';
    elseif($diff > 0)
    {
        $day_diff = floor($diff / 86400);
        if($day_diff == 0)
        {
            if($diff < 60) return 'just now';
            if($diff < 120) return '1 minute ago';
            if($diff < 3600) return floor($diff / 60) . ' minutes ago';
            if($diff < 7200) return '1 hour ago';
            if($diff < 86400) return floor($diff / 3600) . ' hours ago';
        }
        if($day_diff == 1) return 'Yesterday';
        if($day_diff < 7) return $day_diff . ' days ago';
        if($day_diff < 31) return ceil($day_diff / 7) . ' weeks ago';
        if($day_diff < 60) return 'last month';
        return date('F Y', $ts);
    }
    else
    {
        $diff = abs($diff);
        $day_diff = floor($diff / 86400);
        if($day_diff == 0)
        {
            if($diff < 120) return 'in a minute';
            if($diff < 3600) return 'in ' . floor($diff / 60) . ' minutes';
            if($diff < 7200) return 'in an hour';
            if($diff < 86400) return 'in ' . floor($diff / 3600) . ' hours';
        }
        if($day_diff == 1) return 'Tomorrow';
        if($day_diff < 4) return date('l', $ts);
        if($day_diff < 7 + (7 - date('w'))) return 'next week';
        if(ceil($day_diff / 7) < 4) return 'in ' . ceil($day_diff / 7) . ' weeks';
        if(date('n', $ts) == date('n') + 1) return 'next month';
        return date('F Y', $ts);
    }
}
function relativeTime($time) {

    $d[0] = array(1,"second");
    $d[1] = array(60,"minute");
    $d[2] = array(3600,"hour");
    $d[3] = array(86400,"day");
    $d[4] = array(604800,"week");
    $d[5] = array(2592000,"month");
    $d[6] = array(31104000,"year");

    $w = array();

    $return = "";
    $now = time();
    $diff = ($now-$time);
    $secondsLeft = $diff;

    for($i=6;$i>-1;$i--)
    {
         $w[$i] = intval($secondsLeft/$d[$i][0]);
         $secondsLeft -= ($w[$i]*$d[$i][0]);
         if($w[$i]!=0)
         {
            $return.= abs($w[$i]) . " " . $d[$i][1] . (($w[$i]>1)?'s':'') ." ";
         }

    }

    $return .= ($diff>0)?"ago":"left";
    return $return;
}

Kullanımı:

echo relativeTime((time()-256));
4 minutes 16 seconds ago

İşte ben yazdım budur. Bugünün tarihine göre bir geçmiş tarihini görüntüler.

/**
 * @param $date integer of unixtimestamp format, not actual date type
 * @return string
 */
function zdateRelative($date)
{
    $now = time();
    $diff = $now - $date;

    if ($diff < 60){
        return sprintf($diff > 1 ? '%s seconds ago' : 'a second ago', $diff);
    }

    $diff = floor($diff/60);

    if ($diff < 60){
        return sprintf($diff > 1 ? '%s minutes ago' : 'one minute ago', $diff);
    }

    $diff = floor($diff/60);

    if ($diff < 24){
        return sprintf($diff > 1 ? '%s hours ago' : 'an hour ago', $diff);
    }

    $diff = floor($diff/24);

    if ($diff < 7){
        return sprintf($diff > 1 ? '%s days ago' : 'yesterday', $diff);
    }

    if ($diff < 30)
    {
        $diff = floor($diff / 7);

        return sprintf($diff > 1 ? '%s weeks ago' : 'one week ago', $diff);
    }

    $diff = floor($diff/30);

    if ($diff < 12){
        return sprintf($diff > 1 ? '%s months ago' : 'last month', $diff);
    }

    $diff = date('Y', $now) - date('Y', $date);

    return sprintf($diff > 1 ? '%s years ago' : 'last year', $diff);
}

I xdebug tarafından relativeTime işlevini seviyorum. Sorun bazı boyutu var bunu gerekli değildir.

In other words stop at seconds or minutes if I decide. So now,

echo fTime(strtotime('-23 hours 5 minutes 55 seconds'),0); 

gösterecektir,

23 hours, 5 minutes ago

Yerine

23 hours, 5 minutes, 55 seconds ago

I also wanted it to NOT go lower in the array if it reached one of the higher time amounts. So if it shows years, I only want to show years and months. So now,

echo fTime(strtotime('-1 year 2 months 3 weeks 4 days 16 hours 15 minutes 22 seconds'),0); 

Gösterebilir misiniz

1 year, 2 months ago

Yerine

1 year, 2 months, 3 weeks, 4 days, 16 hours, 15 minutes, 22 seconds ago

The following code change did what I needed. Props go to xdebug first of course. Hopefully someone else might find it useful:

function fTime($time, $gran=-1) {

    $d[0] = array(1,"second");
    $d[1] = array(60,"minute");
    $d[2] = array(3600,"hour");
    $d[3] = array(86400,"day");
    $d[4] = array(604800,"week");
    $d[5] = array(2592000,"month");
    $d[6] = array(31104000,"year");

    $w = array();

    $return = "";
    $now = time();
    $diff = ($now-$time);
    $secondsLeft = $diff;
    $stopat = 0;
    for($i=6;$i>$gran;$i--)
    {
         $w[$i] = intval($secondsLeft/$d[$i][0]);
         $secondsLeft -= ($w[$i]*$d[$i][0]);
         if($w[$i]!=0)
         {
            $return.= abs($w[$i]) . " " . $d[$i][1] . (($w[$i]>1)?'s':'') ." ";
             switch ($i) {
                case 6: // shows years and months
                    if ($stopat==0) { $stopat=5; }
                    break;
                case 5: // shows months and weeks
                    if ($stopat==0) { $stopat=4; }
                    break;
                case 4: // shows weeks and days
                    if ($stopat==0) { $stopat=3; }
                    break;
                case 3: // shows days and hours
                    if ($stopat==0) { $stopat=2; }
                    break;
                case 2: // shows hours and minutes
                    if ($stopat==0) { $stopat=1; }
                    break;
                case 1: // shows minutes and seconds if granularity is not set higher
                    break;
             }
             if ($i===$stopat) { break 0; }
         }
    }

    $return .= ($diff>0)?"ago":"left";
    return $return;
}

Marcus

Neden drupal yapar bu şekilde rip değil - http://api.drupal.org/api/drupal/includes%21common.inc/function/format_interval/7

<?php
function format_interval($interval, $granularity = 2, $langcode = NULL) {
  $units = array(
    '1 year|@count years' => 31536000, 
    '1 month|@count months' => 2592000, 
    '1 week|@count weeks' => 604800, 
    '1 day|@count days' => 86400, 
    '1 hour|@count hours' => 3600, 
    '1 min|@count min' => 60, 
    '1 sec|@count sec' => 1,
  );
  $output = '';
  foreach ($units as $key => $value) {
    $key = explode('|', $key);
    if ($interval >= $value) {
      $output .= ($output ? ' ' : '') . format_plural(floor($interval / $value), $key[0], $key[1], array(), array('langcode' => $langcode));
      $interval %= $value;
      $granularity--;
    }

    if ($granularity == 0) {
      break;
    }
  }
  return $output ? $output : t('0 sec', array(), array('langcode' => $langcode));
}
?>

(Muhtemelen) çoklu dil desteği yok gibi muhtemelen t için bir yedek () gerek yoktur ve oldukça kolay format_plural için kendi şey yapabilirdi. http://api.drupal.org/api/drupal/includes%21common.inc/function/format_plural/7

@ Marcus tarafından yayınlanmıştır cevap sadece kısa bir açıklama (http://stackoverflow.com/a/16380094/2026344)

Bu hat

if ($i===$stopat) { break 0; }

sonraki değeri 0 değil ise icra edilecek, çünkü if bloğunda olmamalıdır. Çoğu durumda bu iyi çalışır, ama fark ise örneğin, döngü kırmak asla 2 yıl, 0 ay, 3 hafta vb Sadece if bloğunun dışına itmek, ve sen iyisin.