diff --git a/ProgressOfTesting.txt b/ProgressOfTesting.txt index 2f81ee2..e757a12 100644 --- a/ProgressOfTesting.txt +++ b/ProgressOfTesting.txt @@ -1,6 +1,6 @@ [ ] 未开始测试 - 15 (21.43%) -[-] 测试未完成 - 11 (15.71%) -[Y] 测试完成 - 23 (32.86%) +[-] 测试未完成 - 10 (14.29%) +[Y] 测试完成 - 24 (34.29%) [x] 无需测试 - 21 (30.00%) xyz.zhouxy.plusone.commons @@ -80,7 +80,7 @@ xyz.zhouxy.plusone.commons │ ├───time │ Quarter.java [Y] - │ YearQuarter.java [-] + │ YearQuarter.java [Y] │ └───util ArrayTools.java [-] diff --git a/src/main/java/xyz/zhouxy/plusone/commons/time/Quarter.java b/src/main/java/xyz/zhouxy/plusone/commons/time/Quarter.java index 71efd48..279ca23 100644 --- a/src/main/java/xyz/zhouxy/plusone/commons/time/Quarter.java +++ b/src/main/java/xyz/zhouxy/plusone/commons/time/Quarter.java @@ -16,6 +16,7 @@ package xyz.zhouxy.plusone.commons.time; +import java.time.DateTimeException; import java.time.Month; import java.time.MonthDay; import java.time.temporal.ChronoField; @@ -171,7 +172,8 @@ public enum Quarter implements IWithIntCode { // Getters end public static int checkValidIntValue(int value) { - AssertTools.checkArgument(value >= 1 && value <= 4, () -> "Invalid value for Quarter: " + value); + AssertTools.checkCondition(value >= 1 && value <= 4, + () -> new DateTimeException("Invalid value for Quarter: " + value)); return value; } diff --git a/src/main/java/xyz/zhouxy/plusone/commons/time/YearQuarter.java b/src/main/java/xyz/zhouxy/plusone/commons/time/YearQuarter.java index 7fd4885..947b065 100644 --- a/src/main/java/xyz/zhouxy/plusone/commons/time/YearQuarter.java +++ b/src/main/java/xyz/zhouxy/plusone/commons/time/YearQuarter.java @@ -22,6 +22,7 @@ import java.io.Serializable; import java.time.LocalDate; import java.time.Month; import java.time.YearMonth; +import java.time.temporal.ChronoField; import java.util.Calendar; import java.util.Date; import java.util.Objects; @@ -52,7 +53,6 @@ public final class YearQuarter implements Comparable, Serializable private final LocalDate lastDate; private YearQuarter(int year, @Nonnull Quarter quarter) { - AssertTools.checkNotNull(quarter, "Quarter can not be null."); this.year = year; this.quarter = quarter; this.firstDate = quarter.firstMonthDay().atYear(year); @@ -70,7 +70,7 @@ public final class YearQuarter implements Comparable, Serializable */ @StaticFactoryMethod(YearQuarter.class) public static YearQuarter of(int year, int quarter) { - return of(year, Quarter.of(quarter)); + return new YearQuarter(YEAR.checkValidIntValue(year), Quarter.of(quarter)); } /** @@ -81,8 +81,8 @@ public final class YearQuarter implements Comparable, Serializable * @return {@link YearQuarter} 实例 */ @StaticFactoryMethod(YearQuarter.class) - public static YearQuarter of(int year, @Nonnull Quarter quarter) { - return new YearQuarter(year, quarter); + public static YearQuarter of(int year, Quarter quarter) { + return new YearQuarter(YEAR.checkValidIntValue(year), Objects.requireNonNull(quarter)); } /** @@ -92,8 +92,9 @@ public final class YearQuarter implements Comparable, Serializable * @return {@link YearQuarter} 实例 */ @StaticFactoryMethod(YearQuarter.class) - public static YearQuarter of(@Nonnull LocalDate date) { - return of(date.getYear(), Quarter.fromMonth(date.getMonth())); + public static YearQuarter of(LocalDate date) { + AssertTools.checkNotNull(date); + return new YearQuarter(date.getYear(), Quarter.fromMonth(date.getMonth())); } /** @@ -103,12 +104,13 @@ public final class YearQuarter implements Comparable, Serializable * @return {@link YearQuarter} 实例 */ @StaticFactoryMethod(YearQuarter.class) - public static YearQuarter of(@Nonnull Date date) { + public static YearQuarter of(Date date) { + AssertTools.checkNotNull(date); @SuppressWarnings("deprecation") - final int year = date.getYear() + 1900; + final int yearValue = YEAR.checkValidIntValue(date.getYear() + 1900L); @SuppressWarnings("deprecation") - final int month = date.getMonth() + 1; - return of(year, Quarter.fromMonth(month)); + final int monthValue = date.getMonth() + 1; + return new YearQuarter(yearValue, Quarter.fromMonth(monthValue)); } /** @@ -119,7 +121,10 @@ public final class YearQuarter implements Comparable, Serializable */ @StaticFactoryMethod(YearQuarter.class) public static YearQuarter of(Calendar date) { - return of(date.get(Calendar.YEAR), Quarter.fromMonth(date.get(Calendar.MONTH) + 1)); + AssertTools.checkNotNull(date); + final int yearValue = ChronoField.YEAR.checkValidIntValue(date.get(Calendar.YEAR)); + final int monthValue = date.get(Calendar.MONTH) + 1; + return new YearQuarter(yearValue, Quarter.fromMonth(monthValue)); } /** @@ -130,9 +135,15 @@ public final class YearQuarter implements Comparable, Serializable */ @StaticFactoryMethod(YearQuarter.class) public static YearQuarter of(YearMonth yearMonth) { + AssertTools.checkNotNull(yearMonth); return of(yearMonth.getYear(), Quarter.fromMonth(yearMonth.getMonth())); } + @StaticFactoryMethod(YearQuarter.class) + public static YearQuarter now() { + return of(LocalDate.now()); + } + // #endregion // #region - Getters @@ -185,7 +196,7 @@ public final class YearQuarter implements Comparable, Serializable // #region - computes - public YearQuarter plusQuarters(long quartersToAdd) { // TODO 单元测试 + public YearQuarter plusQuarters(long quartersToAdd) { if (quartersToAdd == 0L) { return this; } @@ -193,27 +204,27 @@ public final class YearQuarter implements Comparable, Serializable long calcQuarters = quarterCount + quartersToAdd; // safe overflow int newYear = YEAR.checkValidIntValue(Math.floorDiv(calcQuarters, 4)); int newQuarter = (int) Math.floorMod(calcQuarters, 4) + 1; - return of(newYear, Quarter.of(newQuarter)); + return new YearQuarter(newYear, Quarter.of(newQuarter)); } - public YearQuarter minusQuarters(long quartersToAdd) { // TODO 单元测试 + public YearQuarter minusQuarters(long quartersToAdd) { return plusQuarters(-quartersToAdd); } - public YearQuarter nextQuarter() { // TODO 单元测试 + public YearQuarter nextQuarter() { return plusQuarters(1L); } - public YearQuarter lastQuarter() { // TODO 单元测试 + public YearQuarter lastQuarter() { return minusQuarters(1L); } - public YearQuarter plusYears(long yearsToAdd) { // TODO 单元测试 + public YearQuarter plusYears(long yearsToAdd) { if (yearsToAdd == 0L) { return this; } int newYear = YEAR.checkValidIntValue(this.year + yearsToAdd); // safe overflow - return of(newYear, this.quarter); + return new YearQuarter(newYear, this.quarter); } public YearQuarter minusYears(long yearsToAdd) { @@ -270,11 +281,11 @@ public final class YearQuarter implements Comparable, Serializable return this.compareTo(other) > 0; } - public static YearQuarter min(YearQuarter yearQuarter1, YearQuarter yearQuarter2) { // TODO 单元测试 + public static YearQuarter min(YearQuarter yearQuarter1, YearQuarter yearQuarter2) { return yearQuarter1.compareTo(yearQuarter2) <= 0 ? yearQuarter1 : yearQuarter2; } - public static YearQuarter max(YearQuarter yearQuarter1, YearQuarter yearQuarter2) { // TODO 单元测试 + public static YearQuarter max(YearQuarter yearQuarter1, YearQuarter yearQuarter2) { return yearQuarter1.compareTo(yearQuarter2) >= 0 ? yearQuarter1 : yearQuarter2; } diff --git a/src/test/java/xyz/zhouxy/plusone/commons/time/QuarterTests.java b/src/test/java/xyz/zhouxy/plusone/commons/time/QuarterTests.java index 75f583f..976ccc7 100644 --- a/src/test/java/xyz/zhouxy/plusone/commons/time/QuarterTests.java +++ b/src/test/java/xyz/zhouxy/plusone/commons/time/QuarterTests.java @@ -18,6 +18,7 @@ package xyz.zhouxy.plusone.commons.time; import static org.junit.jupiter.api.Assertions.*; +import java.time.DateTimeException; import java.time.Month; import java.time.MonthDay; @@ -37,7 +38,7 @@ class QuarterTests { assertEquals(1, quarter.getValue()); assertEquals("Q1", quarter.name()); - assertThrows(IllegalArgumentException.class, () -> { + assertThrows(DateTimeException.class, () -> { Quarter.of(0); }); @@ -84,7 +85,7 @@ class QuarterTests { assertEquals(2, quarter.getValue()); assertEquals("Q2", quarter.name()); - assertThrows(IllegalArgumentException.class, () -> { + assertThrows(DateTimeException.class, () -> { Quarter.of(5); }); diff --git a/src/test/java/xyz/zhouxy/plusone/commons/time/YearQuarterTests.java b/src/test/java/xyz/zhouxy/plusone/commons/time/YearQuarterTests.java index 0e63de8..fcb14a6 100644 --- a/src/test/java/xyz/zhouxy/plusone/commons/time/YearQuarterTests.java +++ b/src/test/java/xyz/zhouxy/plusone/commons/time/YearQuarterTests.java @@ -21,66 +21,775 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import lombok.extern.slf4j.Slf4j; +import java.time.DateTimeException; import java.time.LocalDate; +import java.time.Month; +import java.time.Year; import java.time.YearMonth; - +import java.util.Calendar; +import java.util.Date; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @Slf4j public class YearQuarterTests { - @Test - void of_ValidYearAndQuarter_CreatesYearQuarter() { - int year = 2023; - Quarter quarter = Quarter.Q1; + // ================================ + // #region - of(int year, int quarter) + // ================================ - YearQuarter expected = YearQuarter.of(year, quarter); - YearQuarter actual = YearQuarter.of(LocalDate.of(year, 2, 28)); + @ParameterizedTest + @ValueSource(ints = { 1, 2, 3, 4 }) + void of_ValidYearAndQuarterValue_CreatesYearQuarter(int quarter) { + { + int year = 2024; + YearQuarter yearQuarter = YearQuarter.of(year, quarter); + log.info("{}", yearQuarter); + assertEquals(year, yearQuarter.getYear()); + assertEquals(Quarter.of(quarter), yearQuarter.getQuarter()); + assertEquals(quarter, yearQuarter.getQuarterValue()); + } + { + int year = Year.MIN_VALUE; + YearQuarter yearQuarter = YearQuarter.of(year, quarter); + assertEquals(year, yearQuarter.getYear()); + assertEquals(Quarter.of(quarter), yearQuarter.getQuarter()); + assertEquals(quarter, yearQuarter.getQuarterValue()); + } + { + int year = Year.MAX_VALUE; + YearQuarter yearQuarter = YearQuarter.of(year, quarter); + assertEquals(year, yearQuarter.getYear()); + assertEquals(Quarter.of(quarter), yearQuarter.getQuarter()); + assertEquals(quarter, yearQuarter.getQuarterValue()); + } + } - assertEquals(expected, actual); + @ParameterizedTest + @ValueSource(ints = { -1, 0, 5, 108 }) + void of_ValidYearAndInvalidQuarterValue_DateTimeException(int quarter) { + int year = 2024; + assertThrows(DateTimeException.class, () -> { + YearQuarter.of(year, quarter); + }); + } - assertEquals("2023 Q1", actual.toString()); + @ParameterizedTest + @ValueSource(ints = { Year.MIN_VALUE - 1, Year.MAX_VALUE + 1 }) + void of_InvalidYearAndValidQuarterValue_DateTimeException(int year) { + assertThrows(DateTimeException.class, () -> { + YearQuarter.of(year, 1); + }); + assertThrows(DateTimeException.class, () -> { + YearQuarter.of(year, 2); + }); + assertThrows(DateTimeException.class, () -> { + YearQuarter.of(year, 3); + }); + assertThrows(DateTimeException.class, () -> { + YearQuarter.of(year, 4); + }); } @Test - @SuppressWarnings("null") - void of_InvalidQuarter_ThrowsNullPointerException() { - int year = 2023; - Quarter quarter = null; - - assertThrows(NullPointerException.class, () -> YearQuarter.of(year, quarter)); - } - - @Test - void of_ValidYearQuarter_GetsCorrectStartAndEndDate() { - - for (int year = 1990; year <= 2024; year++) { - for (int quarterValue = 1; quarterValue <= 4; quarterValue++) { - Quarter quarter = Quarter.of(quarterValue); - YearQuarter yearQuarter = YearQuarter.of(year, quarter); - - LocalDate expectedStartDate = quarter.firstMonthDay().atYear(year); - log.info("{} - expectedStartDate: {}", yearQuarter, expectedStartDate); - LocalDate expectedEndDate = quarter.lastMonthDay().atYear(year); - log.info("{} - expectedEndDate: {}", yearQuarter, expectedEndDate); - - assertEquals(expectedStartDate, yearQuarter.firstDate()); - assertEquals(expectedEndDate, yearQuarter.lastDate()); + void of_InvalidYearAndInvalidQuarterValue_DateTimeException() { + final int[] years = { Year.MIN_VALUE - 1, Year.MAX_VALUE + 1 }; + final int[] quarters = { -1, 0, 5, 108 }; + for (int year : years) { + final int yearValue = year; + for (int quarter : quarters) { + final int quarterValue = quarter; + assertThrows(DateTimeException.class, + () -> YearQuarter.of(yearValue, quarterValue)); } } } + // ================================ + // #endregion - of(int year, int quarter) + // ================================ + + // ================================ + // #region - of(int year, Quarter quarter) + // ================================ + + @ParameterizedTest + @ValueSource(ints = { 1, 2, 3, 4 }) + void of_ValidYearAndQuarter_CreatesYearQuarter(int quarterValue) { + { + int year = 2024; + Quarter quarter = Quarter.of(quarterValue); + YearQuarter yearQuarter = YearQuarter.of(year, quarter); + log.info("{}", yearQuarter); + assertEquals(year, yearQuarter.getYear()); + assertEquals(quarter, yearQuarter.getQuarter()); + assertEquals(quarterValue, yearQuarter.getQuarterValue()); + } + { + int year = Year.MIN_VALUE; + Quarter quarter = Quarter.of(quarterValue); + YearQuarter yearQuarter = YearQuarter.of(year, quarter); + assertEquals(year, yearQuarter.getYear()); + assertEquals(quarter, yearQuarter.getQuarter()); + assertEquals(quarterValue, yearQuarter.getQuarterValue()); + } + { + int year = Year.MAX_VALUE; + Quarter quarter = Quarter.of(quarterValue); + YearQuarter yearQuarter = YearQuarter.of(year, quarter); + assertEquals(year, yearQuarter.getYear()); + assertEquals(quarter, yearQuarter.getQuarter()); + assertEquals(quarterValue, yearQuarter.getQuarterValue()); + } + } + + @Test + void of_ValidYearAndNullQuarter_NullPointerException() { + int year = 2024; + assertThrows(NullPointerException.class, () -> { + YearQuarter.of(year, null); + }); + } + + @ParameterizedTest + @ValueSource(ints = { Year.MIN_VALUE - 1, Year.MAX_VALUE + 1 }) + void of_InvalidYearAndValidQuarter_DateTimeException(int year) { + assertThrows(DateTimeException.class, () -> { + YearQuarter.of(year, Quarter.Q1); + }); + assertThrows(DateTimeException.class, () -> { + YearQuarter.of(year, Quarter.Q2); + }); + assertThrows(DateTimeException.class, () -> { + YearQuarter.of(year, Quarter.Q3); + }); + assertThrows(DateTimeException.class, () -> { + YearQuarter.of(year, Quarter.Q4); + }); + } + + @Test + void of_InvalidYearAndNullQuarter_DateTimeException() { + final int[] years = { Year.MIN_VALUE - 1, Year.MAX_VALUE + 1 }; + for (int year : years) { + final int yearValue = year; + assertThrows(DateTimeException.class, + () -> YearQuarter.of(yearValue, null)); + + } + } + + // ================================ + // #endregion - of(int year, Quarter quarter) + // ================================ + + // ================================ + // #region - of(LocalDate date) + // ================================ + + @ParameterizedTest + @ValueSource(ints = { + 2023, // 非闰年 + 2024, // 闰年 + Year.MIN_VALUE, + Year.MAX_VALUE, + }) + void of_ValidLocalDate_CreatesYearQuarter_Q1(int year) { + { + LocalDate date = YearMonth.of(year, 1).atDay(1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(1, yq.getQuarterValue()); + assertSame(Quarter.Q1, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 1).atEndOfMonth(); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(1, yq.getQuarterValue()); + assertSame(Quarter.Q1, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 2).atDay(1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(1, yq.getQuarterValue()); + assertSame(Quarter.Q1, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 2).atEndOfMonth(); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(1, yq.getQuarterValue()); + assertSame(Quarter.Q1, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 3).atDay(1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(1, yq.getQuarterValue()); + assertSame(Quarter.Q1, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 3).atEndOfMonth(); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(1, yq.getQuarterValue()); + assertSame(Quarter.Q1, yq.getQuarter()); + } + } + @ParameterizedTest @ValueSource(ints = { - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, - 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, - 2020, 2021, 2022, 2023, 2024 + 2023, // 非闰年 + 2024, // 闰年 + Year.MIN_VALUE, + Year.MAX_VALUE, }) - void testFirstYearMonth(int year) { + void of_ValidLocalDate_CreatesYearQuarter_Q2(int year) { + { + LocalDate date = YearMonth.of(year, 4).atDay(1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(2, yq.getQuarterValue()); + assertSame(Quarter.Q2, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 4).atEndOfMonth(); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(2, yq.getQuarterValue()); + assertSame(Quarter.Q2, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 5).atDay(1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(2, yq.getQuarterValue()); + assertSame(Quarter.Q2, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 5).atEndOfMonth(); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(2, yq.getQuarterValue()); + assertSame(Quarter.Q2, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 6).atDay(1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(2, yq.getQuarterValue()); + assertSame(Quarter.Q2, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 6).atEndOfMonth(); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(2, yq.getQuarterValue()); + assertSame(Quarter.Q2, yq.getQuarter()); + } + } + + @ParameterizedTest + @ValueSource(ints = { + 2023, // 非闰年 + 2024, // 闰年 + Year.MIN_VALUE, + Year.MAX_VALUE, + }) + void of_ValidLocalDate_CreatesYearQuarter_Q3(int year) { + { + LocalDate date = YearMonth.of(year, 7).atDay(1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(3, yq.getQuarterValue()); + assertSame(Quarter.Q3, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 7).atEndOfMonth(); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(3, yq.getQuarterValue()); + assertSame(Quarter.Q3, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 8).atDay(1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(3, yq.getQuarterValue()); + assertSame(Quarter.Q3, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 8).atEndOfMonth(); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(3, yq.getQuarterValue()); + assertSame(Quarter.Q3, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 9).atDay(1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(3, yq.getQuarterValue()); + assertSame(Quarter.Q3, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 9).atEndOfMonth(); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(3, yq.getQuarterValue()); + assertSame(Quarter.Q3, yq.getQuarter()); + } + } + + @ParameterizedTest + @ValueSource(ints = { + 2023, // 非闰年 + 2024, // 闰年 + Year.MIN_VALUE, + Year.MAX_VALUE, + }) + void of_ValidLocalDate_CreatesYearQuarter_Q4(int year) { + { + LocalDate date = YearMonth.of(year, 10).atDay(1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(4, yq.getQuarterValue()); + assertSame(Quarter.Q4, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 10).atEndOfMonth(); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(4, yq.getQuarterValue()); + assertSame(Quarter.Q4, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 11).atDay(1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(4, yq.getQuarterValue()); + assertSame(Quarter.Q4, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 11).atEndOfMonth(); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(4, yq.getQuarterValue()); + assertSame(Quarter.Q4, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 12).atDay(1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(4, yq.getQuarterValue()); + assertSame(Quarter.Q4, yq.getQuarter()); + } + { + LocalDate date = YearMonth.of(year, 12).atEndOfMonth(); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(4, yq.getQuarterValue()); + assertSame(Quarter.Q4, yq.getQuarter()); + } + } + + @Test + void of_NullLocalDate_NullPointerException() { + LocalDate date = null; + assertThrows(NullPointerException.class, () -> { + YearQuarter.of(date); + }); + } + + // ================================ + // #endregion - of(LocalDate date) + // ================================ + + // ================================ + // #region - of(Date date) + // ================================ + + @SuppressWarnings("deprecation") + @ParameterizedTest + @ValueSource(ints = { + 2023, // 非闰年 + 2024, // 闰年 + 1, + 999999, + }) + void of_ValidDate_CreatesYearQuarter(int year) { + { + Date date = new Date(year - 1900, 1 - 1, 1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(1, yq.getQuarterValue()); + assertSame(Quarter.Q1, yq.getQuarter()); + } + { + Date date = new Date(year - 1900, 3 - 1, 31, 23, 59, 59); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(1, yq.getQuarterValue()); + assertSame(Quarter.Q1, yq.getQuarter()); + } + { + Date date = new Date(year - 1900, 4 - 1, 1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(2, yq.getQuarterValue()); + assertSame(Quarter.Q2, yq.getQuarter()); + } + { + Date date = new Date(year - 1900, 6 - 1, 30, 23, 59, 59); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(2, yq.getQuarterValue()); + assertSame(Quarter.Q2, yq.getQuarter()); + } + { + Date date = new Date(year - 1900, 7 - 1, 1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(3, yq.getQuarterValue()); + assertSame(Quarter.Q3, yq.getQuarter()); + } + { + Date date = new Date(year - 1900, 9 - 1, 30, 23, 59, 59); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(3, yq.getQuarterValue()); + assertSame(Quarter.Q3, yq.getQuarter()); + } + { + Date date = new Date(year - 1900, 10 - 1, 1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(4, yq.getQuarterValue()); + assertSame(Quarter.Q4, yq.getQuarter()); + } + { + Date date = new Date(year - 1900, 12 - 1, 31, 23, 59, 59); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(4, yq.getQuarterValue()); + assertSame(Quarter.Q4, yq.getQuarter()); + } + } + + @Test + void of_NullDate_NullPointerException() { + Date date = null; + assertThrows(NullPointerException.class, () -> { + YearQuarter.of(date); + }); + } + + // ================================ + // #endregion - of(Date date) + // ================================ + + // ================================ + // #region - of(Calendar date) + // ================================ + + @ParameterizedTest + @ValueSource(ints = { + 2023, // 非闰年 + 2024, // 闰年 + 1, + 999999, + }) + void of_ValidCalendar_CreatesYearQuarter(int year) { + Calendar date = Calendar.getInstance(); + { + date.set(year, 1 - 1, 1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(1, yq.getQuarterValue()); + assertSame(Quarter.Q1, yq.getQuarter()); + } + { + date.set(year, 3 - 1, 31, 23, 59, 59); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(1, yq.getQuarterValue()); + assertSame(Quarter.Q1, yq.getQuarter()); + } + { + date.set(year, 4 - 1, 1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(2, yq.getQuarterValue()); + assertSame(Quarter.Q2, yq.getQuarter()); + } + { + date.set(year, 6 - 1, 30, 23, 59, 59); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(2, yq.getQuarterValue()); + assertSame(Quarter.Q2, yq.getQuarter()); + } + { + date.set(year, 7 - 1, 1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(3, yq.getQuarterValue()); + assertSame(Quarter.Q3, yq.getQuarter()); + } + { + date.set(year, 9 - 1, 30, 23, 59, 59); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(3, yq.getQuarterValue()); + assertSame(Quarter.Q3, yq.getQuarter()); + } + { + date.set(year, 10 - 1, 1); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(4, yq.getQuarterValue()); + assertSame(Quarter.Q4, yq.getQuarter()); + } + { + date.set(year, 12 - 1, 31, 23, 59, 59); + YearQuarter yq = YearQuarter.of(date); + assertEquals(year, yq.getYear()); + assertEquals(4, yq.getQuarterValue()); + assertSame(Quarter.Q4, yq.getQuarter()); + } + } + + @Test + void of_NullCalendar_NullPointerException() { + Calendar date = null; + assertThrows(NullPointerException.class, () -> { + YearQuarter.of(date); + }); + } + + // ================================ + // #endregion - of(Calendar date) + // ================================ + + // ================================ + // #region - of(YearMonth yearMonth) + // ================================ + + @ParameterizedTest + @ValueSource(ints = { + 2023, // 非闰年 + 2024, // 闰年 + Year.MIN_VALUE, + Year.MAX_VALUE, + }) + void of_ValidYearMonth_CreatesYearMnoth_Q1(int year) { + { + YearMonth yearMonth = YearMonth.of(year, 1); + YearQuarter yearQuarter = YearQuarter.of(yearMonth); + assertEquals(year, yearQuarter.getYear()); + assertEquals(1, yearQuarter.getQuarterValue()); + assertSame(Quarter.Q1, yearQuarter.getQuarter()); + } + { + YearMonth yearMonth = YearMonth.of(year, 2); + YearQuarter yearQuarter = YearQuarter.of(yearMonth); + assertEquals(year, yearQuarter.getYear()); + assertEquals(1, yearQuarter.getQuarterValue()); + assertSame(Quarter.Q1, yearQuarter.getQuarter()); + } + { + YearMonth yearMonth = YearMonth.of(year, 3); + YearQuarter yearQuarter = YearQuarter.of(yearMonth); + assertEquals(year, yearQuarter.getYear()); + assertEquals(1, yearQuarter.getQuarterValue()); + assertSame(Quarter.Q1, yearQuarter.getQuarter()); + } + } + + @ParameterizedTest + @ValueSource(ints = { + 2023, // 非闰年 + 2024, // 闰年 + Year.MIN_VALUE, + Year.MAX_VALUE, + }) + void of_ValidYearMonth_CreatesYearMnoth_Q2(int year) { + { + YearMonth yearMonth = YearMonth.of(year, 4); + YearQuarter yearQuarter = YearQuarter.of(yearMonth); + assertEquals(year, yearQuarter.getYear()); + assertEquals(2, yearQuarter.getQuarterValue()); + assertSame(Quarter.Q2, yearQuarter.getQuarter()); + } + { + YearMonth yearMonth = YearMonth.of(year, 5); + YearQuarter yearQuarter = YearQuarter.of(yearMonth); + assertEquals(year, yearQuarter.getYear()); + assertEquals(2, yearQuarter.getQuarterValue()); + assertSame(Quarter.Q2, yearQuarter.getQuarter()); + } + { + YearMonth yearMonth = YearMonth.of(year, 6); + YearQuarter yearQuarter = YearQuarter.of(yearMonth); + assertEquals(year, yearQuarter.getYear()); + assertEquals(2, yearQuarter.getQuarterValue()); + assertSame(Quarter.Q2, yearQuarter.getQuarter()); + } + } + + @ParameterizedTest + @ValueSource(ints = { + 2023, // 非闰年 + 2024, // 闰年 + Year.MIN_VALUE, + Year.MAX_VALUE, + }) + void of_ValidYearMonth_CreatesYearMnoth_Q3(int year) { + { + YearMonth yearMonth = YearMonth.of(year, 7); + YearQuarter yearQuarter = YearQuarter.of(yearMonth); + assertEquals(year, yearQuarter.getYear()); + assertEquals(3, yearQuarter.getQuarterValue()); + assertSame(Quarter.Q3, yearQuarter.getQuarter()); + } + { + YearMonth yearMonth = YearMonth.of(year, 8); + YearQuarter yearQuarter = YearQuarter.of(yearMonth); + assertEquals(year, yearQuarter.getYear()); + assertEquals(3, yearQuarter.getQuarterValue()); + assertSame(Quarter.Q3, yearQuarter.getQuarter()); + } + { + YearMonth yearMonth = YearMonth.of(year, 9); + YearQuarter yearQuarter = YearQuarter.of(yearMonth); + assertEquals(year, yearQuarter.getYear()); + assertEquals(3, yearQuarter.getQuarterValue()); + assertSame(Quarter.Q3, yearQuarter.getQuarter()); + } + } + + @ParameterizedTest + @ValueSource(ints = { + 2023, // 非闰年 + 2024, // 闰年 + Year.MIN_VALUE, + Year.MAX_VALUE, + }) + void of_ValidYearMonth_CreatesYearMnoth_Q4(int year) { + { + YearMonth yearMonth = YearMonth.of(year, 10); + YearQuarter yearQuarter = YearQuarter.of(yearMonth); + assertEquals(year, yearQuarter.getYear()); + assertEquals(4, yearQuarter.getQuarterValue()); + assertSame(Quarter.Q4, yearQuarter.getQuarter()); + } + { + YearMonth yearMonth = YearMonth.of(year, 11); + YearQuarter yearQuarter = YearQuarter.of(yearMonth); + assertEquals(year, yearQuarter.getYear()); + assertEquals(4, yearQuarter.getQuarterValue()); + assertSame(Quarter.Q4, yearQuarter.getQuarter()); + } + { + YearMonth yearMonth = YearMonth.of(year, 12); + YearQuarter yearQuarter = YearQuarter.of(yearMonth); + assertEquals(year, yearQuarter.getYear()); + assertEquals(4, yearQuarter.getQuarterValue()); + assertSame(Quarter.Q4, yearQuarter.getQuarter()); + } + } + + @ParameterizedTest + @ValueSource(ints = { + 2023, // 非闰年 + 2024, // 闰年 + Year.MIN_VALUE, + Year.MAX_VALUE, + }) + void of_NullYearMonth_CreatesYearMnoth_Q4(int year) { + YearMonth yearMonth = null; + assertThrows(NullPointerException.class, + () -> YearQuarter.of(yearMonth)); + } + + // ================================ + // #endregion - of(YearMonth yearMonth) + // ================================ + + // ================================ + // #region - firstDate & lastDate + // ================================ + + @ParameterizedTest + @ValueSource(ints = { 1949, 1990, 2000, 2008, 2023, 2024, Year.MIN_VALUE, Year.MAX_VALUE }) + void test_getFirstDate_And_getLastDate(int year) { + { + final int quarterValue = 1; + YearQuarter yearQuarter = YearQuarter.of(year, quarterValue); + + LocalDate expectedFirstDate = LocalDate.of(year, 1, 1); + log.info("{} - expectedFirstDate: {}", yearQuarter, expectedFirstDate); + LocalDate expectedLastDate = LocalDate.of(year, 3, 31); + log.info("{} - expectedLastDate: {}", yearQuarter, expectedLastDate); + + assertEquals(expectedFirstDate, yearQuarter.firstDate()); + assertEquals(expectedLastDate, yearQuarter.lastDate()); + } + { + final int quarterValue = 2; + YearQuarter yearQuarter = YearQuarter.of(year, quarterValue); + + LocalDate expectedFirstDate = LocalDate.of(year, 4, 1); + log.info("{} - expectedFirstDate: {}", yearQuarter, expectedFirstDate); + LocalDate expectedLastDate = LocalDate.of(year, 6, 30); + log.info("{} - expectedLastDate: {}", yearQuarter, expectedLastDate); + + assertEquals(expectedFirstDate, yearQuarter.firstDate()); + assertEquals(expectedLastDate, yearQuarter.lastDate()); + } + { + final int quarterValue = 3; + YearQuarter yearQuarter = YearQuarter.of(year, quarterValue); + + LocalDate expectedFirstDate = LocalDate.of(year, 7, 1); + log.info("{} - expectedFirstDate: {}", yearQuarter, expectedFirstDate); + LocalDate expectedLastDate = LocalDate.of(year, 9, 30); + log.info("{} - expectedLastDate: {}", yearQuarter, expectedLastDate); + + assertEquals(expectedFirstDate, yearQuarter.firstDate()); + assertEquals(expectedLastDate, yearQuarter.lastDate()); + } + { + final int quarterValue = 4; + YearQuarter yearQuarter = YearQuarter.of(year, quarterValue); + + LocalDate expectedFirstDate = LocalDate.of(year, 10, 1); + log.info("{} - expectedFirstDate: {}", yearQuarter, expectedFirstDate); + LocalDate expectedLastDate = LocalDate.of(year, 12, 31); + log.info("{} - expectedLastDate: {}", yearQuarter, expectedLastDate); + + assertEquals(expectedFirstDate, yearQuarter.firstDate()); + assertEquals(expectedLastDate, yearQuarter.lastDate()); + } + } + + // ================================ + // #endregion - firstDate & lastDate + // ================================ + + // ================================ + // #region - firstYearMonth & lastYearMonth + // ================================ + + @ParameterizedTest + @ValueSource(ints = { 1949, 1990, 2000, 2008, 2023, 2024, Year.MIN_VALUE, Year.MAX_VALUE }) + void test_firstYearMonth_And_lastYearMonth(int year) { YearQuarter yq; yq = YearQuarter.of(year, Quarter.Q1); @@ -102,6 +811,50 @@ public class YearQuarterTests { assertEquals(YearMonth.of(year, 12), yq.lastYearMonth()); } + // ================================ + // #endregion - firstYearMonth & lastYearMonth + // ================================ + + // ================================ + // #region - firstMonth & lastMonth + // ================================ + + @ParameterizedTest + @ValueSource(ints = { 1949, 1990, 2000, 2008, 2023, 2024, Year.MIN_VALUE, Year.MAX_VALUE }) + void testFirstMonthAndLastMonth(int year) { + YearQuarter q1 = YearQuarter.of(year, 1); + assertEquals(1, q1.firstMonthValue()); + assertEquals(Month.JANUARY, q1.firstMonth()); + assertEquals(3, q1.lastMonthValue()); + assertEquals(Month.MARCH, q1.lastMonth()); + + YearQuarter q2 = YearQuarter.of(year, 2); + assertEquals(4, q2.firstMonthValue()); + assertEquals(Month.APRIL, q2.firstMonth()); + assertEquals(6, q2.lastMonthValue()); + assertEquals(Month.JUNE, q2.lastMonth()); + + YearQuarter q3 = YearQuarter.of(year, 3); + assertEquals(7, q3.firstMonthValue()); + assertEquals(Month.JULY, q3.firstMonth()); + assertEquals(9, q3.lastMonthValue()); + assertEquals(Month.SEPTEMBER, q3.lastMonth()); + + YearQuarter q4 = YearQuarter.of(year, 4); + assertEquals(10, q4.firstMonthValue()); + assertEquals(Month.OCTOBER, q4.firstMonth()); + assertEquals(12, q4.lastMonthValue()); + assertEquals(Month.DECEMBER, q4.lastMonth()); + } + + // ================================ + // #endregion - firstMonth & lastMonth + // ================================ + + // ================================ + // #region - compareTo + // ================================ + @Test void testCompareTo() { int year1; @@ -124,23 +877,20 @@ public class YearQuarterTests { // 同年同季度 assertEquals(yearQuarter1, yearQuarter2); assertEquals(0, yearQuarter1.compareTo(yearQuarter2)); - } - else if (quarter1 < quarter2) { + } else if (quarter1 < quarter2) { assertNotEquals(yearQuarter1, yearQuarter2); assertTrue(yearQuarter1.isBefore(yearQuarter2)); assertFalse(yearQuarter1.isAfter(yearQuarter2)); assertFalse(yearQuarter2.isBefore(yearQuarter1)); assertTrue(yearQuarter2.isAfter(yearQuarter1)); - } - else if (quarter1 > quarter2) { + } else if (quarter1 > quarter2) { assertNotEquals(yearQuarter1, yearQuarter2); assertFalse(yearQuarter1.isBefore(yearQuarter2)); assertTrue(yearQuarter1.isAfter(yearQuarter2)); assertTrue(yearQuarter2.isBefore(yearQuarter1)); assertFalse(yearQuarter2.isAfter(yearQuarter1)); } - } - else { + } else { // 不同年 assertEquals(year1 - year2, yearQuarter1.compareTo(yearQuarter2)); assertNotEquals(0, yearQuarter1.compareTo(yearQuarter2)); @@ -150,8 +900,7 @@ public class YearQuarterTests { assertFalse(yearQuarter1.isAfter(yearQuarter2)); assertFalse(yearQuarter2.isBefore(yearQuarter1)); assertTrue(yearQuarter2.isAfter(yearQuarter1)); - } - else if (year1 > year2) { + } else if (year1 > year2) { assertNotEquals(yearQuarter1, yearQuarter2); assertFalse(yearQuarter1.isBefore(yearQuarter2)); assertTrue(yearQuarter1.isAfter(yearQuarter2)); @@ -162,4 +911,281 @@ public class YearQuarterTests { } } } + + // ================================ + // #endregion - compareTo + // ================================ + + @ParameterizedTest + @ValueSource(ints = { Year.MIN_VALUE + 25, Year.MAX_VALUE - 25, -1, 0, 1, 1949, 1990, 2000, 2008, 2023, 2024 }) + void testPlusQuartersAndMinusQuarters(int year) { + for (int quarter = 1; quarter <= 4; quarter++) { + YearQuarter yq1 = YearQuarter.of(year, quarter); + for (int quartersToAdd = -100; quartersToAdd <= 100; quartersToAdd++) { + YearQuarter plus = yq1.plusQuarters(quartersToAdd); + YearQuarter minus = yq1.minusQuarters(-quartersToAdd); + assertEquals(plus, minus); + + // offset: 表示自 公元 0000年以来,经历了多少季度。所以 0 表示 -0001,Q4; 1 表示 0000 Q1 + long offset = (year * 4L + quarter) + quartersToAdd; + if (offset > 0) { + assertEquals((offset - 1) / 4, plus.getYear()); + assertEquals(((offset - 1) % 4) + 1, plus.getQuarterValue()); + } else { + assertEquals((offset / 4 - 1), plus.getYear()); + assertEquals((4 + offset % 4), plus.getQuarterValue()); + } + } + } + } + + @ParameterizedTest + @ValueSource(ints = { Year.MIN_VALUE + 1, Year.MAX_VALUE - 1, -1, 0, 1, 1900, 1990, 2000, 2023, 2024 }) + void test_nextQuarter_And_lastQuarter(int year) { + int quarter; + + YearQuarter yq; + YearQuarter next; + YearQuarter last; + + quarter = 1; + yq = YearQuarter.of(year, quarter); + next = yq.nextQuarter(); + assertEquals(year, next.getYear()); + assertEquals(2, next.getQuarterValue()); + last = yq.lastQuarter(); + assertEquals(year - 1, last.getYear()); + assertEquals(4, last.getQuarterValue()); + + quarter = 2; + yq = YearQuarter.of(year, quarter); + next = yq.nextQuarter(); + assertEquals(year, next.getYear()); + assertEquals(3, next.getQuarterValue()); + last = yq.lastQuarter(); + assertEquals(year, last.getYear()); + assertEquals(1, last.getQuarterValue()); + + quarter = 3; + yq = YearQuarter.of(year, quarter); + next = yq.nextQuarter(); + assertEquals(year, next.getYear()); + assertEquals(4, next.getQuarterValue()); + last = yq.lastQuarter(); + assertEquals(year, last.getYear()); + assertEquals(2, last.getQuarterValue()); + + quarter = 4; + yq = YearQuarter.of(year, quarter); + next = yq.nextQuarter(); + assertEquals(year + 1, next.getYear()); + assertEquals(1, next.getQuarterValue()); + last = yq.lastQuarter(); + assertEquals(year, last.getYear()); + assertEquals(3, last.getQuarterValue()); + } + + @ParameterizedTest + @ValueSource(ints = { Year.MIN_VALUE + 100, Year.MAX_VALUE - 100, -1, 0, 1, 1949, 1990, 2000, 2008, 2023, 2024 }) + void test_PlusYearsAndMinusYears(int year) { + for (int yearToAdd = -100; yearToAdd <= 100; yearToAdd++) { + YearQuarter q1 = YearQuarter.of(year, Quarter.Q1); + YearQuarter plus = q1.plusYears(yearToAdd); + assertEquals(year + yearToAdd, plus.getYear()); + assertEquals(Quarter.Q1, plus.getQuarter()); + YearQuarter minus = q1.minusYears(yearToAdd); + assertEquals(Quarter.Q1, minus.getQuarter()); + assertEquals(year - yearToAdd, minus.getYear()); + + assertEquals(q1.plusYears(yearToAdd), q1.minusYears(-yearToAdd)); + } + } + + @ParameterizedTest + @ValueSource(ints = { Year.MIN_VALUE + 1, Year.MAX_VALUE - 1, -1, 0, 1, 1900, 1990, 2000, 2023, 2024 }) + void test_nextYear_And_lastYear(int year) { + int quarter; + + YearQuarter yq; + YearQuarter next; + YearQuarter last; + + quarter = 1; + yq = YearQuarter.of(year, quarter); + next = yq.nextYear(); + assertSame(Quarter.Q1, yq.getQuarter()); + assertEquals(year + 1, next.getYear()); + assertSame(Quarter.Q1, next.getQuarter()); + last = yq.lastYear(); + assertEquals(year - 1, last.getYear()); + assertSame(Quarter.Q1, last.getQuarter()); + + quarter = 2; + yq = YearQuarter.of(year, quarter); + next = yq.nextYear(); + assertSame(Quarter.Q2, yq.getQuarter()); + assertEquals(year + 1, next.getYear()); + assertSame(Quarter.Q2, next.getQuarter()); + last = yq.lastYear(); + assertEquals(year - 1, last.getYear()); + assertSame(Quarter.Q2, last.getQuarter()); + + quarter = 3; + yq = YearQuarter.of(year, quarter); + next = yq.nextYear(); + assertSame(Quarter.Q3, yq.getQuarter()); + assertEquals(year + 1, next.getYear()); + assertSame(Quarter.Q3, next.getQuarter()); + last = yq.lastYear(); + assertEquals(year - 1, last.getYear()); + assertSame(Quarter.Q3, last.getQuarter()); + + quarter = 4; + yq = YearQuarter.of(year, quarter); + next = yq.nextYear(); + assertSame(Quarter.Q4, yq.getQuarter()); + assertEquals(year + 1, next.getYear()); + assertSame(Quarter.Q4, next.getQuarter()); + last = yq.lastYear(); + assertEquals(year - 1, last.getYear()); + assertSame(Quarter.Q4, last.getQuarter()); + } + + @ParameterizedTest + @ValueSource(ints = { -1, 0, 1, 1900, 2000, 2023, 2024, Year.MAX_VALUE, Year.MIN_VALUE }) + void test_compareTo_sameYear(int year) { + YearQuarter yq1 = YearQuarter.of(year, 1); + YearQuarter yq2 = YearQuarter.of(year, 2); + YearQuarter yq3 = YearQuarter.of(year, 3); + YearQuarter yq4 = YearQuarter.of(year, 4); + + assertTrue(yq1.equals(YearQuarter.of(year, Quarter.Q1))); // NOSONAR + assertTrue(yq1.compareTo(yq1) == 0); // NOSONAR + assertTrue(yq1.compareTo(yq2) < 0); + assertTrue(yq1.compareTo(yq3) < 0); + assertTrue(yq1.compareTo(yq4) < 0); + + assertTrue(yq2.equals(YearQuarter.of(year, Quarter.Q2))); // NOSONAR + assertTrue(yq2.compareTo(yq1) > 0); + assertTrue(yq2.compareTo(yq2) == 0); // NOSONAR + assertTrue(yq2.compareTo(yq3) < 0); + assertTrue(yq2.compareTo(yq4) < 0); + + assertTrue(yq3.equals(YearQuarter.of(year, Quarter.Q3))); // NOSONAR + assertTrue(yq3.compareTo(yq1) > 0); + assertTrue(yq3.compareTo(yq2) > 0); + assertTrue(yq3.compareTo(yq3) == 0); // NOSONAR + assertTrue(yq3.compareTo(yq4) < 0); + + assertTrue(yq4.equals(YearQuarter.of(year, Quarter.Q4))); // NOSONAR + assertTrue(yq4.compareTo(yq1) > 0); + assertTrue(yq4.compareTo(yq2) > 0); + assertTrue(yq4.compareTo(yq3) > 0); + assertTrue(yq4.compareTo(yq4) == 0); // NOSONAR + } + + @ParameterizedTest + @ValueSource(ints = { -1, 0, 1, 1900, 2000, 2023, 2024, Year.MAX_VALUE, Year.MIN_VALUE }) + void test_isBefore_sameYear(int year) { + YearQuarter yq1 = YearQuarter.of(year, 1); + YearQuarter yq2 = YearQuarter.of(year, 2); + YearQuarter yq3 = YearQuarter.of(year, 3); + YearQuarter yq4 = YearQuarter.of(year, 4); + + assertFalse(yq1.isBefore(YearQuarter.of(year, Quarter.Q1))); + assertTrue(yq1.isBefore(yq2)); + assertTrue(yq1.isBefore(yq3)); + assertTrue(yq1.isBefore(yq4)); + + assertFalse(yq2.isBefore(yq1)); + assertFalse(yq2.isBefore(YearQuarter.of(year, Quarter.Q2))); + assertTrue(yq2.isBefore(yq3)); + assertTrue(yq2.isBefore(yq4)); + + assertFalse(yq3.isBefore(yq1)); + assertFalse(yq3.isBefore(yq2)); + assertFalse(yq3.isBefore(YearQuarter.of(year, Quarter.Q3))); + assertTrue(yq3.isBefore(yq4)); + + assertFalse(yq4.isBefore(yq1)); + assertFalse(yq4.isBefore(yq2)); + assertFalse(yq4.isBefore(yq3)); + assertFalse(yq4.isBefore(YearQuarter.of(year, Quarter.Q4))); + } + + @ParameterizedTest + @ValueSource(ints = { -1, 0, 1, 1900, 2000, 2023, 2024, Year.MAX_VALUE, Year.MIN_VALUE }) + void test_isAfter_sameYear(int year) { + YearQuarter yq1 = YearQuarter.of(year, 1); + YearQuarter yq2 = YearQuarter.of(year, 2); + YearQuarter yq3 = YearQuarter.of(year, 3); + YearQuarter yq4 = YearQuarter.of(year, 4); + + assertFalse(yq1.isAfter(YearQuarter.of(year, Quarter.Q1))); + assertFalse(yq1.isAfter(yq2)); + assertFalse(yq1.isAfter(yq3)); + assertFalse(yq1.isAfter(yq4)); + + assertTrue(yq2.isAfter(yq1)); + assertFalse(yq2.isAfter(YearQuarter.of(year, Quarter.Q2))); + assertFalse(yq2.isAfter(yq3)); + assertFalse(yq2.isAfter(yq4)); + + assertTrue(yq3.isAfter(yq1)); + assertTrue(yq3.isAfter(yq2)); + assertFalse(yq3.isAfter(YearQuarter.of(year, Quarter.Q3))); + assertFalse(yq3.isAfter(yq4)); + + assertTrue(yq4.isAfter(yq1)); + assertTrue(yq4.isAfter(yq2)); + assertTrue(yq4.isAfter(yq3)); + assertFalse(yq4.isAfter(YearQuarter.of(year, Quarter.Q4))); + } + + @Test + void test_compareTo_null() { + YearQuarter yq = YearQuarter.of(2024, 4); + assertThrows(NullPointerException.class, + () -> yq.compareTo(null)); + assertThrows(NullPointerException.class, + () -> yq.isBefore(null)); + assertThrows(NullPointerException.class, + () -> yq.isAfter(null)); + assertNotEquals(null, yq); + } + + @ParameterizedTest + @ValueSource(ints = { -1, 0, 1, 1900, 2000, 2023, 2024, Year.MAX_VALUE - 1, Year.MIN_VALUE + 1 }) + void test_compareTo_differentYear(int year) { + for (int quarter1 = 1; quarter1 <= 4; quarter1++) { + YearQuarter yq = YearQuarter.of(year, quarter1); + for (int quarter2 = 1; quarter2 <= 4; quarter2++) { + // gt + assertTrue(yq.compareTo(YearQuarter.of(year + 1, quarter2)) < 0); + assertTrue(yq.isBefore(YearQuarter.of(year + 1, quarter2))); + assertTrue(YearQuarter.of(year + 1, quarter2).compareTo(yq) > 0); + assertTrue(YearQuarter.of(year + 1, quarter2).isAfter(yq)); + // lt + assertTrue(yq.compareTo(YearQuarter.of(year - 1, quarter2)) > 0); + assertTrue(yq.isAfter(YearQuarter.of(year - 1, quarter2))); + assertTrue(YearQuarter.of(year - 1, quarter2).compareTo(yq) < 0); + assertTrue(YearQuarter.of(year - 1, quarter2).isBefore(yq)); + } + } + } + + @ParameterizedTest + @ValueSource(ints = { -1, 0, 1, 1900, 2000, 2023, 2024, Year.MAX_VALUE, Year.MIN_VALUE }) + void test_min_And_max_sameYear(int year) { + YearQuarter yq1 = YearQuarter.of(year, 1); + YearQuarter anotherYq1 = YearQuarter.of(year, 1); + + assertEquals(yq1, YearQuarter.max(yq1, anotherYq1)); + assertEquals(yq1, YearQuarter.min(yq1, anotherYq1)); + + YearQuarter yq2 = YearQuarter.of(year, 2); + assertEquals(yq2, YearQuarter.max(yq1, yq2)); + assertEquals(yq1, YearQuarter.min(yq1, yq2)); + + } }