2010-04-22 5 views
26

Ich versuche im Grunde, einen Unix-Zeitstempel (die time() -Funktion) zu einem relativen Datum/Uhrzeit zu konvertieren, die sowohl mit vergangenen und zukünftigen Datum kompatibel ist. So könnten Ausgänge sein:PHP: relative Datum/Uhrzeit aus Zeitstempeln

2 Wochen

1 Stunde und 60 Minuten vor

15 Minuten und 54 Sekunden vor

nach 10 Minuten und 15 Sekunden

Zuerst habe ich versucht, dies zu kodieren, aber ich habe eine riesige, nicht zu behaltende Funktion gemacht, und dann habe ich ein paar Stunden im Internet gesucht, aber alles, was ich finden kann, sind Scri Punkte, die nur einen Teil der Zeit produzieren (zB: "1 Stunde" ohne die Minuten).

Haben Sie ein Skript, das dies bereits tut?

+0

Vielleicht können Sie helfen: http: // Stackoverflow. com/questions/2643113/convert-2010-04-16-163000-zu-morgen-nachmittag/2643137 –

+1

möglich duplikat von [Wie berechne ich relati Zeit?] (http://stackoverflow.com/questions/11/how-do-i-calculate-relative-time) – hakre

Antwort

44

Diese Funktion gibt Ihnen "1 Stunde" oder "Morgen" wie Ergebnisse zwischen "Jetzt" und "bestimmter Zeitstempel".

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); 
    } 
} 
+0

aber das gibt nur die Stunden mit den Minuten zurück (zum Beispiel), richtig? – KeyStroke

+1

ok das? http://pastie.org/929624 – osm

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

Verbrauch:

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

Hier ist, was ich geschrieben habe. Zeigt ein vergangenes Datum in Bezug auf das heutige Datum an.

