PHP项目Carbon日期库常用

wen PHP项目 1

深度解析 PHP Carbon 日期库:从入门到项目实战的 15 个高频操作

目录导读

  1. Carbon 简介:为何成为 PHP 日期处理的事实标准?
  2. 安装与初始化:3 分钟接入你的项目
  3. 核心基础:创建、格式化与输出日期
  4. 日期比较:你还在用 strtotime 做对比?
  5. 时间运算:加减日期就像呼吸一样自然
  6. 时区处理:告别时区转换的噩梦
  7. 人性化显示:diffForHumans() 的 8 种场景
  8. 常用查询:判断今天、周末、闰年等 12 个方法
  9. 与数据库(Laravel/原生)的集成技巧
  10. 高级功能: macro 扩展与自定义格式
  11. 常见问答:6 个真实项目踩坑经验
  12. 性能优化与注意事项

Carbon 简介:为何成为 PHP 日期处理的事实标准?

在 PHP 生态中,日期和时间处理一直是开发者绕不开的话题,原生 PHP 的 DateTime 类和 strtotime 函数虽然可用,但代码冗长、方法链不流畅,尤其在时区转换、人性化显示方面显得捉襟见肘。

PHP项目Carbon日期库常用

Carbon 是什么?
Carbon 是基于 PHP 原生 DateTime 类的扩展库,通过继承原生类并提供 200+ 方法,让日期操作像“链式调用”一样优雅,官方文档显示,全球超过 50% 的 PHP 项目(尤其是 Laravel 框架)默认使用 Carbon。

为什么选择 Carbon?

  • 语义化方法addDay()DateInterval 创建 + add() 更直观
  • 零学习成本:兼容所有 DateTime 原生方法
  • 不可变性:默认方法返回新实例,避免意外修改原对象

安装与初始化:3 分钟接入你的项目

通过 Composer 安装

composer require nesbot/carbon

基本使用

use Carbon\Carbon;
echo Carbon::now(); // 2025-04-05 14:30:00
echo Carbon::today(); // 2025-04-05 00:00:00
echo Carbon::yesterday(); // 2025-04-04
echo Carbon::tomorrow(); // 2025-04-06

从时间戳/字符串创建

// 从时间戳
$dt = Carbon::createFromTimestamp(1712304000);
// 从字符串
$dt = Carbon::parse('next Friday');
$dt = Carbon::parse('2025-04-05 14:30:00');

核心基础:创建、格式化与输出日期

格式化方法

$dt = Carbon::now();
echo $dt->toDateString();      // 2025-04-05
echo $dt->toDateTimeString();  // 2025-04-05 14:30:00
echo $dt->toTimeString();      // 14:30:00
echo $dt->format('Y-m-d H:i:s'); // 自定义格式
echo $dt->isoFormat('LL');     // 2025年4月5日(语言国际化)

常用属性获取

$dt->year;    // 2025
$dt->month;   // 4
$dt->day;     // 5
$dt->hour;    // 14
$dt->minute;  // 30
$dt->second;  // 0
$dt->dayOfWeek;  // 6(周六,0=周日)
$dt->weekOfMonth; // 2

日期比较:你还在用 strtotime 做对比?

原生 PHP 比较日期需要手动转换,Carbon 提供了 10+ 种比较方法:

$first = Carbon::parse('2025-04-05');
$second = Carbon::parse('2025-06-15');
// 比较
$first->eq($second);        // false
$first->gt($second);        // false
$first->lt($second);        // true
$first->gte($second);       // false
$first->ne($second);        // true
// 范围比较
$first->between('2025-01-01', '2025-12-31', true); // true
$first->isWeekday();        // false(周六)
$first->isWeekend();        // true

实战场景:判断用户注册是否超过30天

$registeredAt = Carbon::parse($user->created_at);
if ($registeredAt->diffInDays(Carbon::now()) > 30) {
    echo "已注册超过30天";
}

时间运算:加减日期就像呼吸一样自然

加减操作

$dt = Carbon::now();
// 加
$dt->addDay();          // +1天
$dt->addDays(10);       // +10天
$dt->addWeek();         // +1周
$dt->addWeeks(3);       // +3周
$dt->addMonth();        // +1月
$dt->addYear();         // +1年
// 减(同理)
$dt->subMonth();        // -1月

链式调用示例

$dt = Carbon::now()
    ->addYear()
    ->subMonth()
    ->addDays(5);

注意:Carbon 默认返回新实例,不修改原对象,如果希望直接修改,需调用 ->modify() 或使用可变版本 Carbon\CarbonImmutable


时区处理:告别时区转换的噩梦

切换到其他时区

$dt = Carbon::now('Asia/Shanghai');
echo $dt->tzName; // Asia/Shanghai
$dt->setTimezone('America/New_York');
echo $dt->format('Y-m-d H:i:s'); // 自动转换时间

时区列表与检测

$dt->timezoneName;    // 获取时区全名
$dt->offsetHours;     // 时区偏移小时数(如 8)
// 列出所有可用时区
$timezones = Carbon::timezone()->getAbbreviations();

常用时区字符串

  • UTC / GMT
  • Asia/Shanghai(东八区)
  • America/New_York(美东时间)
  • Europe/London(伦敦时间)

人性化显示:diffForHumans() 的 8 种场景

这是 Carbon 最受好评的功能之一,自动生成“2小时前”“3天后”等描述:

