2010-04-22 14 views
26

Básicamente trato de convertir una marca de tiempo Unix (la función de tiempo) en una fecha/hora relativa que sea compatible con la fecha pasada y futura. Así salidas podrían ser: hacePHP: produciendo fecha/hora relativas a las marcas de tiempo

2 semanas

hace 1 hora y 60 minutos

15 minutos y hace

54 segundos después de 10 minutos y 15 segundos

Primero traté de codificar esto, pero hice una gran función inmanejable, y luego busqué en internet por un par de horas, sin embargo, todo lo que puedo encontrar son scri. puntos que producen solo una parte del tiempo (e.h: "1 hora antes" sin los minutos).

¿Tiene un script que ya lo hace?

+0

Tal vez esto puede ayudar a: http: // stackoverflow. com/questions/2643113/convert-2010-04-16-163000-to-tomorrow-afternoon/2643137 –

+1

posible duplicado de [¿Cómo puedo calcular relati ve time?] (http://stackoverflow.com/questions/11/how-do-i-calculate-relative-time) – hakre

Respuesta

44

Esta función le da "1 hora atrás" o "mañana" como resultados entre "ahora" y "marca de tiempo específica".

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

pero eso solo devuelve las horas con los minutos (por ejemplo), ¿verdad? – KeyStroke

+1

ok esto? 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; 
} 

Uso:

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

Esto es lo que he escrito. Muestra una fecha pasada relativa a la fecha de hoy.

/** 
* @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

Por qué no estafar a la forma en que lo hace Drupal - 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)); 
} 
?> 

Es probable que no necesita un reemplazo para t() y que podría hacer su propia cosa para format_plural bastante fácilmente como usted (probablemente) no tiene que admitir varios idiomas. http://api.drupal.org/api/drupal/includes%21common.inc/function/format_plural/7

+1

¿La función de Drupal no estaría protegida por su licencia de copyright/código abierto? –

+0

@Rhino, depende completamente de lo que planeas hacer con tu código. Si no está distribuyendo el código fuente, puede hacer lo que quiera con el código GPL en Drupal. Si está distribuyendo su código fuente (por dinero o gratis), el uso de una parte de Drupal afectará la licencia que puede redistribuir (es decir, tendría que distribuir bajo licencia GPL) - http: // drupal. org/licensing/faq. –

+1

Sí, entiendo la GPL, solo señalo que es posible que desee mencionar la limitación en la respuesta. –

4

Me encanta la función relativeTime por xdebug. El problema es que necesitaba que tuviera cierta granularidad.

En otras palabras, pare en segundos o minutos si así lo decidiera. Así que ahora,

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

mostraría,

23 horas, 5 minutos hace

En lugar de

23 horas, 5 minutos, 55 hace segundos

También quería que NO fuera menor en la matriz si alcanzaba una de las cantidades de tiempo más altas. Entonces, si muestra años, solo quiero mostrar años y meses. Así que ahora,

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

mostraría

1 año, 2 meses

En lugar de

1 año, 2 meses, 3 semanas , 4 días, 16 horas, 15 minutos, 22 segundos hace

El siguiente cambio de código hizo lo que necesitaba. Los apoyos van a xdebug primero, por supuesto. Esperemos que alguien más podría encontrar útil:

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

lo necesitaba para dar resultados mí como abajo, por lo que escribió el mío. Con suerte, esto ayudará a alguien.

Ejemplo de uso:

$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 

Código:

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

Gracias, me gustó tu función y la usé. – phansen

+1

de nada :) @phansen – Ozzy

+1

También he usado una versión ligeramente modificada de esto en mi proyecto. – VSG24

1

Esto es lo que yo uso para tiempos pasados:

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

muchas gracias por esto. Para aquellos que quieran usar esto pero muestren horas limitadas solo a 24, reemplace 70 por 24 en el tercer elemento de puntos []. – Bayou

Cuestiones relacionadas