You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PHP DateTime更优实现指定格式的日期范围展示?

优化日期范围格式化的PHP实现

需求说明

需要将两个日期按照以下格式展示:

29th and 30th November 2024
or
28th to 30th November 2024
or
28th October to 30th November 2024
or
30th November and 1st December 2024

现有实现代码

$date1 = new DateTime('2024-09-29');
$month1 = $date1->format('m');
$date2 = new DateTime('2024-09-30');
$month2 = $date2->format('m');
$interval = $date1->diff($date2);
if($month1 == $month2){
    if($interval->days == 1){
        $result_date = getDayWithSuffix($date1);
        $result_date .= ' and ';
        $result_date .= getDayWithSuffix($date2);
        $result_date .= ' '.$date1->format('F');
        $result_date .= ' '.$date1->format('Y');
    } else {
        $result_date = getDayWithSuffix($date1);
        $result_date .= ' to ';
        $result_date .= getDayWithSuffix($date2);
        $result_date .= ' '.$date1->format('F');
        $result_date .= ' '.$date1->format('Y');
    }
} else {
    if($interval->days == 1){
        $result_date = getDayWithSuffix($date1);
        $result_date .= ' '.$date1->format('F');
        $result_date .= ' and ';
        $result_date .= getDayWithSuffix($date2);
        $result_date .= ' '.$date2->format('F');
        $result_date .= ' '.$date1->format('Y');
    } else {
        $result_date = getDayWithSuffix($date1);
        $result_date .= ' '.$date1->format('F');
        $result_date .= ' to ';
        $result_date .= getDayWithSuffix($date2);
        $result_date .= ' '.$date2->format('F');
        $result_date .= ' '.$date1->format('Y');
    }
}

优化后的实现

可以通过抽离重复逻辑、简化条件判断让代码更简洁易维护,核心思路是:

  • 统一处理日期后缀生成
  • 根据日期间隔确定连接词(and用于间隔1天,to用于间隔多天)
  • 根据日期是否同月/跨年,决定月份和年份的展示方式

完整优化代码

/**
 * 生成带后缀的日期天数(如1st, 2nd, 3rd, 4th)
 * @param DateTime $date
 * @return string
 */
function getDayWithSuffix(DateTime $date): string {
    $day = (int)$date->format('j');
    $suffixes = ['th', 'st', 'nd', 'rd'];
    $mod = $day % 10;
    $suffix = ($mod >= 1 && $mod <=3 && ($day <11 || $day>13)) ? $suffixes[$mod] : $suffixes[0];
    return "{$day}{$suffix}";
}

/**
 * 格式化日期范围
 * @param DateTime $date1
 * @param DateTime $date2
 * @return string
 */
function formatDateRange(DateTime $date1, DateTime $date2): string {
    $interval = $date1->diff($date2);
    // 确定连接词:间隔1天用and,否则用to
    $connector = $interval->days === 1 ? ' and ' : ' to ';
    
    $day1 = getDayWithSuffix($date1);
    $day2 = getDayWithSuffix($date2);
    
    // 同月同一年的情况
    if ($date1->format('Ym') === $date2->format('Ym')) {
        return "{$day1}{$connector}{$day2} {$date1->format('F Y')}";
    }
    
    // 不同月或跨年情况
    $year1 = $date1->format('Y');
    $year2 = $date2->format('Y');
    $yearPart = $year1 === $year2 ? " {$year1}" : " {$year1} and {$year2}";
    
    return "{$day1} {$date1->format('F')}{$connector}{$day2} {$date2->format('F')}{$yearPart}";
}

// 测试示例
echo formatDateRange(new DateTime('2024-11-29'), new DateTime('2024-11-30')); // 29th and 30th November 2024
echo "\n";
echo formatDateRange(new DateTime('2024-11-28'), new DateTime('2024-11-30')); // 28th to 30th November 2024
echo "\n";
echo formatDateRange(new DateTime('2024-10-28'), new DateTime('2024-11-30')); // 28th October to 30th November 2024
echo "\n";
echo formatDateRange(new DateTime('2024-11-30'), new DateTime('2024-12-01')); // 30th November and 1st December 2024
echo "\n";
echo formatDateRange(new DateTime('2024-12-30'), new DateTime('2025-01-01')); // 30th December and 1st January 2024 and 2025

优化点说明

  • 逻辑复用:拆分出独立的后缀生成和范围格式化函数,提升代码可维护性
  • 简化判断:将多层嵌套的if-else简化为两步判断,逻辑更清晰
  • 兼容跨年:原代码未处理跨年场景,优化后的代码自动适配
  • 减少冗余:复用格式化结果,避免重复调用format方法和字符串拼接

内容的提问来源于stack exchange,提问作者B L Praveen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 10:17:36