问题描述
我正在创建一个应用,用户可以创建每月活动(就像Google / Outlook一样),因此,如果用户选择了31st date of any month
,下个月拥有30 days
,那么所有下一个日期都将更改为{{ 1}}。
与30th
相同,可以说用户选择的30th
比2月之后的所有下一个日期都更改为30th of December
。
因此,如果下个月的日期少于用户选择的日期,则将日期更改为该日期。
示例:
开始日期:28th
结束日期:2020-10-31
2021-11-30
它给出这样的输出
$diffInMonths = $startDate->diffInMonths($endDate);
for ($i = 0; $i <= $diffInMonths; $i++) {
$newStartDate = $i == 0 ? $startDate : $startDate->addMonthWithNoOverflow();
print('<pre>' . print_r($newStartDate->toDateString(),true) . '</pre>');
}
如果该月的天数少于用户选择的日期,我需要跳过该月。在上述示例中,正确的输出应为
2020-10-31
2020-11-30
2020-12-30
2021-01-30
2021-02-28
2021-03-28
2021-04-28
2021-05-28
2021-06-28
2021-07-28
2021-08-28
2021-09-28
2021-10-28
过去2-3天一直在为此苦苦挣扎,因此,任何一种帮助或指导都将使我的生活变得美好:)
解决方法
这可能是一种愚蠢的方式,但是由于时间有限,这里是解决方法
$dateRange = Carbon::parse($callPlanner->start_date)->toPeriod($callPlanner->end_date,1,'month');
$startDate = Carbon::parse($callPlanner->start_date);
foreach ($dateRange as $date) {
// compare the event date with end of month date
if ($startDate->day <= $date->endOfMonth()->day) {
//create new date with this month's year,month and event start date
$newDate = Carbon::createFromDate($date->endOfMonth()->year,$date->endOfMonth()->month,$startDate->day);
echo $newDate->toDateString(). "\n";
}
}
,
addMonths()
添加一个月到日期。没有溢出,它将在下个月(假设2020-02-29
)结束。在下一步中,它会将另外一个月添加到2020-02-29
中,因此下一个日期是2020-03-29
,因为它仅添加了一个月。您不会调用它来更新日期。因此您的解决方案将使用lastOfMonth()
$startDate = Carbon::parse('2020-01-31');
$endDate = Carbon::parse('2020-12-31');
$diffInMonths = $startDate->diffInMonths($endDate);
for ($i = 0; $i <= $diffInMonths; $i++) {
$newStartDate = $i == 0 ? $startDate : $startDate->addMonthWithNoOverflow()->lastOfMonth();
print('<pre>' . print_r($newStartDate->toDateString(),true) . '</pre>');
}
这将给您类似的日期
2020-01-31
2020-02-29
2020-03-31
2020-04-30
2020-05-31
2020-06-30
2020-07-31
2020-08-31
2020-09-30
2020-10-31
2020-11-30
2020-12-31
使用addMonth不能跳过少几天的月份。您必须在某些情况下手动检查它。喜欢
$startDate = Carbon::parse('2020-10-31');
$endDate = Carbon::parse('2021-11-30');
$highestDate = $startDate->format('d');
$diffInMonths = $startDate->diffInMonths($endDate);
for ($i = 0; $i <= $diffInMonths; $i++) {
$newStartDate = $i == 0 ? $startDate : $startDate->addMonthWithNoOverflow()->lastOfMonth();
if ($newStartDate->format('d') >= $highestDate) {
print('<pre>' . print_r($newStartDate->toDateString(),true) . '</pre>');
}
}
输出为
2020-10-31
2020-12-31
2021-01-31
2021-03-31
2021-05-31
2021-07-31
2021-08-31
2021-10-31
,
在这种情况下(类似于每月订阅问题),最好总是从第一天开始而不是将附加内容链接起来:
$diffInMonths = $startDate->diffInMonths($endDate);
for ($i = 0; $i <= $diffInMonths; $i++) {
$newStartDate = $startDate->copy()->addMonthsWithNoOverflow($i + 1);
print('<pre>' . print_r($newStartDate->toDateString(),true) . '</pre>');
}
这样,您将获得该月的最后一天是不可用的日期,但不会更改下一次迭代。
请注意,如果您使用->copy()
,则不需要CarbonImmutable
。