From 6104fc65639e78cf69f5a5acbf465902cbda080f Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Tue, 30 Jul 2024 15:02:27 +0800 Subject: [PATCH 01/26] support daysSinceEpochFromWeekOfMonthDate --- velox/type/TimestampConversion.cpp | 40 ++++++++++++++++++++++++++++++ velox/type/TimestampConversion.h | 9 +++++++ 2 files changed, 49 insertions(+) diff --git a/velox/type/TimestampConversion.cpp b/velox/type/TimestampConversion.cpp index e5c5e3ce5f3d..43dcc3fa84d6 100644 --- a/velox/type/TimestampConversion.cpp +++ b/velox/type/TimestampConversion.cpp @@ -144,6 +144,26 @@ bool isValidWeekDate(int32_t weekYear, int32_t weekOfYear, int32_t dayOfWeek) { return true; } +bool isValidWeekOfMonthDate( + int32_t year, + int32_t month, + int32_t weekOfMonth, + int32_t dayOfWeek) { + if (dayOfWeek < 1 || dayOfWeek > 7) { + return false; + } + if (weekOfMonth < 1 || weekOfMonth > 5) { + return false; + } + if (month < 1 || month > 12) { + return false; + } + if (year < kMinYear || year > kMaxYear) { + return false; + } + return true; +} + inline bool validDate(int64_t daysSinceEpoch) { return daysSinceEpoch >= std::numeric_limits::min() && daysSinceEpoch <= std::numeric_limits::max(); @@ -593,6 +613,26 @@ Status daysSinceEpochFromWeekDate( return Status::OK(); } +Status daysSinceEpochFromWeekOfMonthDate( + int32_t year, + int32_t month, + int32_t weekOfMonth, + int32_t dayOfWeek, + int64_t& out) { + if (!isValidWeekOfMonthDate(year, month, weekOfMonth, dayOfWeek)) { + return Status::UserError( + "Date out of range: {}-{}-{}-{}", year, month, weekOfMonth, dayOfWeek); + } + int64_t daysSinceEpochOfFirstDayOfMonth; + VELOX_RETURN_NOT_OK( + daysSinceEpochFromDate(year, month, 1, daysSinceEpochOfFirstDayOfMonth)); + int32_t firstDayOfWeek = + extractISODayOfTheWeek(daysSinceEpochOfFirstDayOfMonth); + out = daysSinceEpochOfFirstDayOfMonth - (firstDayOfWeek - 1) + + 7 * (weekOfMonth - 1) + dayOfWeek - 1; + return Status::OK(); +} + Status daysSinceEpochFromDayOfYear(int32_t year, int32_t dayOfYear, int64_t& out) { if (!isValidDayOfYear(year, dayOfYear)) { diff --git a/velox/type/TimestampConversion.h b/velox/type/TimestampConversion.h index 5f5e04cfcfe3..491645809a71 100644 --- a/velox/type/TimestampConversion.h +++ b/velox/type/TimestampConversion.h @@ -107,6 +107,15 @@ Status daysSinceEpochFromWeekDate( int32_t dayOfWeek, int64_t& out); +/// Computes the (signed) number of days since unix epoch (1970-01-01). +/// Returns UserError status if the date is invalid. +Status daysSinceEpochFromWeekOfMonthDate( + int32_t year, + int32_t month, + int32_t weekOfMonth, + int32_t dayOfWeek, + int64_t& out); + /// Computes the (signed) number of days since unix epoch (1970-01-01). /// Returns UserError status if the date is invalid. Status From 1d4667bcb8c60604c7e4d2f19cd62d94c3077ef4 Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Thu, 25 Jul 2024 16:49:37 +0800 Subject: [PATCH 02/26] add unit tests --- velox/type/tests/TimestampConversionTest.cpp | 29 ++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index 2ea96844790e..3a1468939bb0 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -104,6 +104,35 @@ TEST(DateTimeUtilTest, fromDateInvalid) { 1970, 6, 31, "Date out of range: 1970-6-31")); } +TEST(DateTimeUtilTest, fromWeekOfMonthDate) { + auto testDaysSinceEpochFromWeekOfMonthDate = + [](int32_t year, int32_t month, int32_t weekOfMonth, int32_t dayOfWeek) { + int64_t daysSinceEpoch; + auto status = util::daysSinceEpochFromWeekOfMonthDate( + year, month, weekOfMonth, dayOfWeek, daysSinceEpoch); + EXPECT_TRUE(status.ok()); + return daysSinceEpoch; + }; + EXPECT_EQ(4, testDaysSinceEpochFromWeekOfMonthDate(1970, 1, 2, 1)); + EXPECT_EQ(361, testDaysSinceEpochFromWeekOfMonthDate(1971, 1, 1, 1)); + EXPECT_EQ(396, testDaysSinceEpochFromWeekOfMonthDate(1971, 2, 1, 1)); + + EXPECT_EQ(10952, testDaysSinceEpochFromWeekOfMonthDate(2000, 1, 1, 1)); + EXPECT_EQ(19905, testDaysSinceEpochFromWeekOfMonthDate(2024, 7, 1, 1)); + + // Before unix epoch. + EXPECT_EQ(-3, testDaysSinceEpochFromWeekOfMonthDate(1970, 1, 1, 1)); + EXPECT_EQ(-2, testDaysSinceEpochFromWeekOfMonthDate(1970, 1, 1, 2)); + EXPECT_EQ(-31, testDaysSinceEpochFromWeekOfMonthDate(1969, 12, 1, 1)); + EXPECT_EQ(-367, testDaysSinceEpochFromWeekOfMonthDate(1969, 1, 1, 1)); + EXPECT_EQ(-724, testDaysSinceEpochFromWeekOfMonthDate(1968, 1, 2, 1)); + EXPECT_EQ(-719533, testDaysSinceEpochFromWeekOfMonthDate(0, 1, 1, 1)); + + // Negative year - BC. + EXPECT_EQ(-719561, testDaysSinceEpochFromWeekOfMonthDate(-1, 12, 1, 1)); + EXPECT_EQ(-719897, testDaysSinceEpochFromWeekOfMonthDate(-1, 1, 1, 1)); +} + TEST(DateTimeUtilTest, fromDateString) { for (ParseMode mode : {ParseMode::kPrestoCast, ParseMode::kSparkCast}) { EXPECT_EQ(0, parseDate("1970-01-01", mode)); From e4b2c78ee8d77ccd477851b344dd233859b64cc2 Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Tue, 30 Jul 2024 15:13:01 +0800 Subject: [PATCH 03/26] reformat --- velox/type/TimestampConversion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/velox/type/TimestampConversion.cpp b/velox/type/TimestampConversion.cpp index 43dcc3fa84d6..33cf73a11694 100644 --- a/velox/type/TimestampConversion.cpp +++ b/velox/type/TimestampConversion.cpp @@ -629,7 +629,7 @@ Status daysSinceEpochFromWeekOfMonthDate( int32_t firstDayOfWeek = extractISODayOfTheWeek(daysSinceEpochOfFirstDayOfMonth); out = daysSinceEpochOfFirstDayOfMonth - (firstDayOfWeek - 1) + - 7 * (weekOfMonth - 1) + dayOfWeek - 1; + 7 * (weekOfMonth - 1) + dayOfWeek - 1; return Status::OK(); } From b4504f868b1c9dfc72302e82429f4317522b2467 Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Tue, 30 Jul 2024 16:40:00 +0800 Subject: [PATCH 04/26] add argument doc --- velox/type/TimestampConversion.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/velox/type/TimestampConversion.h b/velox/type/TimestampConversion.h index 491645809a71..0a5be82201c9 100644 --- a/velox/type/TimestampConversion.h +++ b/velox/type/TimestampConversion.h @@ -109,6 +109,12 @@ Status daysSinceEpochFromWeekDate( /// Computes the (signed) number of days since unix epoch (1970-01-01). /// Returns UserError status if the date is invalid. +/// Runs the aggregation fuzzer. +/// @param year Year, can be negative e.g: 1996, -2000 +/// @param month Month of year, e.g: 7 +/// @param weekOfMonth Week of month, 1 ~ 5 e.g: 2 +/// @param dayOfWeek Day of week, 1 ~ 7 e.g: 4 +/// @param out Reference days since epoch Status daysSinceEpochFromWeekOfMonthDate( int32_t year, int32_t month, From e9be74051cbd2ebfbae56ba6260d4b96dfd90bda Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Tue, 30 Jul 2024 16:40:18 +0800 Subject: [PATCH 05/26] add argument doc --- velox/type/TimestampConversion.h | 1 - 1 file changed, 1 deletion(-) diff --git a/velox/type/TimestampConversion.h b/velox/type/TimestampConversion.h index 0a5be82201c9..c34ad65b045b 100644 --- a/velox/type/TimestampConversion.h +++ b/velox/type/TimestampConversion.h @@ -109,7 +109,6 @@ Status daysSinceEpochFromWeekDate( /// Computes the (signed) number of days since unix epoch (1970-01-01). /// Returns UserError status if the date is invalid. -/// Runs the aggregation fuzzer. /// @param year Year, can be negative e.g: 1996, -2000 /// @param month Month of year, e.g: 7 /// @param weekOfMonth Week of month, 1 ~ 5 e.g: 2 From a4ff46ce34ed1aebb849df55edff27fac26e2d0e Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Tue, 30 Jul 2024 16:42:44 +0800 Subject: [PATCH 06/26] update argument doc --- velox/type/TimestampConversion.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/velox/type/TimestampConversion.h b/velox/type/TimestampConversion.h index c34ad65b045b..a61a8d70e03f 100644 --- a/velox/type/TimestampConversion.h +++ b/velox/type/TimestampConversion.h @@ -113,7 +113,7 @@ Status daysSinceEpochFromWeekDate( /// @param month Month of year, e.g: 7 /// @param weekOfMonth Week of month, 1 ~ 5 e.g: 2 /// @param dayOfWeek Day of week, 1 ~ 7 e.g: 4 -/// @param out Reference days since epoch +/// @param out Reference for days since epoch Status daysSinceEpochFromWeekOfMonthDate( int32_t year, int32_t month, From 555e1d9782aec5b6e1c4c22733459922e2c16ad6 Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Tue, 30 Jul 2024 16:54:00 +0800 Subject: [PATCH 07/26] refactor with velox::Expected --- velox/type/TimestampConversion.cpp | 19 ++++++++++--------- velox/type/TimestampConversion.h | 6 ++---- velox/type/tests/TimestampConversionTest.cpp | 8 ++++---- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/velox/type/TimestampConversion.cpp b/velox/type/TimestampConversion.cpp index 33cf73a11694..fe73c1efc3c6 100644 --- a/velox/type/TimestampConversion.cpp +++ b/velox/type/TimestampConversion.cpp @@ -613,24 +613,25 @@ Status daysSinceEpochFromWeekDate( return Status::OK(); } -Status daysSinceEpochFromWeekOfMonthDate( +Expected daysSinceEpochFromWeekOfMonthDate( int32_t year, int32_t month, int32_t weekOfMonth, - int32_t dayOfWeek, - int64_t& out) { + int32_t dayOfWeek) { if (!isValidWeekOfMonthDate(year, month, weekOfMonth, dayOfWeek)) { - return Status::UserError( - "Date out of range: {}-{}-{}-{}", year, month, weekOfMonth, dayOfWeek); + return folly::makeUnexpected(Status::UserError( + "Date out of range: {}-{}-{}-{}", year, month, weekOfMonth, dayOfWeek)); } int64_t daysSinceEpochOfFirstDayOfMonth; - VELOX_RETURN_NOT_OK( - daysSinceEpochFromDate(year, month, 1, daysSinceEpochOfFirstDayOfMonth)); + Status status = daysSinceEpochFromDate(year, month, 1, daysSinceEpochOfFirstDayOfMonth); + if (status.ok() == false) { + return folly::makeUnexpected(status); + } int32_t firstDayOfWeek = extractISODayOfTheWeek(daysSinceEpochOfFirstDayOfMonth); - out = daysSinceEpochOfFirstDayOfMonth - (firstDayOfWeek - 1) + + int64_t result = daysSinceEpochOfFirstDayOfMonth - (firstDayOfWeek - 1) + 7 * (weekOfMonth - 1) + dayOfWeek - 1; - return Status::OK(); + return result; } Status diff --git a/velox/type/TimestampConversion.h b/velox/type/TimestampConversion.h index a61a8d70e03f..d0f5f972f859 100644 --- a/velox/type/TimestampConversion.h +++ b/velox/type/TimestampConversion.h @@ -113,13 +113,11 @@ Status daysSinceEpochFromWeekDate( /// @param month Month of year, e.g: 7 /// @param weekOfMonth Week of month, 1 ~ 5 e.g: 2 /// @param dayOfWeek Day of week, 1 ~ 7 e.g: 4 -/// @param out Reference for days since epoch -Status daysSinceEpochFromWeekOfMonthDate( +Expected daysSinceEpochFromWeekOfMonthDate( int32_t year, int32_t month, int32_t weekOfMonth, - int32_t dayOfWeek, - int64_t& out); + int32_t dayOfWeek); /// Computes the (signed) number of days since unix epoch (1970-01-01). /// Returns UserError status if the date is invalid. diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index 3a1468939bb0..d113f373aac8 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -108,10 +108,10 @@ TEST(DateTimeUtilTest, fromWeekOfMonthDate) { auto testDaysSinceEpochFromWeekOfMonthDate = [](int32_t year, int32_t month, int32_t weekOfMonth, int32_t dayOfWeek) { int64_t daysSinceEpoch; - auto status = util::daysSinceEpochFromWeekOfMonthDate( - year, month, weekOfMonth, dayOfWeek, daysSinceEpoch); - EXPECT_TRUE(status.ok()); - return daysSinceEpoch; + auto expected = util::daysSinceEpochFromWeekOfMonthDate( + year, month, weekOfMonth, dayOfWeek); + EXPECT_TRUE(!expected.hasError()); + return expected.value(); }; EXPECT_EQ(4, testDaysSinceEpochFromWeekOfMonthDate(1970, 1, 2, 1)); EXPECT_EQ(361, testDaysSinceEpochFromWeekOfMonthDate(1971, 1, 1, 1)); From 83301abf1f6a104fd6039068c11c8c3277d0009d Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Tue, 30 Jul 2024 16:56:32 +0800 Subject: [PATCH 08/26] reformat --- velox/type/TimestampConversion.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/velox/type/TimestampConversion.cpp b/velox/type/TimestampConversion.cpp index fe73c1efc3c6..91a43f3f3c3c 100644 --- a/velox/type/TimestampConversion.cpp +++ b/velox/type/TimestampConversion.cpp @@ -623,7 +623,8 @@ Expected daysSinceEpochFromWeekOfMonthDate( "Date out of range: {}-{}-{}-{}", year, month, weekOfMonth, dayOfWeek)); } int64_t daysSinceEpochOfFirstDayOfMonth; - Status status = daysSinceEpochFromDate(year, month, 1, daysSinceEpochOfFirstDayOfMonth); + Status status = + daysSinceEpochFromDate(year, month, 1, daysSinceEpochOfFirstDayOfMonth); if (status.ok() == false) { return folly::makeUnexpected(status); } From e7180742befd57becc1dd9d49a0fd3d770b681f8 Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Wed, 31 Jul 2024 17:53:25 +0800 Subject: [PATCH 09/26] remove week validation --- velox/type/TimestampConversion.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/velox/type/TimestampConversion.cpp b/velox/type/TimestampConversion.cpp index 91a43f3f3c3c..046dd1e79b8e 100644 --- a/velox/type/TimestampConversion.cpp +++ b/velox/type/TimestampConversion.cpp @@ -147,14 +147,10 @@ bool isValidWeekDate(int32_t weekYear, int32_t weekOfYear, int32_t dayOfWeek) { bool isValidWeekOfMonthDate( int32_t year, int32_t month, - int32_t weekOfMonth, int32_t dayOfWeek) { if (dayOfWeek < 1 || dayOfWeek > 7) { return false; } - if (weekOfMonth < 1 || weekOfMonth > 5) { - return false; - } if (month < 1 || month > 12) { return false; } @@ -618,7 +614,7 @@ Expected daysSinceEpochFromWeekOfMonthDate( int32_t month, int32_t weekOfMonth, int32_t dayOfWeek) { - if (!isValidWeekOfMonthDate(year, month, weekOfMonth, dayOfWeek)) { + if (!isValidWeekOfMonthDate(year, month, dayOfWeek)) { return folly::makeUnexpected(Status::UserError( "Date out of range: {}-{}-{}-{}", year, month, weekOfMonth, dayOfWeek)); } From 9ce7750f1a28f6a9cf619028d5695286f394b8f1 Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Wed, 31 Jul 2024 19:34:49 +0800 Subject: [PATCH 10/26] change after cr --- velox/type/TimestampConversion.cpp | 15 ++++---- velox/type/TimestampConversion.h | 14 +++++-- velox/type/tests/TimestampConversionTest.cpp | 40 +++++++++++--------- 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/velox/type/TimestampConversion.cpp b/velox/type/TimestampConversion.cpp index 046dd1e79b8e..8422d937f5ff 100644 --- a/velox/type/TimestampConversion.cpp +++ b/velox/type/TimestampConversion.cpp @@ -144,10 +144,7 @@ bool isValidWeekDate(int32_t weekYear, int32_t weekOfYear, int32_t dayOfWeek) { return true; } -bool isValidWeekOfMonthDate( - int32_t year, - int32_t month, - int32_t dayOfWeek) { +bool isValidWeekOfMonthDate(int32_t year, int32_t month, int32_t dayOfWeek) { if (dayOfWeek < 1 || dayOfWeek > 7) { return false; } @@ -615,13 +612,17 @@ Expected daysSinceEpochFromWeekOfMonthDate( int32_t weekOfMonth, int32_t dayOfWeek) { if (!isValidWeekOfMonthDate(year, month, dayOfWeek)) { - return folly::makeUnexpected(Status::UserError( - "Date out of range: {}-{}-{}-{}", year, month, weekOfMonth, dayOfWeek)); + if (threadSkipErrorDetails()) { + return folly::makeUnexpected(Status::UserError()); + } else { + return folly::makeUnexpected(Status::UserError( + "Date out of range: {}-{}-{}", year, month, dayOfWeek)); + } } int64_t daysSinceEpochOfFirstDayOfMonth; Status status = daysSinceEpochFromDate(year, month, 1, daysSinceEpochOfFirstDayOfMonth); - if (status.ok() == false) { + if (!status.ok()) { return folly::makeUnexpected(status); } int32_t firstDayOfWeek = diff --git a/velox/type/TimestampConversion.h b/velox/type/TimestampConversion.h index d0f5f972f859..94fc937c1536 100644 --- a/velox/type/TimestampConversion.h +++ b/velox/type/TimestampConversion.h @@ -108,11 +108,17 @@ Status daysSinceEpochFromWeekDate( int64_t& out); /// Computes the (signed) number of days since unix epoch (1970-01-01). -/// Returns UserError status if the date is invalid. +/// Returns error status if the date is invalid. We treat days of the previous +/// or next months as a part of the specified WEEK_OF_MONTH. For example, if +/// weekOfMonth is 5 but the current month only has 4 weeks (such as February), +/// the first week of March will be considered as the 5th week of February. /// @param year Year, can be negative e.g: 1996, -2000 -/// @param month Month of year, e.g: 7 -/// @param weekOfMonth Week of month, 1 ~ 5 e.g: 2 -/// @param dayOfWeek Day of week, 1 ~ 7 e.g: 4 +/// @param month Month of year, A value in [1, 12] range. For example, 1 is Jan, +/// 7 is Jul. +/// @param weekOfMonth Week of the month. A value in [1, 5] range. For example, +/// 1 is 1st week, 3 is 3rd week. +/// @param dayOfWeek Day number of week. A value in [1, 7] range. For example, 1 +/// is Monday, 7 is Sunday. Expected daysSinceEpochFromWeekOfMonthDate( int32_t year, int32_t month, diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index d113f373aac8..60a9180608d9 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -105,32 +105,36 @@ TEST(DateTimeUtilTest, fromDateInvalid) { } TEST(DateTimeUtilTest, fromWeekOfMonthDate) { - auto testDaysSinceEpochFromWeekOfMonthDate = + auto daysSinceEpochFromWeekOfMonthDate = [](int32_t year, int32_t month, int32_t weekOfMonth, int32_t dayOfWeek) { - int64_t daysSinceEpoch; - auto expected = util::daysSinceEpochFromWeekOfMonthDate( + auto result = util::daysSinceEpochFromWeekOfMonthDate( year, month, weekOfMonth, dayOfWeek); - EXPECT_TRUE(!expected.hasError()); - return expected.value(); + EXPECT_TRUE(!result.hasError()); + return result.value(); }; - EXPECT_EQ(4, testDaysSinceEpochFromWeekOfMonthDate(1970, 1, 2, 1)); - EXPECT_EQ(361, testDaysSinceEpochFromWeekOfMonthDate(1971, 1, 1, 1)); - EXPECT_EQ(396, testDaysSinceEpochFromWeekOfMonthDate(1971, 2, 1, 1)); + EXPECT_EQ(4, daysSinceEpochFromWeekOfMonthDate(1970, 1, 2, 1)); + EXPECT_EQ(361, daysSinceEpochFromWeekOfMonthDate(1971, 1, 1, 1)); + EXPECT_EQ(396, daysSinceEpochFromWeekOfMonthDate(1971, 2, 1, 1)); - EXPECT_EQ(10952, testDaysSinceEpochFromWeekOfMonthDate(2000, 1, 1, 1)); - EXPECT_EQ(19905, testDaysSinceEpochFromWeekOfMonthDate(2024, 7, 1, 1)); + EXPECT_EQ(10952, daysSinceEpochFromWeekOfMonthDate(2000, 1, 1, 1)); + EXPECT_EQ(19905, daysSinceEpochFromWeekOfMonthDate(2024, 7, 1, 1)); // Before unix epoch. - EXPECT_EQ(-3, testDaysSinceEpochFromWeekOfMonthDate(1970, 1, 1, 1)); - EXPECT_EQ(-2, testDaysSinceEpochFromWeekOfMonthDate(1970, 1, 1, 2)); - EXPECT_EQ(-31, testDaysSinceEpochFromWeekOfMonthDate(1969, 12, 1, 1)); - EXPECT_EQ(-367, testDaysSinceEpochFromWeekOfMonthDate(1969, 1, 1, 1)); - EXPECT_EQ(-724, testDaysSinceEpochFromWeekOfMonthDate(1968, 1, 2, 1)); - EXPECT_EQ(-719533, testDaysSinceEpochFromWeekOfMonthDate(0, 1, 1, 1)); + EXPECT_EQ(-3, daysSinceEpochFromWeekOfMonthDate(1970, 1, 1, 1)); + EXPECT_EQ(-2, daysSinceEpochFromWeekOfMonthDate(1970, 1, 1, 2)); + EXPECT_EQ(-31, daysSinceEpochFromWeekOfMonthDate(1969, 12, 1, 1)); + EXPECT_EQ(-367, daysSinceEpochFromWeekOfMonthDate(1969, 1, 1, 1)); + EXPECT_EQ(-724, daysSinceEpochFromWeekOfMonthDate(1968, 1, 2, 1)); + EXPECT_EQ(-719533, daysSinceEpochFromWeekOfMonthDate(0, 1, 1, 1)); // Negative year - BC. - EXPECT_EQ(-719561, testDaysSinceEpochFromWeekOfMonthDate(-1, 12, 1, 1)); - EXPECT_EQ(-719897, testDaysSinceEpochFromWeekOfMonthDate(-1, 1, 1, 1)); + EXPECT_EQ(-719561, daysSinceEpochFromWeekOfMonthDate(-1, 12, 1, 1)); + EXPECT_EQ(-719897, daysSinceEpochFromWeekOfMonthDate(-1, 1, 1, 1)); + + // day in previous month + EXPECT_EQ(19783, daysSinceEpochFromWeekOfMonthDate(2024, 2, 5, 5)); + // day in next month + EXPECT_EQ(19751, daysSinceEpochFromWeekOfMonthDate(2024, 2, 1, 1)); } TEST(DateTimeUtilTest, fromDateString) { From 216a0003276c9352a35cbd391ced311647e3054e Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Thu, 15 Aug 2024 17:15:21 +0800 Subject: [PATCH 11/26] add lenient and ut --- velox/type/TimestampConversion.cpp | 74 ++++++++++++++--- velox/type/TimestampConversion.h | 29 ++++--- velox/type/tests/TimestampConversionTest.cpp | 83 +++++++++++++++----- 3 files changed, 147 insertions(+), 39 deletions(-) diff --git a/velox/type/TimestampConversion.cpp b/velox/type/TimestampConversion.cpp index 8422d937f5ff..975103ac002b 100644 --- a/velox/type/TimestampConversion.cpp +++ b/velox/type/TimestampConversion.cpp @@ -144,16 +144,43 @@ bool isValidWeekDate(int32_t weekYear, int32_t weekOfYear, int32_t dayOfWeek) { return true; } -bool isValidWeekOfMonthDate(int32_t year, int32_t month, int32_t dayOfWeek) { - if (dayOfWeek < 1 || dayOfWeek > 7) { +bool isValidWeekOfMonthDate( + int32_t year, + int32_t month, + int32_t weekOfMonth, + int32_t dayOfWeek) { + if (year < 1 || year > kMaxYear) { return false; } if (month < 1 || month > 12) { return false; } - if (year < kMinYear || year > kMaxYear) { + // Validate week of month. + int32_t monthLength = + isLeapYear(year) ? kLeapDays[month] : kNormalDays[month]; + int64_t daysSinceEpochOfFirstDayOfMonth; + Status status = + daysSinceEpochFromDate(year, month, 1, daysSinceEpochOfFirstDayOfMonth); + if (!status.ok()) { + return false; + } + int32_t firstDayOfWeek = + extractISODayOfTheWeek(daysSinceEpochOfFirstDayOfMonth); + int32_t firstWeekLength = 7 - firstDayOfWeek + 1; + int32_t maxWeekOfMonth = 1 + ceil((monthLength - firstWeekLength) / 7.0); + if (weekOfMonth < 1 || weekOfMonth > maxWeekOfMonth) { + return false; + } + // Validate day of week. + if (weekOfMonth == 1 && dayOfWeek < firstDayOfWeek) { return false; } + int32_t lastWeekLength = (monthLength - firstWeekLength) % 7; + if (weekOfMonth == maxWeekOfMonth && lastWeekLength != 0 && + dayOfWeek > lastWeekLength) { + return false; + } + return true; } @@ -610,15 +637,32 @@ Expected daysSinceEpochFromWeekOfMonthDate( int32_t year, int32_t month, int32_t weekOfMonth, - int32_t dayOfWeek) { - if (!isValidWeekOfMonthDate(year, month, dayOfWeek)) { + int32_t dayOfWeek, + bool lenient) { + if (!lenient && + !isValidWeekOfMonthDate(year, month, weekOfMonth, dayOfWeek)) { if (threadSkipErrorDetails()) { return folly::makeUnexpected(Status::UserError()); } else { return folly::makeUnexpected(Status::UserError( - "Date out of range: {}-{}-{}", year, month, dayOfWeek)); - } + "Date out of range: {}-{}-{}-{}", + year, + month, + weekOfMonth, + dayOfWeek)); + } + } + // If the month is out of range, adjust it into range + int32_t additionYears; + if (month < 1) { + additionYears = month / 12 - 1; + month = 12 - abs(month) % 12; + } else { + additionYears = (month - 1) / 12; + month = (month - 1) % 12 + 1; } + year += additionYears; + int64_t daysSinceEpochOfFirstDayOfMonth; Status status = daysSinceEpochFromDate(year, month, 1, daysSinceEpochOfFirstDayOfMonth); @@ -627,8 +671,16 @@ Expected daysSinceEpochFromWeekOfMonthDate( } int32_t firstDayOfWeek = extractISODayOfTheWeek(daysSinceEpochOfFirstDayOfMonth); + int32_t days; + if (dayOfWeek < 1) { + days = 7 - abs(dayOfWeek - 1) % 7; + } else if (dayOfWeek > 7) { + days = (dayOfWeek - 1) % 7; + } else { + days = dayOfWeek % 7; + } int64_t result = daysSinceEpochOfFirstDayOfMonth - (firstDayOfWeek - 1) + - 7 * (weekOfMonth - 1) + dayOfWeek - 1; + 7 * (weekOfMonth - 1) + days - 1; return result; } @@ -682,7 +734,7 @@ Expected fromDateString(const char* str, size_t len, ParseMode mode) { return daysSinceEpoch; } -int32_t extractISODayOfTheWeek(int32_t daysSinceEpoch) { +int32_t extractISODayOfTheWeek(int64_t daysSinceEpoch) { // date of 0 is 1970-01-01, which was a Thursday (4) // -7 = 4 // -6 = 5 @@ -701,10 +753,10 @@ int32_t extractISODayOfTheWeek(int32_t daysSinceEpoch) { // 7 = 4 if (daysSinceEpoch < 0) { // negative date: start off at 4 and cycle downwards - return (7 - ((-int64_t(daysSinceEpoch) + 3) % 7)); + return (7 - ((-int128_t(daysSinceEpoch) + 3) % 7)); } else { // positive date: start off at 4 and cycle upwards - return ((int64_t(daysSinceEpoch) + 3) % 7) + 1; + return ((int128_t(daysSinceEpoch) + 3) % 7) + 1; } } diff --git a/velox/type/TimestampConversion.h b/velox/type/TimestampConversion.h index 94fc937c1536..0a1677ef1968 100644 --- a/velox/type/TimestampConversion.h +++ b/velox/type/TimestampConversion.h @@ -107,15 +107,25 @@ Status daysSinceEpochFromWeekDate( int32_t dayOfWeek, int64_t& out); -/// Computes the (signed) number of days since unix epoch (1970-01-01). -/// Returns error status if the date is invalid. We treat days of the previous -/// or next months as a part of the specified WEEK_OF_MONTH. For example, if -/// weekOfMonth is 5 but the current month only has 4 weeks (such as February), -/// the first week of March will be considered as the 5th week of February. -/// @param year Year, can be negative e.g: 1996, -2000 -/// @param month Month of year, A value in [1, 12] range. For example, 1 is Jan, +/// Computes the signed number of days since the Unix epoch (1970-01-01). To +/// align with Spark's SimpleDateFormat behavior, this function offers two +/// modes: lenient and non-lenient. If `lenient` is false, it returns an error +/// status if the date is invalid. If `lenient` is true, it accepts a wider +/// range of arguments. For the month parameter, values greater than 12 wrap +/// around to the start of the year, and values less than 1 count backward from +/// December. For example, 13 corresponds to January of the following year and +/// -1 corresponds to November of the previous year. For the weekOfMonth +/// parameter, we consider days of the previous or next months as part of the +/// specified weekOfMonth and dayOfWeek. For example, if weekOfMonth is 5 but +/// the current month only has 4 weeks (such as February), the first week of +/// March will be considered as the 5th week of February. For the dayOfWeek +/// parameter, if weekOfMonth is 1 and dayOfWeek is 1 but the month's first day +/// is a Saturday, the Monday of the last week of the previous month will be +/// used. +/// @param year Year, A value in [1, 292278994] range. e.g: 1996, -2000 +/// @param month Month of year. A value in [1, 12] range. For example, 1 is Jan, /// 7 is Jul. -/// @param weekOfMonth Week of the month. A value in [1, 5] range. For example, +/// @param weekOfMonth Week of the month. A value in [1, 6] range. For example, /// 1 is 1st week, 3 is 3rd week. /// @param dayOfWeek Day number of week. A value in [1, 7] range. For example, 1 /// is Monday, 7 is Sunday. @@ -123,7 +133,8 @@ Expected daysSinceEpochFromWeekOfMonthDate( int32_t year, int32_t month, int32_t weekOfMonth, - int32_t dayOfWeek); + int32_t dayOfWeek, + bool lenient); /// Computes the (signed) number of days since unix epoch (1970-01-01). /// Returns UserError status if the date is invalid. diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index 60a9180608d9..56dec87e919f 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -105,36 +105,81 @@ TEST(DateTimeUtilTest, fromDateInvalid) { } TEST(DateTimeUtilTest, fromWeekOfMonthDate) { - auto daysSinceEpochFromWeekOfMonthDate = + auto daysSinceEpoch = [](int32_t year, int32_t month, int32_t weekOfMonth, int32_t dayOfWeek) { auto result = util::daysSinceEpochFromWeekOfMonthDate( - year, month, weekOfMonth, dayOfWeek); + year, month, weekOfMonth, dayOfWeek, true); EXPECT_TRUE(!result.hasError()); return result.value(); }; - EXPECT_EQ(4, daysSinceEpochFromWeekOfMonthDate(1970, 1, 2, 1)); - EXPECT_EQ(361, daysSinceEpochFromWeekOfMonthDate(1971, 1, 1, 1)); - EXPECT_EQ(396, daysSinceEpochFromWeekOfMonthDate(1971, 2, 1, 1)); + EXPECT_EQ(4, daysSinceEpoch(1970, 1, 2, 1)); + EXPECT_EQ(361, daysSinceEpoch(1971, 1, 1, 1)); + EXPECT_EQ(396, daysSinceEpoch(1971, 2, 1, 1)); - EXPECT_EQ(10952, daysSinceEpochFromWeekOfMonthDate(2000, 1, 1, 1)); - EXPECT_EQ(19905, daysSinceEpochFromWeekOfMonthDate(2024, 7, 1, 1)); + EXPECT_EQ(10952, daysSinceEpoch(2000, 1, 1, 1)); + EXPECT_EQ(19905, daysSinceEpoch(2024, 7, 1, 1)); // Before unix epoch. - EXPECT_EQ(-3, daysSinceEpochFromWeekOfMonthDate(1970, 1, 1, 1)); - EXPECT_EQ(-2, daysSinceEpochFromWeekOfMonthDate(1970, 1, 1, 2)); - EXPECT_EQ(-31, daysSinceEpochFromWeekOfMonthDate(1969, 12, 1, 1)); - EXPECT_EQ(-367, daysSinceEpochFromWeekOfMonthDate(1969, 1, 1, 1)); - EXPECT_EQ(-724, daysSinceEpochFromWeekOfMonthDate(1968, 1, 2, 1)); - EXPECT_EQ(-719533, daysSinceEpochFromWeekOfMonthDate(0, 1, 1, 1)); + EXPECT_EQ(-3, daysSinceEpoch(1970, 1, 1, 1)); + EXPECT_EQ(-2, daysSinceEpoch(1970, 1, 1, 2)); + EXPECT_EQ(-31, daysSinceEpoch(1969, 12, 1, 1)); + EXPECT_EQ(-367, daysSinceEpoch(1969, 1, 1, 1)); + EXPECT_EQ(-724, daysSinceEpoch(1968, 1, 2, 1)); + EXPECT_EQ(-719533, daysSinceEpoch(0, 1, 1, 1)); // Negative year - BC. - EXPECT_EQ(-719561, daysSinceEpochFromWeekOfMonthDate(-1, 12, 1, 1)); - EXPECT_EQ(-719897, daysSinceEpochFromWeekOfMonthDate(-1, 1, 1, 1)); + EXPECT_EQ(-719561, daysSinceEpoch(-1, 12, 1, 1)); + EXPECT_EQ(-719897, daysSinceEpoch(-1, 1, 1, 1)); + + // Day in the previous month. + EXPECT_EQ(19783, daysSinceEpoch(2024, 2, 5, 5)); + // Day in the next month. + EXPECT_EQ(19751, daysSinceEpoch(2024, 2, 1, 1)); + + // Out of range day of week. + EXPECT_EQ(338, daysSinceEpoch(1970, 12, 1, 0)); + EXPECT_EQ(337, daysSinceEpoch(1970, 12, 1, -1)); + EXPECT_EQ(337, daysSinceEpoch(1970, 12, 1, -8)); + + EXPECT_EQ(332, daysSinceEpoch(1970, 12, 1, 8)); + EXPECT_EQ(333, daysSinceEpoch(1970, 12, 1, 9)); + EXPECT_EQ(336, daysSinceEpoch(1970, 12, 1, 19)); + + // Out of range month. + EXPECT_EQ(-3, daysSinceEpoch(1970, 1, 1, 1)); + EXPECT_EQ(207, daysSinceEpoch(1970, 8, 1, 1)); + EXPECT_EQ(361, daysSinceEpoch(1970, 13, 1, 1)); + + EXPECT_EQ(-31, daysSinceEpoch(1970, 0, 1, 1)); + EXPECT_EQ(-66, daysSinceEpoch(1970, -1, 1, 1)); + EXPECT_EQ(-430, daysSinceEpoch(1970, -13, 1, 1)); +} + +TEST(DateTimeUtilTest, fromWeekOfMonthDateInvalid) { + auto daysSinceEpoch = [](int32_t year, + int32_t month, + int32_t weekOfMonth, + int32_t dayOfWeek, + const std::string& error) { + auto result = util::daysSinceEpochFromWeekOfMonthDate( + year, month, weekOfMonth, dayOfWeek, false); + EXPECT_TRUE(result.error().isUserError()); + EXPECT_EQ(result.error().message(), error); + }; - // day in previous month - EXPECT_EQ(19783, daysSinceEpochFromWeekOfMonthDate(2024, 2, 5, 5)); - // day in next month - EXPECT_EQ(19751, daysSinceEpochFromWeekOfMonthDate(2024, 2, 1, 1)); + EXPECT_NO_THROW(daysSinceEpoch(-1, 1, 1, 1, "Date out of range: -1-1-1-1")); + EXPECT_NO_THROW( + daysSinceEpoch(292278995, 1, 1, 1, "Date out of range: 292278995-1-1-1")); + EXPECT_NO_THROW( + daysSinceEpoch(2024, 0, 1, 1, "Date out of range: 2024-0-1-1")); + EXPECT_NO_THROW( + daysSinceEpoch(2024, 13, 1, 1, "Date out of range: 2024-13-1-1")); + EXPECT_NO_THROW( + daysSinceEpoch(2024, 1, 6, 1, "Date out of range: 2024-1-6-1")); + EXPECT_NO_THROW( + daysSinceEpoch(2024, 2, 1, 1, "Date out of range: 2024-2-1-1")); + EXPECT_NO_THROW( + daysSinceEpoch(2024, 2, 5, 5, "Date out of range: 2024-2-5-5")); } TEST(DateTimeUtilTest, fromDateString) { From e850388f78cda82aa14609faa37b379fe0d63f6b Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Fri, 16 Aug 2024 16:00:39 +0800 Subject: [PATCH 12/26] changes after ut --- velox/type/TimestampConversion.cpp | 32 ++++++++++++++++-------- velox/type/TimestampConversion.h | 40 ++++++++++++++++-------------- 2 files changed, 42 insertions(+), 30 deletions(-) diff --git a/velox/type/TimestampConversion.cpp b/velox/type/TimestampConversion.cpp index 975103ac002b..ee9036168dbf 100644 --- a/velox/type/TimestampConversion.cpp +++ b/velox/type/TimestampConversion.cpp @@ -45,6 +45,7 @@ #include "velox/common/base/CheckedArithmetic.h" #include "velox/common/base/Exceptions.h" #include "velox/type/tz/TimeZoneMap.h" +#include "HugeInt.h" namespace facebook::velox::util { @@ -155,27 +156,34 @@ bool isValidWeekOfMonthDate( if (month < 1 || month > 12) { return false; } - // Validate week of month. - int32_t monthLength = - isLeapYear(year) ? kLeapDays[month] : kNormalDays[month]; + int64_t daysSinceEpochOfFirstDayOfMonth; - Status status = + const Status status = daysSinceEpochFromDate(year, month, 1, daysSinceEpochOfFirstDayOfMonth); if (!status.ok()) { return false; } - int32_t firstDayOfWeek = + + // Calculates the max week of month and validates if it is in the valid range. + const int32_t firstDayOfWeek = extractISODayOfTheWeek(daysSinceEpochOfFirstDayOfMonth); - int32_t firstWeekLength = 7 - firstDayOfWeek + 1; - int32_t maxWeekOfMonth = 1 + ceil((monthLength - firstWeekLength) / 7.0); + const int32_t firstWeekLength = 7 - firstDayOfWeek + 1; + const int32_t monthLength = + isLeapYear(year) ? kLeapDays[month] : kNormalDays[month]; + const int32_t maxWeekOfMonth = + 1 + ceil((monthLength - firstWeekLength) / 7.0); if (weekOfMonth < 1 || weekOfMonth > maxWeekOfMonth) { return false; } + // Validate day of week. + // If dayOfWeek is before the first day of week, it is considered invalid. if (weekOfMonth == 1 && dayOfWeek < firstDayOfWeek) { return false; } - int32_t lastWeekLength = (monthLength - firstWeekLength) % 7; + const int32_t lastWeekLength = (monthLength - firstWeekLength) % 7; + // If dayOfWeek is after the last day of the last week of the month, it is + // considered invalid. if (weekOfMonth == maxWeekOfMonth && lastWeekLength != 0 && dayOfWeek > lastWeekLength) { return false; @@ -652,12 +660,14 @@ Expected daysSinceEpochFromWeekOfMonthDate( dayOfWeek)); } } - // If the month is out of range, adjust it into range - int32_t additionYears; + + // Adjusts the year and month to ensure month is within the range 1-12, + // accounting for overflow or underflow. + int32_t additionYears = 0; if (month < 1) { additionYears = month / 12 - 1; month = 12 - abs(month) % 12; - } else { + } else if (month > 12) { additionYears = (month - 1) / 12; month = (month - 1) % 12 + 1; } diff --git a/velox/type/TimestampConversion.h b/velox/type/TimestampConversion.h index 0a1677ef1968..62411a484313 100644 --- a/velox/type/TimestampConversion.h +++ b/velox/type/TimestampConversion.h @@ -111,24 +111,26 @@ Status daysSinceEpochFromWeekDate( /// align with Spark's SimpleDateFormat behavior, this function offers two /// modes: lenient and non-lenient. If `lenient` is false, it returns an error /// status if the date is invalid. If `lenient` is true, it accepts a wider -/// range of arguments. For the month parameter, values greater than 12 wrap -/// around to the start of the year, and values less than 1 count backward from -/// December. For example, 13 corresponds to January of the following year and -/// -1 corresponds to November of the previous year. For the weekOfMonth -/// parameter, we consider days of the previous or next months as part of the -/// specified weekOfMonth and dayOfWeek. For example, if weekOfMonth is 5 but -/// the current month only has 4 weeks (such as February), the first week of -/// March will be considered as the 5th week of February. For the dayOfWeek -/// parameter, if weekOfMonth is 1 and dayOfWeek is 1 but the month's first day -/// is a Saturday, the Monday of the last week of the previous month will be -/// used. -/// @param year Year, A value in [1, 292278994] range. e.g: 1996, -2000 -/// @param month Month of year. A value in [1, 12] range. For example, 1 is Jan, -/// 7 is Jul. -/// @param weekOfMonth Week of the month. A value in [1, 6] range. For example, -/// 1 is 1st week, 3 is 3rd week. -/// @param dayOfWeek Day number of week. A value in [1, 7] range. For example, 1 -/// is Monday, 7 is Sunday. +/// range of arguments. +/// @param year Year. For non-lenient mode, it should be in the range [1, +/// 292278994]. e.g: 1996, -2000 +/// @param month Month of year. For non-lenient mode, it should be in the range +/// [1, 12]. For example, 1 is Jan, 7 is Jul. For lenient mode, values greater +/// than 12 wrap around to the start of the year, and values less than 1 count +/// backward from December. For example, 13 corresponds to January of the +/// following year and -1 corresponds to November of the previous year. +/// @param weekOfMonth Week of the month. For non-lenient mode, it should be in +/// the range [1, 6]. For example, 1 is 1st week, 3 is 3rd week. For lenient +/// mode, we consider days of the previous or next months as part of the +/// specified weekOfMonth. For example, if weekOfMonth is 5 but the current +/// month only has 4 weeks (such as February), the first week of March will be +/// considered as the 5th week of February. +/// @param dayOfWeek Day number of week. For non-lenient mode, it should be in +/// the range [1, 7]. For example, 1 is Monday, 7 is Sunday. For lenient mode, +/// we consider days of the previous or next months as part of the specified +/// dayOfWeek.For example, if weekOfMonth is 1 and dayOfWeek is 1 but the +/// month's first day is Saturday, the Monday of the last week of the previous +/// month will be used. Expected daysSinceEpochFromWeekOfMonthDate( int32_t year, int32_t month, @@ -152,7 +154,7 @@ inline Expected fromDateString(const StringView& str, ParseMode mode) { } // Extracts the day of the week from the number of days since epoch -int32_t extractISODayOfTheWeek(int32_t daysSinceEpoch); +int32_t extractISODayOfTheWeek(int64_t daysSinceEpoch); /// Time conversions. From cb45539df3dd43e5b606c4f587c95c83e77e44cd Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Fri, 16 Aug 2024 16:07:08 +0800 Subject: [PATCH 13/26] spotless --- velox/type/TimestampConversion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/velox/type/TimestampConversion.cpp b/velox/type/TimestampConversion.cpp index ee9036168dbf..686744189729 100644 --- a/velox/type/TimestampConversion.cpp +++ b/velox/type/TimestampConversion.cpp @@ -42,10 +42,10 @@ #include "velox/type/TimestampConversion.h" #include +#include "HugeInt.h" #include "velox/common/base/CheckedArithmetic.h" #include "velox/common/base/Exceptions.h" #include "velox/type/tz/TimeZoneMap.h" -#include "HugeInt.h" namespace facebook::velox::util { From a98fedd71b38bab8f15c0f1ad11d8414b8726616 Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Mon, 19 Aug 2024 16:53:56 +0800 Subject: [PATCH 14/26] naming --- velox/type/tests/TimestampConversionTest.cpp | 73 ++++++++++---------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index 56dec87e919f..e92197c18dd9 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -105,58 +105,58 @@ TEST(DateTimeUtilTest, fromDateInvalid) { } TEST(DateTimeUtilTest, fromWeekOfMonthDate) { - auto daysSinceEpoch = + auto daysSinceEpochLenient = [](int32_t year, int32_t month, int32_t weekOfMonth, int32_t dayOfWeek) { auto result = util::daysSinceEpochFromWeekOfMonthDate( year, month, weekOfMonth, dayOfWeek, true); EXPECT_TRUE(!result.hasError()); return result.value(); }; - EXPECT_EQ(4, daysSinceEpoch(1970, 1, 2, 1)); - EXPECT_EQ(361, daysSinceEpoch(1971, 1, 1, 1)); - EXPECT_EQ(396, daysSinceEpoch(1971, 2, 1, 1)); + EXPECT_EQ(4, daysSinceEpochLenient(1970, 1, 2, 1)); + EXPECT_EQ(361, daysSinceEpochLenient(1971, 1, 1, 1)); + EXPECT_EQ(396, daysSinceEpochLenient(1971, 2, 1, 1)); - EXPECT_EQ(10952, daysSinceEpoch(2000, 1, 1, 1)); - EXPECT_EQ(19905, daysSinceEpoch(2024, 7, 1, 1)); + EXPECT_EQ(10952, daysSinceEpochLenient(2000, 1, 1, 1)); + EXPECT_EQ(19905, daysSinceEpochLenient(2024, 7, 1, 1)); // Before unix epoch. - EXPECT_EQ(-3, daysSinceEpoch(1970, 1, 1, 1)); - EXPECT_EQ(-2, daysSinceEpoch(1970, 1, 1, 2)); - EXPECT_EQ(-31, daysSinceEpoch(1969, 12, 1, 1)); - EXPECT_EQ(-367, daysSinceEpoch(1969, 1, 1, 1)); - EXPECT_EQ(-724, daysSinceEpoch(1968, 1, 2, 1)); - EXPECT_EQ(-719533, daysSinceEpoch(0, 1, 1, 1)); + EXPECT_EQ(-3, daysSinceEpochLenient(1970, 1, 1, 1)); + EXPECT_EQ(-2, daysSinceEpochLenient(1970, 1, 1, 2)); + EXPECT_EQ(-31, daysSinceEpochLenient(1969, 12, 1, 1)); + EXPECT_EQ(-367, daysSinceEpochLenient(1969, 1, 1, 1)); + EXPECT_EQ(-724, daysSinceEpochLenient(1968, 1, 2, 1)); + EXPECT_EQ(-719533, daysSinceEpochLenient(0, 1, 1, 1)); // Negative year - BC. - EXPECT_EQ(-719561, daysSinceEpoch(-1, 12, 1, 1)); - EXPECT_EQ(-719897, daysSinceEpoch(-1, 1, 1, 1)); + EXPECT_EQ(-719561, daysSinceEpochLenient(-1, 12, 1, 1)); + EXPECT_EQ(-719897, daysSinceEpochLenient(-1, 1, 1, 1)); // Day in the previous month. - EXPECT_EQ(19783, daysSinceEpoch(2024, 2, 5, 5)); + EXPECT_EQ(19783, daysSinceEpochLenient(2024, 2, 5, 5)); // Day in the next month. - EXPECT_EQ(19751, daysSinceEpoch(2024, 2, 1, 1)); + EXPECT_EQ(19751, daysSinceEpochLenient(2024, 2, 1, 1)); // Out of range day of week. - EXPECT_EQ(338, daysSinceEpoch(1970, 12, 1, 0)); - EXPECT_EQ(337, daysSinceEpoch(1970, 12, 1, -1)); - EXPECT_EQ(337, daysSinceEpoch(1970, 12, 1, -8)); + EXPECT_EQ(338, daysSinceEpochLenient(1970, 12, 1, 0)); + EXPECT_EQ(337, daysSinceEpochLenient(1970, 12, 1, -1)); + EXPECT_EQ(337, daysSinceEpochLenient(1970, 12, 1, -8)); - EXPECT_EQ(332, daysSinceEpoch(1970, 12, 1, 8)); - EXPECT_EQ(333, daysSinceEpoch(1970, 12, 1, 9)); - EXPECT_EQ(336, daysSinceEpoch(1970, 12, 1, 19)); + EXPECT_EQ(332, daysSinceEpochLenient(1970, 12, 1, 8)); + EXPECT_EQ(333, daysSinceEpochLenient(1970, 12, 1, 9)); + EXPECT_EQ(336, daysSinceEpochLenient(1970, 12, 1, 19)); // Out of range month. - EXPECT_EQ(-3, daysSinceEpoch(1970, 1, 1, 1)); - EXPECT_EQ(207, daysSinceEpoch(1970, 8, 1, 1)); - EXPECT_EQ(361, daysSinceEpoch(1970, 13, 1, 1)); + EXPECT_EQ(-3, daysSinceEpochLenient(1970, 1, 1, 1)); + EXPECT_EQ(207, daysSinceEpochLenient(1970, 8, 1, 1)); + EXPECT_EQ(361, daysSinceEpochLenient(1970, 13, 1, 1)); - EXPECT_EQ(-31, daysSinceEpoch(1970, 0, 1, 1)); - EXPECT_EQ(-66, daysSinceEpoch(1970, -1, 1, 1)); - EXPECT_EQ(-430, daysSinceEpoch(1970, -13, 1, 1)); + EXPECT_EQ(-31, daysSinceEpochLenient(1970, 0, 1, 1)); + EXPECT_EQ(-66, daysSinceEpochLenient(1970, -1, 1, 1)); + EXPECT_EQ(-430, daysSinceEpochLenient(1970, -13, 1, 1)); } TEST(DateTimeUtilTest, fromWeekOfMonthDateInvalid) { - auto daysSinceEpoch = [](int32_t year, + auto daysSinceEpochNonLenient = [](int32_t year, int32_t month, int32_t weekOfMonth, int32_t dayOfWeek, @@ -167,19 +167,18 @@ TEST(DateTimeUtilTest, fromWeekOfMonthDateInvalid) { EXPECT_EQ(result.error().message(), error); }; - EXPECT_NO_THROW(daysSinceEpoch(-1, 1, 1, 1, "Date out of range: -1-1-1-1")); EXPECT_NO_THROW( - daysSinceEpoch(292278995, 1, 1, 1, "Date out of range: 292278995-1-1-1")); + daysSinceEpochNonLenient(-1, 1, 1, 1, "Date out of range: -1-1-1-1")); + EXPECT_NO_THROW(daysSinceEpochNonLenient(292278995, 1, 1, 1, "Date out of range: 292278995-1-1-1")); EXPECT_NO_THROW( - daysSinceEpoch(2024, 0, 1, 1, "Date out of range: 2024-0-1-1")); + daysSinceEpochNonLenient(2024, 0, 1, 1, "Date out of range: 2024-0-1-1")); + EXPECT_NO_THROW(daysSinceEpochNonLenient(2024, 13, 1, 1, "Date out of range: 2024-13-1-1")); EXPECT_NO_THROW( - daysSinceEpoch(2024, 13, 1, 1, "Date out of range: 2024-13-1-1")); + daysSinceEpochNonLenient(2024, 1, 6, 1, "Date out of range: 2024-1-6-1")); EXPECT_NO_THROW( - daysSinceEpoch(2024, 1, 6, 1, "Date out of range: 2024-1-6-1")); + daysSinceEpochNonLenient(2024, 2, 1, 1, "Date out of range: 2024-2-1-1")); EXPECT_NO_THROW( - daysSinceEpoch(2024, 2, 1, 1, "Date out of range: 2024-2-1-1")); - EXPECT_NO_THROW( - daysSinceEpoch(2024, 2, 5, 5, "Date out of range: 2024-2-5-5")); + daysSinceEpochNonLenient(2024, 2, 5, 5, "Date out of range: 2024-2-5-5")); } TEST(DateTimeUtilTest, fromDateString) { From 61359911196a824f256d9d0a4197ced9bb4eb99d Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Mon, 19 Aug 2024 17:50:08 +0800 Subject: [PATCH 15/26] naming cmt --- velox/type/TimestampConversion.cpp | 6 +++--- velox/type/TimestampConversion.h | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/velox/type/TimestampConversion.cpp b/velox/type/TimestampConversion.cpp index 686744189729..691d71fbcae4 100644 --- a/velox/type/TimestampConversion.cpp +++ b/velox/type/TimestampConversion.cpp @@ -170,9 +170,9 @@ bool isValidWeekOfMonthDate( const int32_t firstWeekLength = 7 - firstDayOfWeek + 1; const int32_t monthLength = isLeapYear(year) ? kLeapDays[month] : kNormalDays[month]; - const int32_t maxWeekOfMonth = + const int32_t actualNumberOfWeeks = 1 + ceil((monthLength - firstWeekLength) / 7.0); - if (weekOfMonth < 1 || weekOfMonth > maxWeekOfMonth) { + if (weekOfMonth < 1 || weekOfMonth > actualNumberOfWeeks) { return false; } @@ -184,7 +184,7 @@ bool isValidWeekOfMonthDate( const int32_t lastWeekLength = (monthLength - firstWeekLength) % 7; // If dayOfWeek is after the last day of the last week of the month, it is // considered invalid. - if (weekOfMonth == maxWeekOfMonth && lastWeekLength != 0 && + if (weekOfMonth == actualNumberOfWeeks && lastWeekLength != 0 && dayOfWeek > lastWeekLength) { return false; } diff --git a/velox/type/TimestampConversion.h b/velox/type/TimestampConversion.h index 62411a484313..b4157ac9cfcc 100644 --- a/velox/type/TimestampConversion.h +++ b/velox/type/TimestampConversion.h @@ -113,7 +113,8 @@ Status daysSinceEpochFromWeekDate( /// status if the date is invalid. If `lenient` is true, it accepts a wider /// range of arguments. /// @param year Year. For non-lenient mode, it should be in the range [1, -/// 292278994]. e.g: 1996, -2000 +/// 292278994]. e.g: 1996, -2000. For lenient mode, values outside this range +/// could result in overflow. /// @param month Month of year. For non-lenient mode, it should be in the range /// [1, 12]. For example, 1 is Jan, 7 is Jul. For lenient mode, values greater /// than 12 wrap around to the start of the year, and values less than 1 count From b5f3be91d8db2e559cbe1d56686ebc91aa97242a Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Mon, 19 Aug 2024 18:50:40 +0800 Subject: [PATCH 16/26] reformat --- velox/type/tests/TimestampConversionTest.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index e92197c18dd9..997e62f4f039 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -157,10 +157,10 @@ TEST(DateTimeUtilTest, fromWeekOfMonthDate) { TEST(DateTimeUtilTest, fromWeekOfMonthDateInvalid) { auto daysSinceEpochNonLenient = [](int32_t year, - int32_t month, - int32_t weekOfMonth, - int32_t dayOfWeek, - const std::string& error) { + int32_t month, + int32_t weekOfMonth, + int32_t dayOfWeek, + const std::string& error) { auto result = util::daysSinceEpochFromWeekOfMonthDate( year, month, weekOfMonth, dayOfWeek, false); EXPECT_TRUE(result.error().isUserError()); @@ -169,10 +169,12 @@ TEST(DateTimeUtilTest, fromWeekOfMonthDateInvalid) { EXPECT_NO_THROW( daysSinceEpochNonLenient(-1, 1, 1, 1, "Date out of range: -1-1-1-1")); - EXPECT_NO_THROW(daysSinceEpochNonLenient(292278995, 1, 1, 1, "Date out of range: 292278995-1-1-1")); + EXPECT_NO_THROW(daysSinceEpochNonLenient( + 292278995, 1, 1, 1, "Date out of range: 292278995-1-1-1")); EXPECT_NO_THROW( daysSinceEpochNonLenient(2024, 0, 1, 1, "Date out of range: 2024-0-1-1")); - EXPECT_NO_THROW(daysSinceEpochNonLenient(2024, 13, 1, 1, "Date out of range: 2024-13-1-1")); + EXPECT_NO_THROW(daysSinceEpochNonLenient( + 2024, 13, 1, 1, "Date out of range: 2024-13-1-1")); EXPECT_NO_THROW( daysSinceEpochNonLenient(2024, 1, 6, 1, "Date out of range: 2024-1-6-1")); EXPECT_NO_THROW( From 3165392f5d462b67dc2cf4e144226a1cb0f8a322 Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Fri, 23 Aug 2024 11:10:16 +0800 Subject: [PATCH 17/26] update --- velox/type/TimestampConversion.cpp | 22 ++++++++++++-------- velox/type/TimestampConversion.h | 12 +++++------ velox/type/tests/TimestampConversionTest.cpp | 6 ++++++ 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/velox/type/TimestampConversion.cpp b/velox/type/TimestampConversion.cpp index 691d71fbcae4..08acbe0804c3 100644 --- a/velox/type/TimestampConversion.cpp +++ b/velox/type/TimestampConversion.cpp @@ -164,15 +164,16 @@ bool isValidWeekOfMonthDate( return false; } - // Calculates the max week of month and validates if it is in the valid range. + // Calculates the actual number of week of month and validates if it is in the + // valid range. const int32_t firstDayOfWeek = extractISODayOfTheWeek(daysSinceEpochOfFirstDayOfMonth); const int32_t firstWeekLength = 7 - firstDayOfWeek + 1; const int32_t monthLength = isLeapYear(year) ? kLeapDays[month] : kNormalDays[month]; - const int32_t actualNumberOfWeeks = + const int32_t actualWeeks = 1 + ceil((monthLength - firstWeekLength) / 7.0); - if (weekOfMonth < 1 || weekOfMonth > actualNumberOfWeeks) { + if (weekOfMonth < 1 || weekOfMonth > actualWeeks) { return false; } @@ -184,7 +185,7 @@ bool isValidWeekOfMonthDate( const int32_t lastWeekLength = (monthLength - firstWeekLength) % 7; // If dayOfWeek is after the last day of the last week of the month, it is // considered invalid. - if (weekOfMonth == actualNumberOfWeeks && lastWeekLength != 0 && + if (weekOfMonth == actualWeeks && lastWeekLength != 0 && dayOfWeek > lastWeekLength) { return false; } @@ -674,12 +675,16 @@ Expected daysSinceEpochFromWeekOfMonthDate( year += additionYears; int64_t daysSinceEpochOfFirstDayOfMonth; - Status status = + const Status status = daysSinceEpochFromDate(year, month, 1, daysSinceEpochOfFirstDayOfMonth); if (!status.ok()) { - return folly::makeUnexpected(status); + if (threadSkipErrorDetails()) { + return folly::makeUnexpected(Status::UserError()); + } else { + return folly::makeUnexpected(status); + } } - int32_t firstDayOfWeek = + const int32_t firstDayOfWeek = extractISODayOfTheWeek(daysSinceEpochOfFirstDayOfMonth); int32_t days; if (dayOfWeek < 1) { @@ -689,9 +694,8 @@ Expected daysSinceEpochFromWeekOfMonthDate( } else { days = dayOfWeek % 7; } - int64_t result = daysSinceEpochOfFirstDayOfMonth - (firstDayOfWeek - 1) + + return daysSinceEpochOfFirstDayOfMonth - (firstDayOfWeek - 1) + 7 * (weekOfMonth - 1) + days - 1; - return result; } Status diff --git a/velox/type/TimestampConversion.h b/velox/type/TimestampConversion.h index b4157ac9cfcc..88a2f8485709 100644 --- a/velox/type/TimestampConversion.h +++ b/velox/type/TimestampConversion.h @@ -109,16 +109,16 @@ Status daysSinceEpochFromWeekDate( /// Computes the signed number of days since the Unix epoch (1970-01-01). To /// align with Spark's SimpleDateFormat behavior, this function offers two -/// modes: lenient and non-lenient. If `lenient` is false, it returns an error -/// status if the date is invalid. If `lenient` is true, it accepts a wider -/// range of arguments. +/// modes: lenient and non-lenient. For non-lenient mode, it returns an error +/// status if the date is invalid. For lenient mode, it accepts a wider range of +/// arguments. /// @param year Year. For non-lenient mode, it should be in the range [1, /// 292278994]. e.g: 1996, -2000. For lenient mode, values outside this range /// could result in overflow. /// @param month Month of year. For non-lenient mode, it should be in the range -/// [1, 12]. For example, 1 is Jan, 7 is Jul. For lenient mode, values greater -/// than 12 wrap around to the start of the year, and values less than 1 count -/// backward from December. For example, 13 corresponds to January of the +/// [1, 12]. For example, 1 is January, 7 is July. For lenient mode, values +/// greater than 12 wrap around to the start of the year, and values less than 1 +/// count backward from December. For example, 13 corresponds to January of the /// following year and -1 corresponds to November of the previous year. /// @param weekOfMonth Week of the month. For non-lenient mode, it should be in /// the range [1, 6]. For example, 1 is 1st week, 3 is 3rd week. For lenient diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index 997e62f4f039..82ebeffe9d35 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -112,6 +112,7 @@ TEST(DateTimeUtilTest, fromWeekOfMonthDate) { EXPECT_TRUE(!result.hasError()); return result.value(); }; + EXPECT_EQ(4, daysSinceEpochLenient(1970, 1, 2, 1)); EXPECT_EQ(361, daysSinceEpochLenient(1971, 1, 1, 1)); EXPECT_EQ(396, daysSinceEpochLenient(1971, 2, 1, 1)); @@ -153,6 +154,11 @@ TEST(DateTimeUtilTest, fromWeekOfMonthDate) { EXPECT_EQ(-31, daysSinceEpochLenient(1970, 0, 1, 1)); EXPECT_EQ(-66, daysSinceEpochLenient(1970, -1, 1, 1)); EXPECT_EQ(-430, daysSinceEpochLenient(1970, -13, 1, 1)); + + // Out of range year. + auto result = util::daysSinceEpochFromWeekOfMonthDate( + 292278995, 1, 1, 1, true); + EXPECT_EQ(result.error().message(), "Date out of range: 292278995-1-1"); } TEST(DateTimeUtilTest, fromWeekOfMonthDateInvalid) { From d3f2657477fdac2fa808d6d1e9fbeed6c9331f7a Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Fri, 23 Aug 2024 11:11:05 +0800 Subject: [PATCH 18/26] reformat --- velox/type/TimestampConversion.cpp | 3 +-- velox/type/tests/TimestampConversionTest.cpp | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/velox/type/TimestampConversion.cpp b/velox/type/TimestampConversion.cpp index 08acbe0804c3..67ef7d0deda3 100644 --- a/velox/type/TimestampConversion.cpp +++ b/velox/type/TimestampConversion.cpp @@ -171,8 +171,7 @@ bool isValidWeekOfMonthDate( const int32_t firstWeekLength = 7 - firstDayOfWeek + 1; const int32_t monthLength = isLeapYear(year) ? kLeapDays[month] : kNormalDays[month]; - const int32_t actualWeeks = - 1 + ceil((monthLength - firstWeekLength) / 7.0); + const int32_t actualWeeks = 1 + ceil((monthLength - firstWeekLength) / 7.0); if (weekOfMonth < 1 || weekOfMonth > actualWeeks) { return false; } diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index 82ebeffe9d35..b8e8d8c5a9f8 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -156,8 +156,8 @@ TEST(DateTimeUtilTest, fromWeekOfMonthDate) { EXPECT_EQ(-430, daysSinceEpochLenient(1970, -13, 1, 1)); // Out of range year. - auto result = util::daysSinceEpochFromWeekOfMonthDate( - 292278995, 1, 1, 1, true); + auto result = + util::daysSinceEpochFromWeekOfMonthDate(292278995, 1, 1, 1, true); EXPECT_EQ(result.error().message(), "Date out of range: 292278995-1-1"); } From 0e9412c484304aafe92fa12211ead7425db9bc23 Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Fri, 23 Aug 2024 11:41:24 +0800 Subject: [PATCH 19/26] add ut for extractISODayOfTheWeek --- velox/type/tests/TimestampConversionTest.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index b8e8d8c5a9f8..6c8be4df1c98 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -161,6 +161,10 @@ TEST(DateTimeUtilTest, fromWeekOfMonthDate) { EXPECT_EQ(result.error().message(), "Date out of range: 292278995-1-1"); } +TEST(DateTimeUtilTest, extractISODayOfTheWeek) { + EXPECT_EQ(6, util::extractISODayOfTheWeek(int64_t(INT_MAX) + 1)); +} + TEST(DateTimeUtilTest, fromWeekOfMonthDateInvalid) { auto daysSinceEpochNonLenient = [](int32_t year, int32_t month, From 7a52b45ef54f6cfa491c2a16bd06a655f81fd59b Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Fri, 23 Aug 2024 17:33:38 +0800 Subject: [PATCH 20/26] update --- velox/type/tests/TimestampConversionTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index 6c8be4df1c98..1861330fc961 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -162,7 +162,7 @@ TEST(DateTimeUtilTest, fromWeekOfMonthDate) { } TEST(DateTimeUtilTest, extractISODayOfTheWeek) { - EXPECT_EQ(6, util::extractISODayOfTheWeek(int64_t(INT_MAX) + 1)); + EXPECT_EQ(4, util::extractISODayOfTheWeek(std::numeric_limits::max())); } TEST(DateTimeUtilTest, fromWeekOfMonthDateInvalid) { From 7d720171cd5bdef909dc1e7514002e67dd0b5003 Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Mon, 26 Aug 2024 14:18:34 +0800 Subject: [PATCH 21/26] update --- velox/type/TimestampConversion.cpp | 2 +- velox/type/tests/TimestampConversionTest.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/velox/type/TimestampConversion.cpp b/velox/type/TimestampConversion.cpp index 67ef7d0deda3..8b3c45046d3f 100644 --- a/velox/type/TimestampConversion.cpp +++ b/velox/type/TimestampConversion.cpp @@ -42,9 +42,9 @@ #include "velox/type/TimestampConversion.h" #include -#include "HugeInt.h" #include "velox/common/base/CheckedArithmetic.h" #include "velox/common/base/Exceptions.h" +#include "velox/type/HugeInt.h" #include "velox/type/tz/TimeZoneMap.h" namespace facebook::velox::util { diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index 1861330fc961..ce6a491d216e 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -162,7 +162,12 @@ TEST(DateTimeUtilTest, fromWeekOfMonthDate) { } TEST(DateTimeUtilTest, extractISODayOfTheWeek) { - EXPECT_EQ(4, util::extractISODayOfTheWeek(std::numeric_limits::max())); + EXPECT_EQ( + 4, util::extractISODayOfTheWeek(std::numeric_limits::max())); + EXPECT_EQ( + 3, util::extractISODayOfTheWeek(std::numeric_limits::min())); + EXPECT_EQ(1, util::extractISODayOfTheWeek(-10)); + EXPECT_EQ(7, util::extractISODayOfTheWeek(10)); } TEST(DateTimeUtilTest, fromWeekOfMonthDateInvalid) { From 3e2fb0c9a9a19180722f53bb334c2bbb65693f78 Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Thu, 29 Aug 2024 20:37:19 +0800 Subject: [PATCH 22/26] changes --- velox/type/TimestampConversion.cpp | 12 +-- velox/type/tests/TimestampConversionTest.cpp | 78 ++++++++++---------- 2 files changed, 46 insertions(+), 44 deletions(-) diff --git a/velox/type/TimestampConversion.cpp b/velox/type/TimestampConversion.cpp index 8b3c45046d3f..477fcb585be5 100644 --- a/velox/type/TimestampConversion.cpp +++ b/velox/type/TimestampConversion.cpp @@ -602,7 +602,11 @@ daysSinceEpochFromDate(int32_t year, int32_t month, int32_t day, int64_t& out) { int64_t daysSinceEpoch = 0; if (!isValidDate(year, month, day)) { - return Status::UserError("Date out of range: {}-{}-{}", year, month, day); + if (threadSkipErrorDetails()) { + return Status::UserError(); + } else { + return Status::UserError("Date out of range: {}-{}-{}", year, month, day); + } } while (year < 1970) { year += kYearInterval; @@ -677,11 +681,7 @@ Expected daysSinceEpochFromWeekOfMonthDate( const Status status = daysSinceEpochFromDate(year, month, 1, daysSinceEpochOfFirstDayOfMonth); if (!status.ok()) { - if (threadSkipErrorDetails()) { - return folly::makeUnexpected(Status::UserError()); - } else { - return folly::makeUnexpected(status); - } + return folly::makeUnexpected(status); } const int32_t firstDayOfWeek = extractISODayOfTheWeek(daysSinceEpochOfFirstDayOfMonth); diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index ce6a491d216e..b732524825e5 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -104,8 +104,8 @@ TEST(DateTimeUtilTest, fromDateInvalid) { 1970, 6, 31, "Date out of range: 1970-6-31")); } -TEST(DateTimeUtilTest, fromWeekOfMonthDate) { - auto daysSinceEpochLenient = +TEST(DateTimeUtilTest, daysSinceEpochFromWeekOfMonthDateLenient) { + auto daysSinceEpoch = [](int32_t year, int32_t month, int32_t weekOfMonth, int32_t dayOfWeek) { auto result = util::daysSinceEpochFromWeekOfMonthDate( year, month, weekOfMonth, dayOfWeek, true); @@ -113,47 +113,47 @@ TEST(DateTimeUtilTest, fromWeekOfMonthDate) { return result.value(); }; - EXPECT_EQ(4, daysSinceEpochLenient(1970, 1, 2, 1)); - EXPECT_EQ(361, daysSinceEpochLenient(1971, 1, 1, 1)); - EXPECT_EQ(396, daysSinceEpochLenient(1971, 2, 1, 1)); + EXPECT_EQ(4, daysSinceEpoch(1970, 1, 2, 1)); + EXPECT_EQ(361, daysSinceEpoch(1971, 1, 1, 1)); + EXPECT_EQ(396, daysSinceEpoch(1971, 2, 1, 1)); - EXPECT_EQ(10952, daysSinceEpochLenient(2000, 1, 1, 1)); - EXPECT_EQ(19905, daysSinceEpochLenient(2024, 7, 1, 1)); + EXPECT_EQ(10952, daysSinceEpoch(2000, 1, 1, 1)); + EXPECT_EQ(19905, daysSinceEpoch(2024, 7, 1, 1)); // Before unix epoch. - EXPECT_EQ(-3, daysSinceEpochLenient(1970, 1, 1, 1)); - EXPECT_EQ(-2, daysSinceEpochLenient(1970, 1, 1, 2)); - EXPECT_EQ(-31, daysSinceEpochLenient(1969, 12, 1, 1)); - EXPECT_EQ(-367, daysSinceEpochLenient(1969, 1, 1, 1)); - EXPECT_EQ(-724, daysSinceEpochLenient(1968, 1, 2, 1)); - EXPECT_EQ(-719533, daysSinceEpochLenient(0, 1, 1, 1)); + EXPECT_EQ(-3, daysSinceEpoch(1970, 1, 1, 1)); + EXPECT_EQ(-2, daysSinceEpoch(1970, 1, 1, 2)); + EXPECT_EQ(-31, daysSinceEpoch(1969, 12, 1, 1)); + EXPECT_EQ(-367, daysSinceEpoch(1969, 1, 1, 1)); + EXPECT_EQ(-724, daysSinceEpoch(1968, 1, 2, 1)); + EXPECT_EQ(-719533, daysSinceEpoch(0, 1, 1, 1)); // Negative year - BC. - EXPECT_EQ(-719561, daysSinceEpochLenient(-1, 12, 1, 1)); - EXPECT_EQ(-719897, daysSinceEpochLenient(-1, 1, 1, 1)); + EXPECT_EQ(-719561, daysSinceEpoch(-1, 12, 1, 1)); + EXPECT_EQ(-719897, daysSinceEpoch(-1, 1, 1, 1)); // Day in the previous month. - EXPECT_EQ(19783, daysSinceEpochLenient(2024, 2, 5, 5)); + EXPECT_EQ(19783, daysSinceEpoch(2024, 2, 5, 5)); // Day in the next month. - EXPECT_EQ(19751, daysSinceEpochLenient(2024, 2, 1, 1)); + EXPECT_EQ(19751, daysSinceEpoch(2024, 2, 1, 1)); // Out of range day of week. - EXPECT_EQ(338, daysSinceEpochLenient(1970, 12, 1, 0)); - EXPECT_EQ(337, daysSinceEpochLenient(1970, 12, 1, -1)); - EXPECT_EQ(337, daysSinceEpochLenient(1970, 12, 1, -8)); + EXPECT_EQ(338, daysSinceEpoch(1970, 12, 1, 0)); + EXPECT_EQ(337, daysSinceEpoch(1970, 12, 1, -1)); + EXPECT_EQ(337, daysSinceEpoch(1970, 12, 1, -8)); - EXPECT_EQ(332, daysSinceEpochLenient(1970, 12, 1, 8)); - EXPECT_EQ(333, daysSinceEpochLenient(1970, 12, 1, 9)); - EXPECT_EQ(336, daysSinceEpochLenient(1970, 12, 1, 19)); + EXPECT_EQ(332, daysSinceEpoch(1970, 12, 1, 8)); + EXPECT_EQ(333, daysSinceEpoch(1970, 12, 1, 9)); + EXPECT_EQ(336, daysSinceEpoch(1970, 12, 1, 19)); // Out of range month. - EXPECT_EQ(-3, daysSinceEpochLenient(1970, 1, 1, 1)); - EXPECT_EQ(207, daysSinceEpochLenient(1970, 8, 1, 1)); - EXPECT_EQ(361, daysSinceEpochLenient(1970, 13, 1, 1)); + EXPECT_EQ(-3, daysSinceEpoch(1970, 1, 1, 1)); + EXPECT_EQ(207, daysSinceEpoch(1970, 8, 1, 1)); + EXPECT_EQ(361, daysSinceEpoch(1970, 13, 1, 1)); - EXPECT_EQ(-31, daysSinceEpochLenient(1970, 0, 1, 1)); - EXPECT_EQ(-66, daysSinceEpochLenient(1970, -1, 1, 1)); - EXPECT_EQ(-430, daysSinceEpochLenient(1970, -13, 1, 1)); + EXPECT_EQ(-31, daysSinceEpoch(1970, 0, 1, 1)); + EXPECT_EQ(-66, daysSinceEpoch(1970, -1, 1, 1)); + EXPECT_EQ(-430, daysSinceEpoch(1970, -13, 1, 1)); // Out of range year. auto result = @@ -170,8 +170,8 @@ TEST(DateTimeUtilTest, extractISODayOfTheWeek) { EXPECT_EQ(7, util::extractISODayOfTheWeek(10)); } -TEST(DateTimeUtilTest, fromWeekOfMonthDateInvalid) { - auto daysSinceEpochNonLenient = [](int32_t year, +TEST(DateTimeUtilTest, daysSinceEpochFromWeekOfMonthDateNonLenient) { + auto daysSinceEpoch = [](int32_t year, int32_t month, int32_t weekOfMonth, int32_t dayOfWeek, @@ -182,20 +182,22 @@ TEST(DateTimeUtilTest, fromWeekOfMonthDateInvalid) { EXPECT_EQ(result.error().message(), error); }; + EXPECT_NO_THROW(daysSinceEpoch(-1, 1, 1, 1, "Date out of range: -1-1-1-1")); EXPECT_NO_THROW( - daysSinceEpochNonLenient(-1, 1, 1, 1, "Date out of range: -1-1-1-1")); - EXPECT_NO_THROW(daysSinceEpochNonLenient( + daysSinceEpoch( 292278995, 1, 1, 1, "Date out of range: 292278995-1-1-1")); EXPECT_NO_THROW( - daysSinceEpochNonLenient(2024, 0, 1, 1, "Date out of range: 2024-0-1-1")); - EXPECT_NO_THROW(daysSinceEpochNonLenient( + daysSinceEpoch(2024, 0, 1, 1, "Date out of range: 2024-0-1-1")); + EXPECT_NO_THROW( + daysSinceEpoch( 2024, 13, 1, 1, "Date out of range: 2024-13-1-1")); EXPECT_NO_THROW( - daysSinceEpochNonLenient(2024, 1, 6, 1, "Date out of range: 2024-1-6-1")); + daysSinceEpoch(2024, 1, 6, 1, "Date out of range: 2024-1-6-1")); EXPECT_NO_THROW( - daysSinceEpochNonLenient(2024, 2, 1, 1, "Date out of range: 2024-2-1-1")); + daysSinceEpoch(2024, 2, 1, 1, "Date out of range: 2024-2-1-1")); EXPECT_NO_THROW( - daysSinceEpochNonLenient(2024, 2, 5, 5, "Date out of range: 2024-2-5-5")); + daysSinceEpoch(2024, 2, 5, 5, "Date out of range: 2024-2-5-5")); + EXPECT_EQ(4, daysSinceEpochFromWeekOfMonthDate(1970, 1, 2, 1, false).value()); } TEST(DateTimeUtilTest, fromDateString) { From 0fcb1117eab4cddeeee43d722479ab06aa26222f Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Thu, 29 Aug 2024 20:40:00 +0800 Subject: [PATCH 23/26] changes --- velox/type/TimestampConversion.h | 16 ++++++++-------- velox/type/tests/TimestampConversionTest.cpp | 15 ++++++--------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/velox/type/TimestampConversion.h b/velox/type/TimestampConversion.h index 88a2f8485709..868bd11d94a8 100644 --- a/velox/type/TimestampConversion.h +++ b/velox/type/TimestampConversion.h @@ -121,17 +121,17 @@ Status daysSinceEpochFromWeekDate( /// count backward from December. For example, 13 corresponds to January of the /// following year and -1 corresponds to November of the previous year. /// @param weekOfMonth Week of the month. For non-lenient mode, it should be in -/// the range [1, 6]. For example, 1 is 1st week, 3 is 3rd week. For lenient -/// mode, we consider days of the previous or next months as part of the -/// specified weekOfMonth. For example, if weekOfMonth is 5 but the current +/// the range [1, depends on month]. For example, 1 is 1st week, 3 is 3rd week. +/// For lenient mode, we consider days of the previous or next months as part of +/// the specified weekOfMonth. For example, if weekOfMonth is 5 but the current /// month only has 4 weeks (such as February), the first week of March will be /// considered as the 5th week of February. /// @param dayOfWeek Day number of week. For non-lenient mode, it should be in -/// the range [1, 7]. For example, 1 is Monday, 7 is Sunday. For lenient mode, -/// we consider days of the previous or next months as part of the specified -/// dayOfWeek.For example, if weekOfMonth is 1 and dayOfWeek is 1 but the -/// month's first day is Saturday, the Monday of the last week of the previous -/// month will be used. +/// the range [1, depends on month]. For example, 1 is Monday, 7 is Sunday. For +/// lenient mode, we consider days of the previous or next months as part of the +/// specified dayOfWeek.For example, if weekOfMonth is 1 and dayOfWeek is 1 but +/// the month's first day is Saturday, the Monday of the last week of the +/// previous month will be used. Expected daysSinceEpochFromWeekOfMonthDate( int32_t year, int32_t month, diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index b732524825e5..6fc89248d788 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -172,25 +172,22 @@ TEST(DateTimeUtilTest, extractISODayOfTheWeek) { TEST(DateTimeUtilTest, daysSinceEpochFromWeekOfMonthDateNonLenient) { auto daysSinceEpoch = [](int32_t year, - int32_t month, - int32_t weekOfMonth, - int32_t dayOfWeek, - const std::string& error) { + int32_t month, + int32_t weekOfMonth, + int32_t dayOfWeek, + const std::string& error) { auto result = util::daysSinceEpochFromWeekOfMonthDate( year, month, weekOfMonth, dayOfWeek, false); EXPECT_TRUE(result.error().isUserError()); EXPECT_EQ(result.error().message(), error); }; - EXPECT_NO_THROW(daysSinceEpoch(-1, 1, 1, 1, "Date out of range: -1-1-1-1")); EXPECT_NO_THROW( - daysSinceEpoch( - 292278995, 1, 1, 1, "Date out of range: 292278995-1-1-1")); + daysSinceEpoch(292278995, 1, 1, 1, "Date out of range: 292278995-1-1-1")); EXPECT_NO_THROW( daysSinceEpoch(2024, 0, 1, 1, "Date out of range: 2024-0-1-1")); EXPECT_NO_THROW( - daysSinceEpoch( - 2024, 13, 1, 1, "Date out of range: 2024-13-1-1")); + daysSinceEpoch(2024, 13, 1, 1, "Date out of range: 2024-13-1-1")); EXPECT_NO_THROW( daysSinceEpoch(2024, 1, 6, 1, "Date out of range: 2024-1-6-1")); EXPECT_NO_THROW( From 0d29272654c04d7d7861fd9eb01a5c51d0244fd4 Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Fri, 30 Aug 2024 14:55:04 +0800 Subject: [PATCH 24/26] changes --- velox/type/TimestampConversion.h | 10 +++--- velox/type/tests/TimestampConversionTest.cpp | 34 ++++++++++++-------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/velox/type/TimestampConversion.h b/velox/type/TimestampConversion.h index 868bd11d94a8..24b736285b3a 100644 --- a/velox/type/TimestampConversion.h +++ b/velox/type/TimestampConversion.h @@ -109,12 +109,12 @@ Status daysSinceEpochFromWeekDate( /// Computes the signed number of days since the Unix epoch (1970-01-01). To /// align with Spark's SimpleDateFormat behavior, this function offers two -/// modes: lenient and non-lenient. For non-lenient mode, it returns an error -/// status if the date is invalid. For lenient mode, it accepts a wider range of -/// arguments. +/// modes: lenient and non-lenient. For non-lenient mode, dates before Jan 1, 1 +/// are not supported, and it returns an error status if the date is invalid. +/// For lenient mode, it accepts a wider range of arguments. /// @param year Year. For non-lenient mode, it should be in the range [1, -/// 292278994]. e.g: 1996, -2000. For lenient mode, values outside this range -/// could result in overflow. +/// 292278994]. e.g: 1996, 2024. For lenient mode, it should be in the range +/// [-292275055, 292278994]. /// @param month Month of year. For non-lenient mode, it should be in the range /// [1, 12]. For example, 1 is January, 7 is July. For lenient mode, values /// greater than 12 wrap around to the start of the year, and values less than 1 diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index 6fc89248d788..520d2d31365f 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -171,7 +171,7 @@ TEST(DateTimeUtilTest, extractISODayOfTheWeek) { } TEST(DateTimeUtilTest, daysSinceEpochFromWeekOfMonthDateNonLenient) { - auto daysSinceEpoch = [](int32_t year, + auto daysSinceEpochReturnError = [](int32_t year, int32_t month, int32_t weekOfMonth, int32_t dayOfWeek, @@ -182,19 +182,25 @@ TEST(DateTimeUtilTest, daysSinceEpochFromWeekOfMonthDateNonLenient) { EXPECT_EQ(result.error().message(), error); }; - EXPECT_NO_THROW( - daysSinceEpoch(292278995, 1, 1, 1, "Date out of range: 292278995-1-1-1")); - EXPECT_NO_THROW( - daysSinceEpoch(2024, 0, 1, 1, "Date out of range: 2024-0-1-1")); - EXPECT_NO_THROW( - daysSinceEpoch(2024, 13, 1, 1, "Date out of range: 2024-13-1-1")); - EXPECT_NO_THROW( - daysSinceEpoch(2024, 1, 6, 1, "Date out of range: 2024-1-6-1")); - EXPECT_NO_THROW( - daysSinceEpoch(2024, 2, 1, 1, "Date out of range: 2024-2-1-1")); - EXPECT_NO_THROW( - daysSinceEpoch(2024, 2, 5, 5, "Date out of range: 2024-2-5-5")); - EXPECT_EQ(4, daysSinceEpochFromWeekOfMonthDate(1970, 1, 2, 1, false).value()); + EXPECT_NO_THROW(daysSinceEpochReturnError(292278995, 1, 1, 1, "Date out of range: 292278995-1-1-1")); + EXPECT_NO_THROW(daysSinceEpochReturnError(2024, 0, 1, 1, "Date out of range: 2024-0-1-1")); + EXPECT_NO_THROW(daysSinceEpochReturnError(2024, 13, 1, 1, "Date out of range: 2024-13-1-1")); + EXPECT_NO_THROW(daysSinceEpochReturnError(2024, 1, 6, 1, "Date out of range: 2024-1-6-1")); + EXPECT_NO_THROW(daysSinceEpochReturnError(2024, 2, 1, 1, "Date out of range: 2024-2-1-1")); + EXPECT_NO_THROW(daysSinceEpochReturnError(2024, 2, 5, 5, "Date out of range: 2024-2-5-5")); + + auto daysSinceEpochReturnValues = + [](int32_t year, int32_t month, int32_t weekOfMonth, int32_t dayOfWeek) { + auto result = util::daysSinceEpochFromWeekOfMonthDate( + year, month, weekOfMonth, dayOfWeek, false); + EXPECT_TRUE(!result.hasError()); + return result.value(); + }; + + EXPECT_EQ(-724, daysSinceEpochReturnValues(1968, 1, 2, 1)); + EXPECT_EQ(4, daysSinceEpochReturnValues(1970, 1, 2, 1)); + EXPECT_EQ(396, daysSinceEpochReturnValues(1971, 2, 1, 1)); + EXPECT_EQ(19905, daysSinceEpochReturnValues(2024, 7, 1, 1)); } TEST(DateTimeUtilTest, fromDateString) { From 9267d21b405cb161a69883d622149b45ec66d80b Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Fri, 30 Aug 2024 14:56:57 +0800 Subject: [PATCH 25/26] reformat --- velox/type/tests/TimestampConversionTest.cpp | 26 ++++++++++++-------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index 520d2d31365f..3922e983e5ec 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -172,22 +172,28 @@ TEST(DateTimeUtilTest, extractISODayOfTheWeek) { TEST(DateTimeUtilTest, daysSinceEpochFromWeekOfMonthDateNonLenient) { auto daysSinceEpochReturnError = [](int32_t year, - int32_t month, - int32_t weekOfMonth, - int32_t dayOfWeek, - const std::string& error) { + int32_t month, + int32_t weekOfMonth, + int32_t dayOfWeek, + const std::string& error) { auto result = util::daysSinceEpochFromWeekOfMonthDate( year, month, weekOfMonth, dayOfWeek, false); EXPECT_TRUE(result.error().isUserError()); EXPECT_EQ(result.error().message(), error); }; - EXPECT_NO_THROW(daysSinceEpochReturnError(292278995, 1, 1, 1, "Date out of range: 292278995-1-1-1")); - EXPECT_NO_THROW(daysSinceEpochReturnError(2024, 0, 1, 1, "Date out of range: 2024-0-1-1")); - EXPECT_NO_THROW(daysSinceEpochReturnError(2024, 13, 1, 1, "Date out of range: 2024-13-1-1")); - EXPECT_NO_THROW(daysSinceEpochReturnError(2024, 1, 6, 1, "Date out of range: 2024-1-6-1")); - EXPECT_NO_THROW(daysSinceEpochReturnError(2024, 2, 1, 1, "Date out of range: 2024-2-1-1")); - EXPECT_NO_THROW(daysSinceEpochReturnError(2024, 2, 5, 5, "Date out of range: 2024-2-5-5")); + EXPECT_NO_THROW(daysSinceEpochReturnError( + 292278995, 1, 1, 1, "Date out of range: 292278995-1-1-1")); + EXPECT_NO_THROW(daysSinceEpochReturnError( + 2024, 0, 1, 1, "Date out of range: 2024-0-1-1")); + EXPECT_NO_THROW(daysSinceEpochReturnError( + 2024, 13, 1, 1, "Date out of range: 2024-13-1-1")); + EXPECT_NO_THROW(daysSinceEpochReturnError( + 2024, 1, 6, 1, "Date out of range: 2024-1-6-1")); + EXPECT_NO_THROW(daysSinceEpochReturnError( + 2024, 2, 1, 1, "Date out of range: 2024-2-1-1")); + EXPECT_NO_THROW(daysSinceEpochReturnError( + 2024, 2, 5, 5, "Date out of range: 2024-2-5-5")); auto daysSinceEpochReturnValues = [](int32_t year, int32_t month, int32_t weekOfMonth, int32_t dayOfWeek) { From 935bab1f0287403acf155cde421eb457d7b90aa4 Mon Sep 17 00:00:00 2001 From: NEUpanning Date: Tue, 3 Sep 2024 15:10:43 +0800 Subject: [PATCH 26/26] non-lenient -> strict --- velox/type/TimestampConversion.h | 10 +++++----- velox/type/tests/TimestampConversionTest.cpp | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/velox/type/TimestampConversion.h b/velox/type/TimestampConversion.h index 24b736285b3a..1a621f624391 100644 --- a/velox/type/TimestampConversion.h +++ b/velox/type/TimestampConversion.h @@ -109,24 +109,24 @@ Status daysSinceEpochFromWeekDate( /// Computes the signed number of days since the Unix epoch (1970-01-01). To /// align with Spark's SimpleDateFormat behavior, this function offers two -/// modes: lenient and non-lenient. For non-lenient mode, dates before Jan 1, 1 +/// modes: lenient and strict. For strict mode, dates before Jan 1, 1 /// are not supported, and it returns an error status if the date is invalid. /// For lenient mode, it accepts a wider range of arguments. -/// @param year Year. For non-lenient mode, it should be in the range [1, +/// @param year Year. For strict mode, it should be in the range [1, /// 292278994]. e.g: 1996, 2024. For lenient mode, it should be in the range /// [-292275055, 292278994]. -/// @param month Month of year. For non-lenient mode, it should be in the range +/// @param month Month of year. For strict mode, it should be in the range /// [1, 12]. For example, 1 is January, 7 is July. For lenient mode, values /// greater than 12 wrap around to the start of the year, and values less than 1 /// count backward from December. For example, 13 corresponds to January of the /// following year and -1 corresponds to November of the previous year. -/// @param weekOfMonth Week of the month. For non-lenient mode, it should be in +/// @param weekOfMonth Week of the month. For strict mode, it should be in /// the range [1, depends on month]. For example, 1 is 1st week, 3 is 3rd week. /// For lenient mode, we consider days of the previous or next months as part of /// the specified weekOfMonth. For example, if weekOfMonth is 5 but the current /// month only has 4 weeks (such as February), the first week of March will be /// considered as the 5th week of February. -/// @param dayOfWeek Day number of week. For non-lenient mode, it should be in +/// @param dayOfWeek Day number of week. For strict mode, it should be in /// the range [1, depends on month]. For example, 1 is Monday, 7 is Sunday. For /// lenient mode, we consider days of the previous or next months as part of the /// specified dayOfWeek.For example, if weekOfMonth is 1 and dayOfWeek is 1 but diff --git a/velox/type/tests/TimestampConversionTest.cpp b/velox/type/tests/TimestampConversionTest.cpp index 3922e983e5ec..77b9d39e20a1 100644 --- a/velox/type/tests/TimestampConversionTest.cpp +++ b/velox/type/tests/TimestampConversionTest.cpp @@ -170,7 +170,7 @@ TEST(DateTimeUtilTest, extractISODayOfTheWeek) { EXPECT_EQ(7, util::extractISODayOfTheWeek(10)); } -TEST(DateTimeUtilTest, daysSinceEpochFromWeekOfMonthDateNonLenient) { +TEST(DateTimeUtilTest, daysSinceEpochFromWeekOfMonthDateStrict) { auto daysSinceEpochReturnError = [](int32_t year, int32_t month, int32_t weekOfMonth,