2013-03-21 76 views
0

我想知道在给定一定的秒数的情况下,计算人类可读的时间的最优雅的方法是什么。我想用PHP写这个。计算人类可读时间的最佳方法

这是需要的输出:

  • elapsedTimeInSeconds>一年输出 “#年#月”
  • elapsedTimeInSeconds>一个月内,输出 “#月#日”
  • elapsedTimeInSeconds>有一天,输出 “#天,#小时”
  • elapsedTimeInSeconds>一小时输出 “#小时,#分钟”
  • elapsedTimeInSeconds>一分钟输出 “#分钟,#秒”

我已经尝试了不同的解决方案,这些解决方案很尴尬且充满了条件语句,但我希望有更多的递归和“干净的代码”方法。

+0

六个条件语句并不算太坏,尽管我会至少把它放到函数中(代码重用和所有爵士乐)。我不确定这是否是一个好的递归问题,因为没有基本情况。 – 2013-03-21 13:25:23

回答

1

我用这个:

function durationFormat($time) 
{ 
    if(gmdate("Y", $time)>1970) return (1970-gmdate("Y",$time)).gmdate(" \y\r\s ", $time).(gmdate("n",$time)-1).gmdate(" \m\o\n\t\h\s ", $time).(gmdate("j",$time)-1).gmdate(" \d\a\y\s H:i:s", $time); 
    if(gmdate("n", $time)>1) return (gmdate("n",$time)-1).gmdate(" \m\o\n\t\h\s ", $time).(gmdate("j",$time)-1).gmdate(" \d\a\y\s H:i:s", $time); 
    if(gmdate("j", $time)>1) return (gmdate("j",$time)-1).gmdate(" \d\a\y\s H:i:s", $time); 
    return gmdate("H:i:s", $time); 
} 

这是一个有点快速和肮脏的,但做这项工作

OR

function durationFormat2($seconds) 
{ 
    $a_sec=1; 
    $a_min=$a_sec*60; 
    $an_hour=$a_min*60; 
    $a_day=$an_hour*24; 
    $a_week=$a_day*52; 
    //$a_month=$a_day*(floor(365/12)); 
    $a_month=$a_day*30; 
    $a_year=$a_day*365; 

    $params=2; 
    $text=''; 
    if($seconds>$a_year) 
    { 
     $years=floor($seconds/$a_year); 
     $text.=$years.' years '; 
     $seconds=$seconds-($years*$a_year); 
     $params--; 
    } 
    if($params==0) return $text; 
    if($seconds>$a_month) 
    { 
     $months=floor($seconds/$a_month); 
     $text.=$months.' months '; 
     $seconds=$seconds-($months*$a_month); 
     $params--; 
    } 
    if($params==0) return $text; 
    if($seconds>$a_week) 
    { 
     $weeks=floor($seconds/$a_week); 
     $text.=$weeks.' weeks '; 
     $seconds=$seconds-($months*$a_week); 
     $params--; 
    } 
    if($params==0) return $text; 
    if($seconds>$a_day) 
    { 
     $days=floor($seconds/$a_day); 
     $text.=$days.' days '; 
     $seconds=$seconds-($days*$a_day); 
     $params--; 
    } 
    if($params==0) return $text; 
    $H=gmdate("H", $seconds); 
    if($H>0) 
    { 
     $text.=$H.' hours '; 
     $params--; 
    } 
    if($params==0) return $text; 
    $M=gmdate("i", $seconds); 
    if($M>0) 
    { 
     $text.=$M.' minutes '; 
     $params--; 
    } 
    if($params==0) return $text; 
    $S=gmdate("s", $seconds); 
    $text.=$S.' seconds '; 

    return $text; 
} 
+1

+1与编辑;但要求确实说,文本只有两个部分。也许在if语句中,将它们推送到队列中,在函数结束时,将前两个关闭并从那里出发? – 2013-03-21 13:36:17

+0

改为只允许2个元素 – Waygood 2013-03-21 14:13:58

3

我觉得这是比较灵活,您可以轻松地添加新单位像十年,世纪等,并且代码不会改变:

