我想知道给定一定的秒数,计算人类可读的弹性时间的最优雅的方法是什么。我想用PHP写这个
下面是需要的输出:
- elapsedTimeInSeconds>一年,输出"# years, # months"
- elapsedTimeInSeconds>一个月,输出"# months, # days"
- elapsedTimeInSeconds>一天,输出"# days, # hours"
- elapsedTimeInSeconds>一个小时,输出"# hours, # minutes"
- elapsedTimeInSeconds> 1分钟,输出"# minutes, # seconds"
我已经尝试了不同的解决方案,尴尬和充满条件语句,但我希望有一个更递归和"干净的代码"的方法。
我认为这是更灵活的,因为你可以很容易地添加新的单位,如十年,世纪等,代码不会改变:
$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];
}
谢谢你的建议。
对于这个方法,我主要使用了Waygood和chrisforence的建议。我尽量使它保持简单,并引入了简单的参数,如细节级别和分隔符(用于字符串输出)。
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循环不是很满意,但它实际上工作得很好。
无论如何,非常感谢你的帮助!我用这个:
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);
}
这是有点快和脏,但工作
或
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;
}