首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从秒值创建格式化的“[时间][单位]前”消息

从秒值创建格式化的“[时间][单位]前”消息
EN

Code Review用户
提问于 2020-08-29 02:59:47
回答 1查看 30关注 0票数 4

我有一个函数,它计算一个特定的时间字符串之前的秒、分钟、小时等等。

然而,我这样做是由一个庞大的if语句块组成的,它贯穿于它能够达到的每一个特定时间。

是否有更好的方法来编写这段代码,使其更高效,并且没有一个庞大的if语句块?

代码语言:javascript
复制
define('SECS_IN_MIN', 60);
define('SECS_IN_HR', 3600);
define('SECS_IN_DAY', 86400);
define('SECS_IN_WEEK', 604800);   // 7 days
define('SECS_IN_MONTH', 2592000); // 30 days
define('SECS_IN_YEAR', 31536000); // 365 days

// Determines if a number is a plural
// Input: Takes in a number
// Output: Outputs a string which is either "s", if plural
//         OR "" if not plural
function is_plural($num) {
    if ($num != 1) return "s";
    else return "";
}

// Gets a string line x minutes ago
// Input a date
// Output: a string which matches its time ago
function date_to_str($time) {
    $currTime = time();
    $pastTime = strtotime($time);
    $diff = $currTime - $pastTime;

    // Seconds Ago
    if ($diff < SECS_IN_MIN) {
        $plural = is_plural($diff);
        return "$ans few second$plural ago";
    
    // Minutes Ago
    } else if($diff < SECS_IN_HR) {
        $ans = floor($diff / SECS_IN_MIN);
        $plural = is_plural($ans);
        return "$ans minute$plural ago";
    
    // Hours Ago
    } else if ($diff < SECS_IN_DAY) {
        $ans = floor($diff / SECS_IN_HR);
        $plural = is_plural($ans);
        return "$ans hour$plural ago";
    
    // Days Ago
    } else if ($diff < SECS_IN_WEEK) {
        $ans = floor($diff / SECS_IN_DAY);
        $plural = is_plural($ans);
        return "$ans day$plural ago";

    // Weeks ago
    } else if ($diff < SECS_IN_MONTH) {
        $ans = floor($diff / SECS_IN_WEEK);
        $plural = is_plural($ans);
        return "$ans week$plural ago";

    // Months Ago
    } else if ($diff < SECS_IN_YEAR) {
        $ans = floor($diff / SECS_IN_MONTH);
        $plural = is_plural($ans);
        return "$ans month$plural ago";
    
    // Years Ago
    } else if ($diff > SECS_IN_YEAR * 10) {
        $ans = floor($diff / SECS_IN_YEAR);
        $plural = is_plural($ans);
        return "$ans year$plural ago";
    }

    return "-1";
}

$time = "2020-08-25 13:02:32"
echo( date_to_str($time) );
// Outputs 4 days ago
EN

回答 1

Code Review用户

发布于 2020-08-29 06:07:59

首先,下面是我推荐的脚本替换(受这是如此的帖子启发)和一些测试用例:

代码:(演示)

代码语言:javascript
复制
function secondsToTime($seconds) {
    $dtF = new DateTime('@0');
    $dtT = new DateTime("@$seconds");
    $diff = $dtF->diff($dtT);
    $units = [
        'y' => 'year',
        'm' => 'month',
        'd' => 'day',
        'h' => 'hour',
        'i' => 'minute',
        's' => 'second'
    ];
    foreach ($units as $char => $unit) {
        if ($diff->$char) {
            if ($char === 'd' && $diff->$char >= 7) {
                $diff->$char = floor($diff->$char / 7);
                $unit = 'week';
            }
            return sprintf(
                '%d %s%s ago',
                $diff->$char,
                $unit,
                $diff->$char !== 1 ? 's' : ''
            );
        }
    }
}

$tests = [
    53 =>  53,           // y=0, m=0, d=0,  h=0, i=0,  s=53
    365 => 365,          // y=0, m=0, d=0,  h=0, i=6,  s=5
    7200 => 7200,        // y=0, m=0, d=0,  h=2, i=0,  s=0
    176455 => 176455,    // y=0, m=0, d=2,  h=1, i=0,  s=55
    2002000 => 2002000,  // y=0, m=0, d=23, h=4, i=6,  s=40
    4592000 => 4592000,  // y=0, m=1, d=22, h=3, i=33, s=20
    66536000 => 66536000 // y=2, m=1, d=9,  h=2, i=13, s=20
];

var_export(
    array_map('secondsToTime', $tests)
);

输出:

代码语言:javascript
复制
array (
  53 => '53 seconds ago',
  365 => '6 minutes ago',
  7200 => '2 hours ago',
  176455 => '2 days ago',
  2002000 => '3 weeks ago',
  4592000 => '1 month ago',
  66536000 => '2 years ago',
)

通过利用PHP对象的优点,您可以从DateTime计算中选择最大的非零单元,并从循环/函数中快速返回。作为一种奖励,您不需要担心夏时制或闰年之类的事情--相信diff()方法。

如果您调用var_export($diff),您将看到填充了其他属性,但您只需要其中的6个。

我不认为我会麻烦一个多元函数的开销,只需将条件写成内联条件(三元)即可。

如果你想让$unit成为常量,好吧,因为它不会变异。

唯一需要的特殊处理是周计算,因为这不是对象中立即可用的属性。执行简单的算法并更改要显示的单元,然后继续返回所需的字符串。

至于批评你的代码:

  • $ans总是返回,但并不总是声明的;我假设这是您忽略的错误。
  • 您的is_plural()条件块缺少它的大括号。
  • else if作为两个词在php中是违反PSR-12编码标准的.你应该把一个词组成为elseif
  • 我希望您的-1返回永远不会达到,但如果达到了,那就意味着您需要验证传入的秒值。
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/248595

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档