Skip to content

Commit

Permalink
Improve date parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
starchypotatocode committed Nov 8, 2024
1 parent 56b342f commit b3287d0
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/main/java/hallpointer/address/model/member/Room.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
public class Room {

public static final String MESSAGE_CONSTRAINTS = "Room should be in the format block-floor-room number.\n"
public static final String MESSAGE_CONSTRAINTS = "Room must be in the format block-floor-room number.\n"
+ "Example: 10-3-100\n"
+ "Unfortunately, non-numeric block or room numbers are currently unsupported.";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ public boolean equals(Object other) {
}

Telegram otherTelegram = (Telegram) other;
System.out.println(value.equals(otherTelegram.value));
return value.equals(otherTelegram.value);
}

Expand Down
44 changes: 39 additions & 5 deletions src/main/java/hallpointer/address/model/session/SessionDate.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Represents a SessionDate.
Expand All @@ -14,11 +16,14 @@
public class SessionDate {

public static final String MESSAGE_CONSTRAINTS =
"Dates should be in the format dd MMM yyyy.\n"
"Dates must be in the format dd MMM yyyy,\n"
+ "although it is case-insensitive and does not need zero-padding.\n"
+ "Example: 24 Sep 2024";

// Desired date format
public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd MMM yyyy");
// Whitespace processing already done earlier
public static final Pattern parsingPattern = Pattern.compile("^([0-9]{1,2}) ([a-zA-Z]{3}) ([0-9]{4})$");

public final LocalDate fullDate;

Expand All @@ -30,16 +35,45 @@ public class SessionDate {
public SessionDate(String date) {
requireNonNull(date);
checkArgument(isValidDate(date), MESSAGE_CONSTRAINTS);
fullDate = LocalDate.parse(date, DATE_FORMATTER);
fullDate = LocalDate.parse(manualFormatDate(date), DATE_FORMATTER);
}

/**
* Parses minor errors in date formatting and fixes them.
* Minor errors in this case referring to zero-padding and month case.
*
* @param date the input date in question
* @return the correctly formatted date
*/
private static String manualFormatDate(String date) {
requireNonNull(date);
Matcher matcher = parsingPattern.matcher(date);
if (!matcher.find()) {
return ""; // no amount of formatting can save this given the input constraints
}
// matcher.group(0) returns the whole string
String day = matcher.group(1);
String month = matcher.group(2);
String year = matcher.group(3);

// Fix zero-padding requirement
if (day.length() == 1) {
day = "0" + day;
}
// Fix month case issue
month = month.substring(0, 1).toUpperCase() + month.substring(1).toLowerCase();
// Nothing can be done about year errors due to ambiguity
return day + " " + month + " " + year;
}

/**
* Returns true if a given string is a valid date and has the expected format.
*/
public static boolean isValidDate(String test) {
public static boolean isValidDate(String date) {
try {
LocalDate parsedDate = LocalDate.parse(test, DATE_FORMATTER);
return parsedDate.format(DATE_FORMATTER).equals(test);
String formattedDate = manualFormatDate(date);
LocalDate parsedDate = LocalDate.parse(formattedDate, DATE_FORMATTER);
return parsedDate.format(DATE_FORMATTER).equals(formattedDate); // throws error if it doesn't work
} catch (DateTimeParseException e) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/hallpointer/address/model/tag/Tag.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
public class Tag {

public static final String MESSAGE_CONSTRAINTS = "Tag names should be alphanumeric and without spaces.";
public static final String MESSAGE_CONSTRAINTS = "Tag names must be alphanumeric and without spaces.";
public static final String VALIDATION_REGEX = "\\p{Alnum}+";

public final String tagName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,33 @@ public void isValidDate() {
assertFalse(SessionDate.isValidDate("24 September 2024")); // wrong format
assertFalse(SessionDate.isValidDate("Oct 24 2024")); // wrong format
assertFalse(SessionDate.isValidDate("2024 24 Sep")); // wrong format
assertFalse(SessionDate.isValidDate("333 Mar 2024")); // invalid day
assertFalse(SessionDate.isValidDate("30 m 2024")); // invalid month
assertFalse(SessionDate.isValidDate("30 Mar 024")); // invalid year
assertFalse(SessionDate.isValidDate(" Mar 2024")); // missing day
assertFalse(SessionDate.isValidDate("29 2024")); // missing month
assertFalse(SessionDate.isValidDate("30 Mar ")); // missing year

// valid dates
assertTrue(SessionDate.isValidDate("24 Sep 2024")); // valid date
assertTrue(SessionDate.isValidDate("01 Jan 2000")); // valid date
assertTrue(SessionDate.isValidDate("15 Aug 2023")); // valid date
assertTrue(SessionDate.isValidDate("24 Sep 2024"));
assertTrue(SessionDate.isValidDate("01 Jan 2000"));
assertTrue(SessionDate.isValidDate("15 Aug 2023"));
assertTrue(SessionDate.isValidDate("1 Jan 2000")); // no zero-padding
assertTrue(SessionDate.isValidDate("15 aUg 2023")); // wrong case
assertTrue(SessionDate.isValidDate("4 fEB 1989")); //both
}

@Test
public void equals() {
SessionDate sessionDate = new SessionDate("24 Sep 2024");
SessionDate sessionDate = new SessionDate("4 Sep 2024");

// same values -> returns true
assertTrue(sessionDate.equals(new SessionDate("24 Sep 2024")));
assertTrue(sessionDate.equals(new SessionDate("4 Sep 2024")));

// same after formatting -> returns true
assertTrue(sessionDate.equals(new SessionDate("04 Sep 2024")));
assertTrue(sessionDate.equals(new SessionDate("4 sep 2024")));
assertTrue(sessionDate.equals(new SessionDate("4 SeP 2024")));

// same object -> returns true
assertTrue(sessionDate.equals(sessionDate));
Expand Down

0 comments on commit b3287d0

Please sign in to comment.