$dt = Carbon::now()->subHours(2);
echo $dt->diffForHumans(); // "2 hours ago"
$future = Carbon::now()->addDays(5);
echo $future->diffForHumans(); // "5 days from now"
// 中文显示(需设置语言)
Carbon::setLocale('zh');
echo $dt->diffForHumans(); // "2小时前"

场景定制

// 绝对差异
echo $dt->diffForHumans(['join' => ', ']); // "2 hours, 30 minutes ago"
// 移除“ago”后缀
echo $dt->diffForHumans(['syntax' => CarbonInterface::DIFF_ABSOLUTE]); // "2 hours"
// 自定义比较时间
echo $dt->diffForHumans(Carbon::yesterday()); // "1 day after yesterday"

常用查询:判断今天、周末、闰年等 12 个方法

Carbon 内置了大量布尔查询方法,极大简化逻辑判断:

$dt = Carbon::now();
// 基本状态
$dt->isToday();       // true
$dt->isYesterday();   // false
$dt->isTomorrow();    // false
$dt->isFuture();      // false
$dt->isPast();        // true
// 每周/月/年判断
$dt->isWeekday();     // false(周六)
$dt->isWeekend();     // true
$dt->isMonday();      // false
$dt->isSunday();      // false
$dt->isLeapYear();    // false(2025不是闰年)
// 相对判断
$dt->isSameDay(Carbon::yesterday()); // false
$dt->isCurrentYear(); // true
$dt->isNextYear();    // false

与数据库(Laravel/原生)的集成技巧

Laravel Eloquent 中的 Carbon

Laravel 默认将 created_at 等时间戳自动转为 Carbon 实例,可直接调用:

$user = User::find(1);
echo $user->created_at->diffForHumans(); // "3 months ago"

批量设置为 Carbon

protected $dates = ['birthday', 'expired_at'];
// 在模型中定义后,这些字段自动转为 Carbon

原生 SQL 与 Carbon 互转

// 从数据库取出后转为 Carbon
$dateFromDb = $row['created_at'];
$carbon = Carbon::parse($dateFromDb);
// 存入数据库前
$dbValue = $carbon->toDateTimeString(); // 或直接传 Carbon,PDO 自动处理

高级功能:macro 扩展与自定义格式

宏扩展(自定义方法)

Carbon::macro('toAsiaString', function () {
    return $this->timezone('Asia/Shanghai')->format('Y-m-d H:i:s');
});
echo Carbon::now()->toAsiaString(); // 注册后全局使用

自定义格式化

// 周数表示
echo $dt->isoFormat('W'); // 当前年的第几周
// 语言本地化
Carbon::setLocale('fr');
echo $dt->isoFormat('dddd'); // "samedi"

静态工厂方法

Carbon::create(2025, 4, 5, 14, 30, 0); // 年月日时分秒
Carbon::createFromDate(2025, 4, 5);    // 仅日期
Carbon::createFromTime(14, 30);        // 仅时间

十一、常见问答:6 个真实项目踩坑经验

Q1:为什么 Carbon::now() 获取的是服务器时间而不是北京时间?
A:默认使用 PHP 配置的 date.timezone,需在项目入口设置:

date_default_timezone_set('Asia/Shanghai');
// 或 Laravel 修改 config/app.php 的 timezone

Q2:addMonth() 导致日期溢出(如 1月31日加1月变成3月3日)?
A:Carbon 自动处理溢出:

Carbon::parse('2025-01-31')->addMonth(); // 2025-03-03(因为2月只有28天)
// 若需保留一个月最后一天,使用 addMonthWithOverflow(false)

Q3:如何获取两个日期之间的所有日期?
A:使用 Carbon\CarbonPeriod

$period = Carbon::parse('2025-04-01')->toPeriod('2025-04-05');
foreach ($period as $date) {
    echo $date->format('Y-m-d'); // 输出 04-01 到 04-05
}

Q4:diffForHumans() 显示英文,如何改为中文?
A:安装中文语言包:

Carbon::setLocale('zh');
// 确保 PHP 安装了 intl 扩展

Q5:如何判断当前时间是否在某两个时间之间?
A:between() 方法:

$now = Carbon::now();
$start = Carbon::parse('2025-04-01');
$end = Carbon::parse('2025-04-30');
if ($now->between($start, $end, true)) { // true 包含边界
    echo "在范围内";
}

Q6:时间戳转换出现负数?
A:检查是否使用了毫秒时间戳(13位),需除以1000:

$microTimestamp = 1712304000000;
echo Carbon::createFromTimestamp($microTimestamp / 1000);

十二、性能优化与注意事项

  1. 避免频繁调用 now()
    循环内多次获取当前时间建议使用 $now = Carbon::now() 缓存变量。

  2. 善用 CarbonImmutable
    不可变版本在复杂链式操作中更安全,避免意外修改共享对象:

    use Carbon\CarbonImmutable;
    $dt = CarbonImmutable::now();
  3. 时区转换消耗
    每次 setTimezone() 会重新计算时间,批量处理时建议在开始一次性设置。

  4. 语言包缓存
    频繁切换 setLocale() 可能影响性能,对于固定语言在应用启动时设置即可。

  5. debug_backtrace 警告
    某些环境使用 __toString() 时可能触发性能问题,用 format() 代替。


Carbon 将 PHP 日期处理从“工具函数”提升为“流畅的语言”,建议在项目中尽早统一使用 Carbon,并结合 Laravel(如果使用)的自动类型转换,可减少80%的日期相关 Bug,对于新手,掌握 parse()diffForHumans()format()addDays() 这四个核心方法,就能应对90%的日常开发需求。

抱歉,评论功能暂时关闭!