diff --git a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/time/TimeChecker.java b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/time/TimeChecker.java index 90ea353242..135acfe8a4 100644 --- a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/time/TimeChecker.java +++ b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/time/TimeChecker.java @@ -242,13 +242,15 @@ public boolean hasDayChanged(boolean set) { public boolean hasMonthChanged(boolean set) { String prevMonth = plugin.getServerDataFile().getPrevMonth(); - String month = getTime().getMonth().toString(); + LocalDateTime current = getTime(); + String month = current.getMonth().toString(); if (prevMonth.equals(month)) return false; if (set) plugin.getServerDataFile().setPrevMonth(month); - if (!plugin.getOptions().isTimeChangeFailSafeBypass() && getTime().getDayOfMonth() > 3) { + LocalDateTime graceEnd = current.withDayOfMonth(1).toLocalDate().atStartOfDay().plusHours(12); + if (!plugin.getOptions().isTimeChangeFailSafeBypass() && current.isAfter(graceEnd)) { plugin.getLogger().warning( - "Detected a month change, but current day is not near end of a month, ignoring month change, " - + getTime().getDayOfMonth()); + "Detected a month change outside the first 12 hours of the month, ignoring month change: " + + current); plugin.getServerDataFile().setPrevMonth(month); return false; } diff --git a/AdvancedCore/src/main/java/com/bencodez/advancedcore/bungeeapi/time/BungeeTimeChecker.java b/AdvancedCore/src/main/java/com/bencodez/advancedcore/bungeeapi/time/BungeeTimeChecker.java index 892c1d5166..ee47c85be6 100644 --- a/AdvancedCore/src/main/java/com/bencodez/advancedcore/bungeeapi/time/BungeeTimeChecker.java +++ b/AdvancedCore/src/main/java/com/bencodez/advancedcore/bungeeapi/time/BungeeTimeChecker.java @@ -102,16 +102,18 @@ public boolean hasDayChanged(boolean set) { public boolean hasMonthChanged(boolean set) { String prevMonth = getPrevMonth(); - String month = getTime().getMonth().toString(); + LocalDateTime current = getTime(); + String month = current.getMonth().toString(); if (prevMonth.equals(month)) { return false; } if (set) { setPrevMonth(month); } - if (!timeChangeFailSafeBypass && getTime().getDayOfMonth() > 3) { - warning("Detected a month change, but current day is not near end of a month, ignoring month change, " - + getTime().getDayOfMonth()); + LocalDateTime graceEnd = current.withDayOfMonth(1).toLocalDate().atStartOfDay().plusHours(12); + if (!timeChangeFailSafeBypass && current.isAfter(graceEnd)) { + warning("Detected a month change outside the first 12 hours of the month, ignoring month change: " + + current); setPrevMonth(month); return false; } diff --git a/AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/time/BungeeTimeCheckerTest.java b/AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/time/BungeeTimeCheckerTest.java index 55561f0262..47e6d27a33 100644 --- a/AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/time/BungeeTimeCheckerTest.java +++ b/AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/time/BungeeTimeCheckerTest.java @@ -367,6 +367,10 @@ public void warning(String text) { assertTrue(result); verify(timeChecker).setPrevMonth("NOVEMBER"); + + Mockito.doReturn(LocalDateTime.of(2023, 11, 1, 12, 0, 1)).when(timeChecker).getTime(); + assertFalse(timeChecker.hasMonthChanged(false)); + verify(timeChecker, Mockito.times(2)).setPrevMonth("NOVEMBER"); } @Test diff --git a/AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/time/TimeCheckerTest.java b/AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/time/TimeCheckerTest.java index c6ccc1b6b1..90570c4fbe 100644 --- a/AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/time/TimeCheckerTest.java +++ b/AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/time/TimeCheckerTest.java @@ -149,6 +149,22 @@ public void testDayWeekMonthChanges() { } } + @Test + public void monthChangeFailSafeRejectsStaleChangeAfterTwelveHours() { + when(serverDataFile.getPrevMonth()).thenReturn("DECEMBER"); + when(options.isTimeChangeFailSafeBypass()).thenReturn(false); + when(plugin.getLogger()).thenReturn(Logger.getLogger("TimeCheckerTest")); + + TimeChecker timeChecker = Mockito.spy(new TimeChecker(plugin)); + + Mockito.doReturn(LocalDateTime.of(2025, 1, 1, 12, 0)).when(timeChecker).getTime(); + assertTrue(timeChecker.hasMonthChanged(false)); + + Mockito.doReturn(LocalDateTime.of(2025, 1, 1, 12, 0, 1)).when(timeChecker).getTime(); + assertFalse(timeChecker.hasMonthChanged(false)); + verify(serverDataFile).setPrevMonth("JANUARY"); + } + @Test public void detectedTransitionAdvancesMarkerOnlyAfterSuccessfulDispatch() { TimeChangeTransitionState transition = transitionState();