设置下个月的付款日期(使用 PHP Carbon)
Set next month payment date (with PHP Carbon)
我需要确定下个月的付款日期。所以我选择最后的截止日期
并增加一个月。我该怎么做?
我的示例是:最后一次付款是 1 月 31 日,我正在做
Carbon::create(2018, 1, 31, 0, 0, 0)->addMonthsNoOverflow(1)
它起作用了,它给了 2018-02-28
但之后下一次付款将再次在 28 日到期。所以我需要在添加一个月后设置一个日期。
Carbon::create(2018, 2, 28, 0, 0, 0)->addMonthsNoOverflow(1)->day(31)
它给了我 2018-03-31
这很好但是如果我在第一个例子中使用这个公式
Carbon::create(2018, 1, 31, 0, 0, 0)->addMonthsNoOverflow(1)->day(31)
它让我溢出 2018-03-03
。这是我的问题。我应该怎么办?有没有类似 ->setDayNoOverflow(31)
的东西?
Carbon中好像没有这个功能,为什么不自己做呢?
public function setDaysNoOverflow($value)
{
$year = $this->year;
$month = $this->month;
$this->day((int)$value);
if ($month !== $this->month) {
$this->year = $year;
$this->month = $month;
$this->modify('last day of this month');
}
return $this;
}
只需将其添加到 Carbon/Carbon.php
即可。
它基于 addMonthsNoOverflow 函数源。
警告:未经测试,仅供参考。
您不应该使用最后一个付款日期,而是保留第一个日期并从第一个而不是前一个计算所有其他日期:
Carbon::create(2018, 1, 31, 0, 0, 0)
Carbon::create(2018, 1, 31, 0, 0, 0)->addMonthsNoOverflow(1)
Carbon::create(2018, 1, 31, 0, 0, 0)->addMonthsNoOverflow(2)
Carbon::create(2018, 1, 31, 0, 0, 0)->addMonthsNoOverflow(3)
假设您没有这些数据,您仍然可以:
$day = 31;
$date = Carbon::create(2018, 1, 28, 0, 0, 0);
$date->addMonthsNoOverflow(1);
$date->day(min($day, $date->daysInMonth));
您可以使用 Carbon 库中的 addMonth() 函数,如下所示
Carbon::create(2018, 1, 31, 0, 0, 0)->addMonth();
我认为这里的实际问题是关于业务逻辑或数据库模式,而不是日期操作。
尽管我不确定您的订阅模式是什么,但您似乎想要跟踪两条不同的信息:
- 支付服务费用的截止日期,
- 付款到期的日期。
通过尝试将两者存储在一个字段中,您可能会丢失一些信息,就像 January/February/March 转换的情况一样。通过使用单独的字段,您可以阻止它并在每个月建立付款到期日,例如 KyleK 所建议的:
$lastPayment->addMonthsNoOverflow(1)->day(
min($paymentDue->day, $lastPayment->daysInMonth)
);
在我看来,这样做有点复杂,可以通过以下方式大大简化:
- 使用工作月(30 天)而不是日历月,
- 放弃原来的付款日,只在最后一次付款后增加一个月。
不过据我所知,这可能不由您决定。
您可以将其用作循环
// from month
$min = 3;
// to mont
$max = 9;
// all dates
$paymentDates = [];
$date2 = \Carbon\Carbon::now();
// next day (or today)
$day = $date2->addDay(1)->format('d');
$currentMonth = $date2->format('m');
$year = $date2->format('Y');;
$date = \Carbon\Carbon::now();
$nextMonth = $currentMonth;
for($i = $min; $i <= $max; $i++) {
$date = \Carbon\Carbon::create($year, $currentMonth, $day)->addMonthsNoOverflow($nextMonth)->format('d/m/Y');
// add to array
array_push($paymentDates, $date);
// next month
$nextMonth++;
}
我需要确定下个月的付款日期。所以我选择最后的截止日期 并增加一个月。我该怎么做?
我的示例是:最后一次付款是 1 月 31 日,我正在做
Carbon::create(2018, 1, 31, 0, 0, 0)->addMonthsNoOverflow(1)
它起作用了,它给了 2018-02-28
但之后下一次付款将再次在 28 日到期。所以我需要在添加一个月后设置一个日期。
Carbon::create(2018, 2, 28, 0, 0, 0)->addMonthsNoOverflow(1)->day(31)
它给了我 2018-03-31
这很好但是如果我在第一个例子中使用这个公式
Carbon::create(2018, 1, 31, 0, 0, 0)->addMonthsNoOverflow(1)->day(31)
它让我溢出 2018-03-03
。这是我的问题。我应该怎么办?有没有类似 ->setDayNoOverflow(31)
的东西?
Carbon中好像没有这个功能,为什么不自己做呢?
public function setDaysNoOverflow($value)
{
$year = $this->year;
$month = $this->month;
$this->day((int)$value);
if ($month !== $this->month) {
$this->year = $year;
$this->month = $month;
$this->modify('last day of this month');
}
return $this;
}
只需将其添加到 Carbon/Carbon.php
即可。
它基于 addMonthsNoOverflow 函数源。
警告:未经测试,仅供参考。
您不应该使用最后一个付款日期,而是保留第一个日期并从第一个而不是前一个计算所有其他日期:
Carbon::create(2018, 1, 31, 0, 0, 0)
Carbon::create(2018, 1, 31, 0, 0, 0)->addMonthsNoOverflow(1)
Carbon::create(2018, 1, 31, 0, 0, 0)->addMonthsNoOverflow(2)
Carbon::create(2018, 1, 31, 0, 0, 0)->addMonthsNoOverflow(3)
假设您没有这些数据,您仍然可以:
$day = 31;
$date = Carbon::create(2018, 1, 28, 0, 0, 0);
$date->addMonthsNoOverflow(1);
$date->day(min($day, $date->daysInMonth));
您可以使用 Carbon 库中的 addMonth() 函数,如下所示
Carbon::create(2018, 1, 31, 0, 0, 0)->addMonth();
我认为这里的实际问题是关于业务逻辑或数据库模式,而不是日期操作。
尽管我不确定您的订阅模式是什么,但您似乎想要跟踪两条不同的信息:
- 支付服务费用的截止日期,
- 付款到期的日期。
通过尝试将两者存储在一个字段中,您可能会丢失一些信息,就像 January/February/March 转换的情况一样。通过使用单独的字段,您可以阻止它并在每个月建立付款到期日,例如 KyleK 所建议的:
$lastPayment->addMonthsNoOverflow(1)->day(
min($paymentDue->day, $lastPayment->daysInMonth)
);
在我看来,这样做有点复杂,可以通过以下方式大大简化:
- 使用工作月(30 天)而不是日历月,
- 放弃原来的付款日,只在最后一次付款后增加一个月。
不过据我所知,这可能不由您决定。
您可以将其用作循环
// from month
$min = 3;
// to mont
$max = 9;
// all dates
$paymentDates = [];
$date2 = \Carbon\Carbon::now();
// next day (or today)
$day = $date2->addDay(1)->format('d');
$currentMonth = $date2->format('m');
$year = $date2->format('Y');;
$date = \Carbon\Carbon::now();
$nextMonth = $currentMonth;
for($i = $min; $i <= $max; $i++) {
$date = \Carbon\Carbon::create($year, $currentMonth, $day)->addMonthsNoOverflow($nextMonth)->format('d/m/Y');
// add to array
array_push($paymentDates, $date);
// next month
$nextMonth++;
}