计算年龄,实岁年月日

逻辑思路

以出生日期对比当前时间,计算时间差,然后转换为天数时间戳(秒),再分别计算年份,月份,天数(注:以时间差按年月日递减格式化时间);其他语言也可采用此逻辑思路;

注意关键点

因为年份按四年一闰(365 * 4)+ 1=365.25(一年份);均衡月份:365.25/12=30.4375;天份=86400;才能精确计算具体的年龄,若是要计算时分秒,可继续设定对应单位;附上代码示例

代码示例

代码方法采用PHP8版本,低版本修改入参即可,其他语言可借用此逻辑,修改一下语法即可

	/**
     * 计算年龄
     *
     * @param string|int $birthday 生日
     * @param int $type 类型:0默认年岁,1年月,2年月日
     * @param bool $is_fm 是否格式年月日:false默认格式化,true不格式化返回(岁数,不返月份和天数)
     * @return int|string
     */
    function age(string|int $birthday, int $type=0, bool $is_fm=false): int|string
    {
        $birthday = is_numeric($birthday) ? $birthday : strtotime($birthday);

        $d_unit = 86400; // 一天
        // 时间差:当前时间和出生日期之差
        $day_time = time() - $birthday;
        if ($day_time < $d_unit && $type < 3) {
            return 0;
        }

        // 年月日时间戳单位
        $units = [
            365.25 * $d_unit, // 一年:四年一闰=365 * 4 + 1
            30.4375 * $d_unit, // 一月:均衡每月月份=365.25 / 12
            $d_unit,  // 一天:24 * 3600
            3600, // 一小时: 60 * 60
            60 // 一分
        ];

        $ages = [];
        foreach ($units as $key=>$unit) {

            $age = floor($day_time / $unit);
            if ($is_fm === true) {
                return $age; // 不允许格式化,只能返回年龄(一年以内直接返回0,若要计算虚岁,则向上取一)
            }

            // 指定类型计算设定类型,截断后续操作
            if ($key === $type) {
                break;
            }

            // 计算出当前等于0,不操作
            if ($age == 0) {
                continue;
            }

            // 递减去当前等级的时间戳
            $day_time -= $age * $unit;
            // 拼接时间格式单位
            $age .= match ($key) {
                0=> '岁',
                1=> '月',
                2=> '天',
                3=> '小时',
                4=> '分',
                default=> ''
            };
            $ages[] = $age;
        }
        return implode('', $ages);
    }
 
# 调用示例
$birthday = '1990-07-01'; # 当前时间:2023-07-12
echo age($birthday); # 输出结果:33岁11天

运算逻辑解析

		$birthday = is_numeric($birthday) ? $birthday : strtotime($birthday);

        // 年-月-日-单位
        $y_unit = 365.25; // 一年:四年一闰=365 * 4 + 1;
        $m_unit = 30.4375; // 一月:均衡每月月份=365.25 / 12
        $d_unit = 86400; // 一天

        // 时间差:当前时间和出生日期之差
        $day_time = time() - $birthday;
        if ($day_time < $d_unit) {
            return 0;
        }

        // 计算年份
        $y_age = bcdiv($day_time, $y_unit * $d_unit);
        if ($is_fm === true) {
            return $y_age; // 不允许格式化,只能返回年龄(一年以内直接返回0,若要计算虚岁,则向上取一)
        }

        // 计算月份
        $day_time -= $y_age * ($y_unit * $d_unit); // 减去年份,剩余月份
        $m_age = bcdiv($day_time , $m_unit * $d_unit);

        // 计算天数
        $day_time -= $m_age *  ($m_unit * $d_unit); // 减去月份,剩余天份
        $d_age = bcdiv($day_time , $d_unit);

        // 格式化:年月日
        $fy_age = $y_age == 0 ? '' : $y_age.'岁';
        $fm_age = $m_age == 0 ? '' : $m_age.'月';
        $fd_age = $d_age == 0 ? '' : $d_age.'天';
        return match ($type) {
            1=> $fy_age . $fm_age,
            2=> $fy_age . $fm_age . $fd_age,
            default=> $fy_age
        };

反馈

若有疑问不解,欢迎留言讨论

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bobo-rs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值