3 回答
TA贡献1848条经验 获得超6个赞
我发现使用 DAYOFYEAR 方法的原始查询非常优雅,因为它消除了不同出生年份的所有问题。然而,它不会很好地处理闰年。
我发现 BETWEEN 和 DATE_FORMAT 的组合会产生正确的结果。它确实需要检查来处理多年来的边缘。
以下是如何在模型范围内实现此功能的示例:
public function scopeBirthDayBetween ($query, Carbon $from, Carbon $till)
{
$fromMonthDay = $from->format('m-d');
$tillMonthDay = $till->format('m-d');
if ($fromMonthDay <= $tillMonthDay) {
//normal search within the one year
$query->whereRaw("DATE_FORMAT(birthdate, '%m-%d') BETWEEN '{$fromMonthDay}' AND '{$tillMonthDay}'");
} else {
//we are overlapping a year, search at end and beginning of year
$query->where(function ($query) use ($fromMonthDay, $tillMonthDay) {
$query->whereRaw("DATE_FORMAT(birthdate, '%m-%d') BETWEEN '{$fromMonthDay}' AND '12-31'")
->orWhereRaw("DATE_FORMAT(birthdate, '%m-%d') BETWEEN '01-01' AND '{$tillMonthDay}'");
});
}
}
用法:
$users = User::birthDayBetween(Carbon::now(), Carbon::now()->addWeek())->get()
要在出生日期而不是出生日期添加排序,更多原始查询和 DATE_FORMAT 可以提供帮助。
$users = User::query()
->birthDayBetween($from, $till)
->orderByRaw("DATE_FORMAT(birth_date,'%m%d')")
->orderByRaw("DATE_FORMAT(birth_date,'%y') desc")
->orderBy('first_name')
->get();
注意:查看年份边缘时,订购将关闭,因为将首先订购明年年初生日的用户。我选择在前端解决这个问题。
TA贡献1784条经验 获得超9个赞
您的模型有一个date-of-birth字段,您将它与当前日期(可能是出生日期之后的许多年)进行比较。
解决方案:
为了可读性和处理年结转问题,您应该:
使用 Carbon 计算日期和日期
查找用户的下一个/即将到来的生日
请记住,Ymd 格式通常意味着时间为 00:00:00。
$now = Carbon::now();
$customers = Customer::all();
// find next birthday for each customer
foreach ($customers as $customer) {
$curyear_bd = Carbon::createFromFormat('Y-m-d', $customer->date_of_birth)->setYear($now->year);
$now > $curyear_bd->endOfDay() ? $next_bd = $curyear_bd->addYear(1) : $next_bd = $curyear_bd;
if ($now <= $next_bd->startOfDay() && $next_bd <= Carbon::now()->addDay(7)->endOfDay())
{
print "customer $customer->name has birthday coming up\n";
}
}
MySQL解决方案
您可以像这样使用 SQL 查询:
select * from customers where
if (
CURDATE() >= date_add(date_of_birth, interval TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) year),
date_add(date_of_birth, interval (TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE())+1) year),
date_add(date_of_birth, interval TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) year)
)
between
curdate()
and
date_add(curdate(), interval 7 day);
但我会警惕时区(服务器、客户端等)。这可能需要它自己的SO问题......
- 3 回答
- 0 关注
- 339 浏览
添加回答
举报