/** 
* @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); 
} 
0

Warum Abzocke nicht die Art und Weise, dass Drupal tut es - 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)); 
} 
?> 

Sie wahrscheinlich nicht brauchen einen Ersatz für t() und man konnte für format_plural ziemlich leicht Ihre eigene Sache tun als Sie müssen (wahrscheinlich) nicht mehrere Sprachen unterstützen. http://api.drupal.org/api/drupal/includes%21common.inc/function/format_plural/7

+1

Wäre nicht die Funktion von Drupal unter ihrer Urheberrechts-/Open-Source-Lizenz geschützt? –

+0

@Rhino, es hängt ganz davon ab, was Sie mit Ihrem Code vorhaben. Wenn Sie den Quellcode nicht verteilen, können Sie mit dem GPL-Code in Drupal tun, was Ihnen gefällt. Wenn Sie Ihren Quellcode verteilen (gegen Geld oder kostenlos), dann würde die Verwendung eines Teils von Drupal die Lizenz beeinflussen, unter der Sie weiterverteilen können (dh Sie müssten selbst unter einer GPL-Lizenz verteilen) - http: // drupal. org/Lizenzierung/faq. –

+1

Ja, ich verstehe die GPL, nur darauf hinweisen, dass Sie die Einschränkung in der Antwort erwähnen möchten. –

4

Ich liebe die RelativeTime Funktion von xdebug. Problem ist, dass ich eine gewisse Granularität brauche.

Mit anderen Worten halt nach Sekunden oder Minuten, wenn ich mich entscheide. So, jetzt

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

zeigen würde,

23 Stunden, 5 Minuten vor

Statt

23 Stunden, 5 Minuten, 55 Sekunden zuvor

Ich wollte auch, dass es im Array nicht niedriger wird, wenn es einen der höheren Zeitbeträge erreicht. Also wenn es Jahre zeigt, möchte ich nur Jahre und Monate zeigen. So, jetzt

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

1 Jahr zeigen würde, 2 Monate vor

Statt

1 Jahr, 2 Monate, 3 Wochen , 4 Tage, 16 Stunden, 15 Minuten, 22 Sekunden vor

Die folgende Codeänderung tat, was ich brauchte. Requisiten gehen natürlich zuerst zu xdebug. Hoffentlich jemand anderes könnte es nützlich finden:

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

3

Ich brauchte man mich, wie unten zu geben, führt, so dass ich schrieb mein eigenes. Hoffentlich hilft das jemandem.

Beispiel Nutzung:

$datetime = "2014-08-13 12:52:48"; 
echo getRelativeTime($datetime); //10 hours ago 
echo getRelativeTime($datetime, 1); //10 hours ago 
echo getRelativeTime($datetime, 2); //10 hours and 50 minutes ago 
echo getRelativeTime($datetime, 3); //10 hours, 50 minutes and 50 seconds ago 
echo getRelativeTime($datetime, 4); //10 hours, 50 minutes and 50 seconds ago 

Code:

public function getRelativeTime($datetime, $depth=1) { 

    $units = array(
     "year"=>31104000, 
     "month"=>2592000, 
     "week"=>604800, 
     "day"=>86400, 
     "hour"=>3600, 
     "minute"=>60, 
     "second"=>1 
    ); 

    $plural = "s"; 
    $conjugator = " and "; 
    $separator = ", "; 
    $suffix1 = " ago"; 
    $suffix2 = " left"; 
    $now = "now"; 
    $empty = ""; 

    # DO NOT EDIT BELOW 

    $timediff = time()-strtotime($datetime); 
    if ($timediff == 0) return $now; 
    if ($depth < 1) return $empty; 

    $max_depth = count($units); 
    $remainder = abs($timediff); 
    $output = ""; 
    $count_depth = 0; 
    $fix_depth = true; 

    foreach ($units as $unit=>$value) { 
     if ($remainder>$value && $depth-->0) { 
      if ($fix_depth) { 
       $max_depth -= ++$count_depth; 
       if ($depth>=$max_depth) $depth=$max_depth; 
       $fix_depth = false; 
      } 
      $u = (int)($remainder/$value); 
      $remainder %= $value; 
      $pluralise = $u>1?$plural:$empty; 
      $separate = $remainder==0||$depth==0?$empty: 
          ($depth==1?$conjugator:$separator); 
      $output .= "{$u} {$unit}{$pluralise}{$separate}"; 
     } 
     $count_depth++; 
    } 
    return $output.($timediff<0?$suffix2:$suffix1); 
} 
+1

Danke, mir hat deine Funktion gefallen und sie genutzt. – phansen

+1

du bist willkommen :) @phansen – Ozzy

+1

Ich habe auch eine leicht modifizierte Version von diesem in meinem Projekt verwendet. – VSG24

1

Hier ist, was ich für vergangene Zeiten verwenden:

function zdateRelative($date) 
{ 
    $diff = time() - $date; 
    $periods[] = [60, 1, '%s seconds ago', 'a second ago']; 
    $periods[] = [60*100, 60, '%s minutes ago', 'one minute ago']; 
    $periods[] = [3600*70, 3600, '%s hours ago', 'an hour ago']; 
    $periods[] = [3600*24*10, 3600*24, '%s days ago', 'yesterday']; 
    $periods[] = [3600*24*30, 3600*24*7, '%s weeks ago', 'one week ago']; 
    $periods[] = [3600*24*30*30, 3600*24*30, '%s months ago', 'last month']; 
    $periods[] = [INF, 3600*24*265, '%s years ago', 'last year']; 
    foreach ($periods as $period) { 
    if ($diff > $period[0]) continue; 
    $diff = floor($diff/$period[1]); 
    return sprintf($diff > 1 ? $period[2] : $period[3], $diff); 
    } 
} 
+1

vielen Dank dafür. Für diejenigen, die dies verwenden möchten, aber die Stunden nur auf 24 Stunden begrenzt sind, ersetzen Sie 70 in der dritten Punktperiode durch []. – Bayou