[cherry-pick](branch2.1) fix week/yearweek function get wrong result (#36538)

## Proposed changes
cherry-pick from master #36000 #36159
This commit is contained in:
zhangstar333
2024-06-20 15:48:19 +08:00
committed by GitHub
parent 88e02c836d
commit 1a242b8ae0
3 changed files with 93 additions and 2 deletions

View File

@ -687,7 +687,10 @@ public class DateTimeExtractAndTransform {
return week(date.toJavaDateType(), mode.getIntValue());
}
private static Expression week(LocalDateTime localDateTime, int mode) {
/**
* the impl of function week(date/datetime, mode)
*/
public static Expression week(LocalDateTime localDateTime, int mode) {
switch (mode) {
case 0: {
return new TinyIntLiteral(
@ -697,6 +700,13 @@ public class DateTimeExtractAndTransform {
return new TinyIntLiteral((byte) localDateTime.get(WeekFields.ISO.weekOfYear()));
}
case 2: {
// https://dev.mysql.com/doc/refman/8.4/en/date-and-time-functions.html#function_week
// mode 2 is start with a Sunday day as first week in this year.
// and special case for 0000-01-01, as it's SATURDAY, calculate result of 52 is
// last year, so it's meaningless.
if (checkIsSpecificDate(localDateTime)) {
return new TinyIntLiteral((byte) 1);
}
return new TinyIntLiteral(
(byte) localDateTime.get(WeekFields.of(DayOfWeek.SUNDAY, 7).weekOfWeekBasedYear()));
}
@ -757,9 +767,15 @@ public class DateTimeExtractAndTransform {
return yearWeek(dateTime.toJavaDateType(), 0);
}
private static Expression yearWeek(LocalDateTime localDateTime, int mode) {
/**
* the impl of function yearWeek(date/datetime, mode)
*/
public static Expression yearWeek(LocalDateTime localDateTime, int mode) {
switch (mode) {
case 0: {
if (checkIsSpecificDate(localDateTime)) {
return new IntegerLiteral(1);
}
return new IntegerLiteral(
localDateTime.get(WeekFields.of(DayOfWeek.SUNDAY, 7).weekBasedYear()) * 100
+ localDateTime.get(
@ -770,6 +786,9 @@ public class DateTimeExtractAndTransform {
+ localDateTime.get(WeekFields.ISO.weekOfWeekBasedYear()));
}
case 2: {
if (checkIsSpecificDate(localDateTime)) {
return new IntegerLiteral(1);
}
return new IntegerLiteral(
localDateTime.get(WeekFields.of(DayOfWeek.SUNDAY, 7).weekBasedYear()) * 100
+ localDateTime.get(
@ -810,6 +829,13 @@ public class DateTimeExtractAndTransform {
}
}
/**
* 0000-01-01 is specific date, sometime need handle it alone.
*/
private static boolean checkIsSpecificDate(LocalDateTime localDateTime) {
return localDateTime.getYear() == 0 && localDateTime.getMonthValue() == 1 && localDateTime.getDayOfMonth() == 1;
}
@ExecFunction(name = "weekofyear", argTypes = {"DATETIMEV2"}, returnType = "TINYINT")
public static Expression weekOfYear(DateTimeV2Literal dateTime) {
return new TinyIntLiteral((byte) dateTime.toJavaDateType().get(WeekFields.ISO.weekOfWeekBasedYear()));