diff --git a/src/main/java/duke/util/TimeUtil.java b/src/main/java/duke/util/TimeUtil.java index 96aba36faf..c3beafaf33 100644 --- a/src/main/java/duke/util/TimeUtil.java +++ b/src/main/java/duke/util/TimeUtil.java @@ -1,5 +1,6 @@ package duke.util; +import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -84,15 +85,18 @@ public static String formatLocalDateTime(LocalDateTime localDate) { */ public static String getHelpMessage() { return "Invalid date format! Please use one of the following formats:" - + "\n- yyyy-MM-dd HHmm (e.g. 2023-05-28 1800)" - + "\n- yyyyMMdd HHmm (e.g. 2023-05-28 1800)" - + "\n- yyyy-MM-dd (e.g. 2023-05-28)" - + "\n- yyyymmdd (e.g. 20230528)" - + "\n- d MMM yyyy (e.g. 1 Jan 2023)" - + "\n- d MMMM yyyy (e.g. 1 January 2023)" - + "\nOr use special terms like:" - + "\n- today" - + "\n- tomorrow"; + + "\n- yyyy-MM-dd HHmm (e.g. 2023-05-28 1800)" + + "\n- yyyyMMdd HHmm (e.g. 2023-05-28 1800)" + + "\n- yyyy-MM-dd (e.g. 2023-05-28)" + + "\n- yyyymmdd (e.g. 20230528)" + + "\n- d MMM yyyy (e.g. 1 Jan 2023)" + + "\n- d MMMM yyyy (e.g. 1 January 2023)" + + "\nOr use special terms like:" + + "\n- today" + + "\n- tomorrow" + + "\n- monday (for the next Monday)" + + "\n- tuesday (for the next Tuesday)" + + "\n- ... (similarly for other days of the week)"; } /** @@ -110,8 +114,36 @@ private static LocalDateTime handleSpecialStrings(String input) { return LocalDateTime.now().withHour(23).withMinute(59); case "tomorrow": return LocalDateTime.now().plusDays(1).withHour(23).withMinute(59); + case "monday": + case "tuesday": + case "wednesday": + case "thursday": + case "friday": + case "saturday": + case "sunday": + return getNextDayOfWeek(DayOfWeek.valueOf(input.toUpperCase())); default: return null; } } + + /** + * Returns the LocalDateTime of the next occurrence of the specified day of the week. + *

+ * This method calculates the number of days between the current day and the desired day of the week. + * If the desired day is the same as the current day, it returns the date of the next week's occurrence. + *

+ * + * @param desiredDay The desired day of the week as a DayOfWeek enum value. + * @return A LocalDateTime representing the next occurrence of the desired day, with the time set to 23:59. + */ + private static LocalDateTime getNextDayOfWeek(DayOfWeek desiredDay) { + LocalDateTime now = LocalDateTime.now(); + int daysUntilDesired = desiredDay.getValue() - now.getDayOfWeek().getValue(); + if (daysUntilDesired <= 0) { // if today is the desired day or a later day in the week + daysUntilDesired += 7; // get the next occurrence of the desired day + } + return now.plusDays(daysUntilDesired).withHour(23).withMinute(59); + } + } diff --git a/src/test/java/duke/util/TimeUtilTest.java b/src/test/java/duke/util/TimeUtilTest.java index 847ced5182..98b87b8cd5 100644 --- a/src/test/java/duke/util/TimeUtilTest.java +++ b/src/test/java/duke/util/TimeUtilTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import java.time.DayOfWeek; import java.time.LocalDateTime; import java.util.List; @@ -67,6 +68,22 @@ public void testParseDateTimeString_withSpecialInputs() { } } + @Test + public void testParseDateTimeString_withDaysOfWeekInputs() { + List daysOfWeekInputs = List.of("monday", "tuesday", "wednesday", "thursday", "friday", + "saturday", "sunday"); + for (String input : daysOfWeekInputs) { + try { + LocalDateTime actual = TimeUtil.parseDateTimeString(input); + DayOfWeek expectedDay = DayOfWeek.valueOf(input.toUpperCase()); + assertEquals(expectedDay, actual.getDayOfWeek()); + } catch (TimeUtilException e) { + fail(); + } + } + } + + @Test public void testParseDateTimeString_withInvalidInputs() { List invalidInputs = List.of(