$names = array("seconds", "minutes", "hours", "days", "months", "years"); 
$values = array(1, 60, 3600, 24 * 3600, 30 * 24 * 3600, 365 * 24 * 3600); 

$time = ...elapsedTimeInSeconds...; 
for($i = count($values) - 1; $i > 0 && $time < $values[$i]; $i--); 
if($i == 0) { 
    echo intval($time/$values[$i]) . " " . $names[$i]; 
} else { 
    $t1 = intval($time/$values[$i]); 
    $t2 = intval(($time - $t1 * $values[$i])/$values[$i - 1]); 
    echo "$t1 " . $names[$i] . ", $t2 " . $names[$i - 1]; 
} 
+0

有趣,我会尽快尝试这一个。 – cellover 2013-03-21 17:05:50

+0

@cellover,你的ASAP有多快? :) – Andron 2014-04-26 14:03:22

+0

尽快通常代表“几年到一个世纪”。 我试过了,但最后决定去找一个更具可读性的解决方案,就像我在回复中提到的那样:http://stackoverflow.com/questions/15548792/best-way-to-calculate-human-readable-elapsed-time/15551814 #15551814 – cellover 2014-04-30 08:59:19

2

谢谢您的建议。

我主要使用Waygood和ChrisForrence对此方法的建议。我尽量保持简单,并引入了简单的参数,如细节级别和分隔符(用于字符串输出)。

public function elapsedTimeHumanReadable($date = null, $detailLevel = 2, $delimiter = ' et ') 
{ 
    if($date === null) 
    { 
     $date = self::now(); 
    } 

    $sec = $this->elapsedSecond($date); 

    $a_sec = 1; 
    $a_min = $a_sec * 60; 
    $an_hour = $a_min * 60; 
    $a_day = $an_hour * 24; 
    $a_month = $a_day * 30; 
    $a_year = $a_day * 365; 

    $text = ''; 
    $resultStack = array(); 
    if($sec >= $a_year) 
    { 
     $years = floor($sec/$a_year); 
     $text .= $years . $this->plural($years, ' an'); 
     $sec = $sec - ($years * $a_year); 
     array_push($resultStack, $text); 
    } 

    if($sec >= $a_month) 
    { 
     $months = floor($sec/$a_month); 
     $text = $months . ' mois'; 
     $sec = $sec - ($months * $a_month); 
     array_push($resultStack, $text); 
    } 

    if($sec >= $a_day) 
    { 
     $days = floor($sec/$a_day); 
     $text = $days . $this->plural($days, ' jour'); 
     $sec = $sec - ($days * $a_day); 
     array_push($resultStack, $text); 
    } 

    if($sec >= $an_hour) 
    { 
     $hours = floor($sec/$an_hour); 
     $text = $hours . $this->plural($hours, ' heure'); 
     $sec = $sec - ($hours * $an_hour); 
     array_push($resultStack, $text); 
    } 

    if($sec >= $a_min) 
    { 
     $minutes = floor($sec/$a_min); 
     $text = $minutes . $this->plural($minutes, ' minute'); 
     $sec = $sec - ($minutes * $a_min); 
     array_push($resultStack, $text); 
    } 

    if($sec >= $a_sec) 
    { 
     $seconds = floor($sec/$a_sec); 
     $text = $sec . $this->plural($seconds, ' seconde'); 
     $sec = $sec - ($sec * $a_sec); 
     array_push($resultStack, $text); 
    } 

    $result = $resultStack[0]; 
    for($i = 1; $i <= $detailLevel - 1; $i++) 
    { 
     if(!empty($resultStack[$i])) 
     { 
      $result .= $delimiter . $resultStack[$i]; 
     } 
    } 

    return $result; 
} 

我还添加了一个非常简单的多的功能在正确的语法的方式返回的时间单位:

public function plural($value, $unit) 
{ 
    if($value > 1) 
    { 
     return $unit . 's'; 
    } 
    else 
    { 
     return $unit; 
    } 
} 

我不是在for循环真的很高兴,但实际上工作正常。

无论如何,非常感谢您的帮助!