【问题标题】:Best way to calculate human readable elapsed time [closed]计算人类可读经过时间的最佳方法[关闭]
【发布时间】:2013-03-21 13:21:50
【问题描述】:

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

这是需要的输出:

  • elapsedTimeInSeconds > 一年,输出“#years, #months”
  • elapsedTimeInSeconds > 一个月,输出“#months,#days”
  • elapsedTimeInSeconds > 一天,输出“# days, # hours”
  • elapsedTimeInSeconds > 一小时,输出“# hours, # minutes”
  • elapsedTimeInSeconds > 一分钟,输出“# minutes, # seconds”

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

【问题讨论】:

  • 六个条件语句还不错,尽管我至少会将它放入一个函数中(代码重用和所有那些爵士乐)。我不确定这是否是一个很好的递归问题,因为没有基本情况。

标签: php algorithm elapsedtime


【解决方案1】:

我认为这更灵活,因为您可以轻松添加新单位,如十年、世纪等,并且代码不会改变:

$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];
}

【讨论】:

  • 有趣,我会尽快试试这个。
  • @cellover,你的 ASAP 有多快? :)
  • ASAP 通常代表“几年到一个世纪”。我尝试过,但最终决定采用更易读的解决方案,正如我在回复中提到的那样:stackoverflow.com/questions/15548792/…
  • 一年不是 365 天。它是 365 天还是 366 天,具体取决于它是否是闰年。
【解决方案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 循环不是很满意,但它实际上运行良好。

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

【讨论】:

    【解决方案3】:

    我用这个:

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

    【讨论】:

    • +1 编辑;不过,要求确实说,案文只有两部分。也许在 if 语句中,将它们推送到队列中,然后在函数结束时,将前两个弹出并从那里开始?
    • 更改为仅允许 2 个元素
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    • 2012-07-16
    • 1970-01-01
    • 2021-04-05
    • 2021-02-05
    相关资源
    最近更新 更多