Laravel 开箱即用,带有著名的 Carbon 类,用于操作日期和时间。但是,有一个鲜为人知的 gem 称为 CarbonPeriod,它对于创建 DateTime 数组非常有用。这些数组通常用于填充报表和日历。在本指南中,我们深入探讨了 CarbonPeriod 的七个实际应用。
示例 1:生成时间间隔 — 按小时或分钟
假设您的目标是捕获正常工作时间的数组,由特定的开始和结束时间分隔,例如:
- 9:00
- 10:00
- 11:00
- …
- 18:00
考虑这个示例 CarbonPeriod 片段:
use Carbon\Carbon;
use Carbon\CarbonPeriod;
$startPeriod = Carbon::parse('9:00');
$endPeriod = Carbon::parse('18:00');
$period = CarbonPeriod::create($startPeriod, '1 hour', $endPeriod);
$hours = [];
foreach ($period as $date) {
$hours[] = $date->format('H:i');
}
// Resulting Array
[
"09:00", "10:00", "11:00", "12:00",
"13:00", "14:00", "15:00", "16:00",
"17:00", "18:00"
]
可以观察到,CarbonPeriod 中的每个实体都是 Carbon 类的实例化,让您可以根据需要灵活地对其进行格式化。
如果你无法选择每小时间隔,则可以将间隔重新校准为更短的间隔,例如 45 分钟:
$period = CarbonPeriod::create($startPeriod, '45 minutes', $endPeriod);
// Resulting Array
[
"09:00", "09:45", "10:30", "11:15", "12:00",
"12:45", "13:30", "14:15", "15:00", "15:45",
"16:30", "17:15", "18:00"
]
您可能希望避开初始或结束条目。excludeStartDate 和 excludeEndDate 方法是为此量身定制的:
$period = CarbonPeriod::create($startPeriod, '45 minutes', $endPeriod)
->excludeStartDate()
->excludeEndDate();
// Resulting Array
[
"09:45", "10:30", "11:15", "12:00",
"12:45", "13:30", "14:15", "15:00",
"15:45", "16:30", "17:15"
]
想要更休闲的 12 小时格式吗?方法如下:
foreach ($period as $date) {
$hours[] = $date->format('h:i A');
}
// Resulting Array
[
"09:45 AM", "10:30 AM", "11:15 AM", "12:00 PM",
"12:45 PM", "01:30 PM", "02:15 PM", "03:00 PM",
"03:45 PM", "04:30 PM", "05:15 PM"
]
示例 2.按工作日划分的日期列表
假设您正在安排会议,并且您决定仅将会议安排在当月的星期一。这是使用 Laravel 的 Carbon 获取所有星期一的简单方法。
首先,包括 CarbonPeriod:
use Carbon\CarbonPeriod;
然后,获取月初和月末之间的日期。我们将筛选这些内容以仅包含星期一:
$period = CarbonPeriod::between(now()->startOfMonth(), now()->endOfMonth())
->filter(function ($date) {
return $date->isMonday();
});
$mondaysList = [];
foreach ($period as $date) {
$mondaysList[] = $date->format('M j, l, Y');
}
结果将为你提供该月所有星期一的数组,例如:
[
"Jul 3, Monday, 2023",
"Jul 10, Monday, 2023",
// ... and so on
]
很酷的是 Carbon 提供了许多其他功能,而不仅仅是周一。您可以检查日期是否在工作日、周末、星期二等。以下是 Carbon 文档中的一些便捷功能:
$dt->isWeekday();
$dt->isWeekend();
// ... and many more!
例 3.周列表
假设您正在制定一个时间表或计划器,并且希望查看周数的细分。具体来说,您需要列出从 2023 年 6 月 15 日到 2023 年 7 月 15 日的几周。对于每周,您想知道周数以及开始日期和结束日期。 以下是使用 Laravel 的 Carbon 轻松执行此操作的方法:
首先,您需要包含 CarbonPeriod:
use Carbon\CarbonPeriod;
$period = CarbonPeriod::create('2023-06-15', '1 week', '2023-07-15');
$weekList = [];
$dateFormat = 'F j, Y';
foreach ($period as $date) {
$weekList[] = [
'weekNumber' => $date->format('W'),
'startDate' => $date->startOfWeek()->format($dateFormat),
'endDate' => $date->endOfWeek()->format($dateFormat),
];
}
当你运行这个时,你会得到一个数组,里面有周数以及相应的开始和结束日期:
[ [ "weekNumber" => "24", "startDate" => "June 12, 2023", "endDate" => "June 18, 2023" ],
[ "weekNumber" => "25", "startDate" => "June 19, 2023", "endDate" => "June 25, 2023" ],
// ... and the list continues
]
有了这个,您可以轻松查看指定时间段内哪些日期属于哪一周!
示例 4:根据 Order Date 创建 Pickup Date 列表
让我们简化方案:
假设您在线下订单。订单发货后,您有一个时间范围从邮局取货。最初,您有 5 天的期限,从订单发货之日起计算。
以下是在 Laravel 中设置的方法:
使用 shipped_at date 属性定义 Order 模型:
class Order extends Model
{
protected $fillable = ['shipped_at'];
protected $casts = ['shipped_at' => 'date'];
}
如果创建的订单具有发货日期(例如“2023–07–13”),我们可以获取接下来的 5 天作为可能的取货日期:
use App\Models\Order;
$order = Order::create(['shipped_at' => '2023-07-13']);
$pickupDates = $order->shipped_at->toPeriod($order->shipped_at->copy()->addDays(5), '1 day')
->excludeEndDate();
$dates = [];
foreach ($pickupDates as $date) {
$dates[] = $date->format('Y-m-d');
}
/
但是,如果有新政策,并且您只想在工作日取货,并且总共有 7 个工作日可供选择,该怎么办?方法如下: 将期限延长至自发货日期起 1 个月。
将总日期限制为 7 个。
$order = Order::create(['shipped_at' => '2023-07-13']);
$pickupDates = $order->shipped_at->toPeriod($order->shipped_at->copy()->addMonth(), '1 day')
->setRecurrences(7)
->filter(function ($date) {
return $date->isWeekday();
});
$dates = [];
foreach ($pickupDates as $date) {
$dates[] = $date->format('Y-m-d');
}
// This will give seven weekdays starting from '2023-07-13'
示例 5:跟踪与期间重叠的员工休假
假设您管理一个团队,并且想知道未来 30 天内哪些员工将休假。这将有助于分配任务并确保工作流程顺畅。 以下是一些员工及其休假日期的示例数据:
Employee::insert([
['name' => 'Helmer Wilkinson', 'vacation_start' => '2023-01-01', 'vacation_end' => '2023-02-01'],
['name' => 'Kaya Lowe', 'vacation_start' => '2023-07-05', 'vacation_end' => '2023-07-14'],
['name' => 'Royal Yundt', 'vacation_start' => '2023-07-20', 'vacation_end' => '2023-08-01'],
['name' => 'Willow Stark', 'vacation_start' => '2023-09-01', 'vacation_end' => '2023-09-15'],
]);
现在,要找出这些员工中哪些员工的假期与从 “2023–07–13” 开始的接下来的 30 天重叠,我们可以执行以下操作: 定义我们感兴趣的 30 天期限。
检查员工的休假是否与此期间重叠。
$startOfCheck = Carbon::parse('2023-07-13');
$checkPeriod = CarbonPeriod::create($startOfCheck, $startOfCheck->copy()->addMonth());
$vacationingEmployees = [];
Employee::get()->each(function ($employee) use ($checkPeriod, &$vacationingEmployees) {
$employeeVacation = $employee->vacation_start->toPeriod($employee->vacation_end);
if ($employeeVacation->overlaps($checkPeriod)) {
$vacationingEmployees[] = $employee->name;
}
});
// The result will show employees on vacation during this period:
// ["Kaya Lowe", "Royal Yundt"]
示例 6:检查日期是否在给定时间段内
想知道哪些客户在某个月过生日吗?让我们使用一个易于理解的示例来分解它。
以下是我们的客户生日列表:
$customers = [
['name' => 'Helmer Wilkinson', 'birthday' => '1982-09-27'],
//... other customers ...
['name' => 'Nyasia Senger', 'birthday' => '1993-07-06'],
];
现在,如果您对哪些客户的生日(比如说 7 月)感到好奇,您可以执行以下操作:
定义月份的开始日期和结束日期。
浏览每个客户,看看他们的生日是否在该月。
use Carbon\Carbon;
use Carbon\CarbonPeriod;
// Setting the date range for July
$monthRange = CarbonPeriod::create(now()->startOfMonth(), now()->endOfMonth());
$celebrants = [];
foreach ($customers as $customer) {
$birthdayDate = Carbon::parse($customer['birthday']);
// Adjusting the birthday year to the current year
$thisYearBirthday = $birthdayDate->copy()->year(now()->format('Y'));
// If the birthday is in July
if ($monthRange->contains($thisYearBirthday)) {
$celebrants[] = sprintf(
'%s celebrates their %dth birthday this month.',
$customer['name'],
$birthdayDate->diffInYears($thisYearBirthday)
);
}
}
// The result for July will show:
// ["Willow Stark celebrates their 35th birthday this month.", "Nyasia Senger celebrates their 30th birthday this month."]
示例 7:查找一天的空预约空档
假设您正在为特定日期的约会选择时间。为了帮助您选择,我们可以根据之前预订的时段显示哪些时间仍然开放。这是一个简单的细分: 我们有 2023 年 7 月 13 日的预订时段:
- 10:00 AM 晚上 10:00
- 2:00 PM 下午 2:00
- 3:00 PM 下午 3:00
我们从上午 9:00 开始接受预约,并在当天下午 4:00 结束。因此,要找出可用的时段,我们可以将一整天的时间与预订的时间进行比较。
这是执行此操作的代码:
$bookedSlots = [
'2023-07-13 10:00',
'2023-07-13 14:00',
'2023-07-13 15:00',
];
$startHour = Carbon::parse('2023-07-13 9:00');
$endHour = Carbon::parse('2023-07-13 16:00');
$allSlots = CarbonPeriod::create($startHour, '1 hour', $endHour)
->filter(function ($time) use ($bookedSlots) {
return ! in_array($time->format('Y-m-d H:i'), $bookedSlots);
});
$freeSlots = [];
foreach ($allSlots as $slot) {
$freeSlots[] = $slot->format('Y-m-d H:i');
}
基于此,2023 年 7 月 13 日的预约免费时间为:
- 9:00 AM 上午 9:00
- 11:00 AM 上午 11:00
- 12:00 PM 中午 12:00
- 1:00 PM 下午 1:00
- 4:00 PM 下午 4:00