如何使用 Carbon 确定日期过去一个月

How to determine a month has past to the date using Carbon

一个人在平台上每个月都会获得一个积分。因此,如果他在 7 月 3 日加入,则在 8 月 3 日他会获得额外的积分。

开始日期在数据库中设置为 date 字段。

考虑到这一点时,如果我只是在日常 cron 中做这样的事情,似乎有不同的情况我可能会错过添加这一点:

$startDate = new Carbon($startDateFromDb);
$today = new Carbon( date("Y-m-d"));

if ($startDate->day === $today->day) {
    //Add point!
}

例如,此人从 11 月 30 日开始。所以在 12 月 30 日他应该得到 +1 分(现在总共有 1 分)。 1 月 30 日他应该得到 +1 分(现在总共有 2 分)。

问题会出现在 2 月,因为 2 月没有 30 天,所以 $startDate->day === $today->day 这个月永远不会成立。

如果一个人在 31 日开始工作,这也会发生在任何有 30 天的月份。

Carbon 是否有一些方法可以让我验证这一点,或者我应该用每月 month/days 和我自己的逻辑做一个长 if/else?

谢谢!

根据您正在寻找的确切行为以及您可以在数据库中存储的内容,有几个选项:

选项 1: 如果唯一可以调整一个人的分数的是任期,那么直接计算分数可能是最简单的。这可以使用 Carbon 的 diffInMonths 非常简单地完成。这看起来像这样:

$startDate = new Carbon($startDateFromDb);
$today = Carbon::today();

$points = $today->diffInMonths($startDate);

选项 2: 如果您不能使用即时计算,那么最直接的方法是除了总分之外还存储任期分。这允许您检查当前任期积分和授予的任期积分之间是否存在差异:

$startDate = new Carbon($startDateFromDb);
$today = Carbon::today();

$calcTenurePoints = $today->diffInMonths($startDate);
if ($calcTenurePoints < $awardedTenurePoints) {
    $points += $calcTenurePoints - $awardedTenurePoints;
    $awardedTenurePoints = calcTenurePoints
} 

您还可以通过仅存储非任期积分并动态计算任期积分来组合这两个选项。这样做的缺点是你不能很容易地直接从数据库中获取积分。

我终于手动完成了:

public static function shouldAddVacationDay(User $user, Carbon $today) : bool {

    $shouldAddVacation = false;

    if ($user->startdate) {

        $start = new Carbon($user->startdate);

        // Normal day
        if ($today->day === $start->day) {
            $shouldAddVacation = true;
        }

        // Add a vacation day on March 1 for users that started Jan 29,30,31.
        if ($today->month === VacationlogController::$MAR && $today->day === 1) {
            if ($today->isLeapYear() && ($start->day === 30 || $start->day === 31)) {
                $shouldAddVacation = true;
            } elseif ($start->day === 29 || $start->day === 30 || $start->day === 31) {
                $shouldAddVacation = true;
            }
        }

        // If he started on the 31st of a month where the following month has less than 31 days, add a
        // vacation day the following month on the 1st.
        if ($start->day === 31) {

            if ($today->month === VacationlogController::$MAY && $today->day === 1) {
                $shouldAddVacation = true;
            }

            if ($today->month === VacationlogController::$JUL && $today->day === 1) {
                $shouldAddVacation = true;
            }

            if ($today->month === VacationlogController::$OCT && $today->day === 1) {
                $shouldAddVacation = true;
            }

            if ($today->month === VacationlogController::$DEC && $today->day === 1) {
                $shouldAddVacation = true;
            }
        }
    }

    return $shouldAddVacation;
}