diff --git a/hutool-cron/src/test/java/cn/hutool/v7/cron/pattern/CronPatternNextMatchTest.java b/hutool-cron/src/test/java/cn/hutool/v7/cron/pattern/CronPatternNextMatchTest.java index aeaacf749..2d54b4966 100644 --- a/hutool-cron/src/test/java/cn/hutool/v7/cron/pattern/CronPatternNextMatchTest.java +++ b/hutool-cron/src/test/java/cn/hutool/v7/cron/pattern/CronPatternNextMatchTest.java @@ -24,6 +24,8 @@ import org.junit.jupiter.api.Test; import java.util.Calendar; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class CronPatternNextMatchTest { @Test @@ -32,35 +34,35 @@ public class CronPatternNextMatchTest { CronPattern pattern = new CronPattern("* * * * * * *"); DateTime date = DateUtil.truncate(DateUtil.now(), DateField.SECOND); Calendar calendar = pattern.nextMatchAfter(date.toCalendar()); - Assertions.assertEquals(date.getTime() + 1000, DateUtil.date(calendar).getTime()); + assertEquals(date.getTime() + 1000, DateUtil.date(calendar).getTime()); // 匹配所有分,返回下一分钟 pattern = new CronPattern("0 * * * * * *"); date = DateUtil.parse("2022-04-08 07:44:16"); //noinspection ConstantConditions calendar = pattern.nextMatchAfter(date.toCalendar()); - Assertions.assertEquals(DateUtil.parse("2022-04-08 07:45:00"), DateUtil.date(calendar)); + assertEquals(DateUtil.parse("2022-04-08 07:45:00"), DateUtil.date(calendar)); // 匹配所有时,返回下一小时 pattern = new CronPattern("0 0 * * * * *"); date = DateUtil.parse("2022-04-08 07:44:16"); //noinspection ConstantConditions calendar = pattern.nextMatchAfter(date.toCalendar()); - Assertions.assertEquals(DateUtil.parse("2022-04-08 08:00:00"), DateUtil.date(calendar)); + assertEquals(DateUtil.parse("2022-04-08 08:00:00"), DateUtil.date(calendar)); // 匹配所有天,返回明日 pattern = new CronPattern("0 0 0 * * * *"); date = DateUtil.parse("2022-04-08 07:44:16"); //noinspection ConstantConditions calendar = pattern.nextMatchAfter(date.toCalendar()); - Assertions.assertEquals(DateUtil.parse("2022-04-09 00:00:00"), DateUtil.date(calendar)); + assertEquals(DateUtil.parse("2022-04-09 00:00:00"), DateUtil.date(calendar)); // 匹配所有月,返回下一月 pattern = new CronPattern("0 0 0 1 * * *"); date = DateUtil.parse("2022-04-08 07:44:16"); //noinspection ConstantConditions calendar = pattern.nextMatchAfter(date.toCalendar()); - Assertions.assertEquals(DateUtil.parse("2022-05-01 00:00:00"), DateUtil.date(calendar)); + assertEquals(DateUtil.parse("2022-05-01 00:00:00"), DateUtil.date(calendar)); } @Test @@ -73,35 +75,35 @@ public class CronPatternNextMatchTest { DateUtil.parse("2022-04-12 09:12:12").toCalendar()); Assertions.assertTrue(pattern.match(calendar, true)); - Assertions.assertEquals("2022-04-12 09:12:23", DateUtil.date(calendar).toString()); + assertEquals("2022-04-12 09:12:23", DateUtil.date(calendar).toString()); // 秒超出规定值的最大值,分+1,秒取最小值 //noinspection ConstantConditions calendar = pattern.nextMatchAfter( DateUtil.parse("2022-04-12 09:09:24").toCalendar()); Assertions.assertTrue(pattern.match(calendar, true)); - Assertions.assertEquals("2022-04-12 09:12:23", DateUtil.date(calendar).toString()); + assertEquals("2022-04-12 09:12:23", DateUtil.date(calendar).toString()); // 秒超出规定值的最大值,分不变,小时+1,秒和分使用最小值 //noinspection ConstantConditions calendar = pattern.nextMatchAfter( DateUtil.parse("2022-04-12 09:12:24").toCalendar()); Assertions.assertTrue(pattern.match(calendar, true)); - Assertions.assertEquals("2022-04-12 10:12:23", DateUtil.date(calendar).toString()); + assertEquals("2022-04-12 10:12:23", DateUtil.date(calendar).toString()); // 天超出规定值的最大值,月+1,天、时、分、秒取最小值 //noinspection ConstantConditions calendar = pattern.nextMatchAfter( DateUtil.parse("2022-04-13 09:12:24").toCalendar()); Assertions.assertTrue(pattern.match(calendar, true)); - Assertions.assertEquals("2022-05-12 00:12:23", DateUtil.date(calendar).toString()); + assertEquals("2022-05-12 00:12:23", DateUtil.date(calendar).toString()); // 跨年 //noinspection ConstantConditions calendar = pattern.nextMatchAfter( DateUtil.parse("2021-12-22 00:00:00").toCalendar()); Assertions.assertTrue(pattern.match(calendar, true)); - Assertions.assertEquals("2022-01-12 00:12:23", DateUtil.date(calendar).toString()); + assertEquals("2022-01-12 00:12:23", DateUtil.date(calendar).toString()); } @Test @@ -113,7 +115,7 @@ public class CronPatternNextMatchTest { final Calendar calendar = pattern.nextMatchAfter( DateUtil.parse("2022-04-12 09:12:24").toCalendar()); Assertions.assertTrue(pattern.match(calendar, true)); - Assertions.assertEquals("2022-04-12 10:12:23", DateUtil.date(calendar).toString()); + assertEquals("2022-04-12 10:12:23", DateUtil.date(calendar).toString()); } @Test @@ -123,6 +125,137 @@ public class CronPatternNextMatchTest { final DateTime time = DateUtil.parse("2022-04-03"); assert time != null; final Calendar calendar = pattern.nextMatchAfter(time.toCalendar()); - Assertions.assertEquals("2022-04-09 01:01:01", DateUtil.date(calendar).toString()); + assertEquals("2022-04-09 01:01:01", DateUtil.date(calendar).toString()); + } + + @Test + public void testLastDayOfMonthForEveryMonth1() { + DateTime date = DateUtil.parse("2023-01-08 07:44:16"); + DateTime result = DateUtil.parse("2023-01-31 03:02:01"); + // 匹配所有月,生成每个月的最后一天 + final CronPattern pattern = new CronPattern("1 2 3 L * ?"); + for (int i = 0; i < 30; i++) { + //noinspection ConstantConditions + final Calendar calendar = pattern.nextMatchAfter(date.toCalendar()); + date = DateUtil.date(calendar); + assertEquals(date, result); + // 加一秒 + date = date.offset(DateField.SECOND, 1); + + // 移动到下一个月的最后一天 + result = result.offset(DateField.DAY_OF_MONTH, 1); + final int lastDayOfMonth = DateUtil.getLastDayOfMonth(result); + result.setField(DateField.DAY_OF_MONTH, lastDayOfMonth); + } + } + + @Test + public void testLastDayOfMonthForEveryMonth2() { + DateTime date = DateUtil.parse("2023-03-08 07:44:16"); + DateTime result = DateUtil.parse("2023-03-31 03:02:01"); + // 匹配所有月,生成每个月的最后一天 + final CronPattern pattern = new CronPattern("1 2 3 L * ?"); + for (int i = 0; i < 30; i++) { + //noinspection ConstantConditions + final Calendar calendar = pattern.nextMatchAfter(date.toCalendar()); + date = DateUtil.date(calendar); + assertEquals(date, result); + // 加一秒 + date = date.offset(DateField.SECOND, 1); + + // 移动到下一个月的最后一天 + result = result.offset(DateField.DAY_OF_MONTH, 1); + final int lastDayOfMonth = DateUtil.getLastDayOfMonth(result); + result.setField(DateField.DAY_OF_MONTH, lastDayOfMonth); + } + } + + @Test + public void testLastDayOfMonthForEveryYear1() { + DateTime date = DateUtil.parse("2023-01-08 07:44:16"); + DateTime result = DateUtil.parse("2023-02-28 03:02:01"); + // 匹配每一年2月的最后一天 + final CronPattern pattern = new CronPattern("1 2 3 L 2 ?"); + for (int i = 0; i < 10; i++) { + //noinspection ConstantConditions + final Calendar calendar = pattern.nextMatchAfter(date.toCalendar()); + date = DateUtil.date(calendar); + assertEquals(date, result); + // 加一秒 + date = date.offset(DateField.SECOND, 1); + + // 移动到下一年的最后一天 + result = result.offset(DateField.YEAR, 1); + final int lastDayOfMonth = DateUtil.getLastDayOfMonth(result); + result.setField(DateField.DAY_OF_MONTH, lastDayOfMonth); + } + } + + @Test + public void testLastDayOfMonthForEveryYear2() { + DateTime date = DateUtil.parse("2022-03-08 07:44:16"); + DateTime result = DateUtil.parse("2023-02-28 03:02:01"); + // 匹配每一年2月的最后一天 + final CronPattern pattern = new CronPattern("1 2 3 L 2 ?"); + for (int i = 0; i < 30; i++) { + //noinspection ConstantConditions + final Calendar calendar = pattern.nextMatchAfter(date.toCalendar()); + date = DateUtil.date(calendar); + assertEquals(date, result); + // 加一秒 + date = date.offset(DateField.SECOND, 1); + + // 移动到下一年的最后一天 + result = result.offset(DateField.YEAR, 1); + final int lastDayOfMonth = DateUtil.getLastDayOfMonth(result); + result.setField(DateField.DAY_OF_MONTH, lastDayOfMonth); + } + } + + @Test + public void testEveryHour() { + DateTime date = DateUtil.parse("2022-02-28 07:44:16"); + DateTime result = DateUtil.parse("2022-02-28 08:02:01"); + // 匹配每一年2月的最后一天 + final CronPattern pattern = new CronPattern("1 2 */1 * * ?"); + for (int i = 0; i < 30; i++) { + //noinspection ConstantConditions + final Calendar calendar = pattern.nextMatchAfter(date.toCalendar()); + date = DateUtil.date(calendar); + assertEquals(date, result); + // 加一秒 + date = date.offset(DateField.SECOND, 1); + + // 移动到下一个小时 + result = result.offset(DateField.HOUR_OF_DAY, 1); + } + } + + @Test + public void testLastDayOfMonthForEveryHour() { + DateTime date = DateUtil.parse("2023-01-28 07:44:16"); + DateTime result = DateUtil.parse("2023-01-31 00:00:00"); + // 匹配每一年2月的最后一天 + final CronPattern pattern = new CronPattern("0 0 */1 L * ?"); + for (int i = 0; i < 400; i++) { + //noinspection ConstantConditions + final Calendar calendar = pattern.nextMatchAfter(date.toCalendar()); + date = DateUtil.date(calendar); + assertEquals(date, result); + // 加一秒 + date = date.offset(DateField.SECOND, 1); + + // 移动到下一个小时 + final DateTime t = result.setMutable(false).offset(DateField.HOUR_OF_DAY, 1); + if (t.dayOfMonth() != result.dayOfMonth()) { + // 移动到下个月最后一天的开始 + result = result.offset(DateField.DAY_OF_MONTH, 1); + final int lastDayOfMonth = DateUtil.getLastDayOfMonth(result); + result = result.setField(DateField.DAY_OF_MONTH, lastDayOfMonth); + result = DateUtil.beginOfDay(result); + } else { + result = t; + } + } } }