Formatting Date with time, only if there is a time on the date

Sam :

I am trying to sanitize dates that are generated from another application. Sometimes the dates can be of a bad format, when they are, they should be blanked out. The general conditions should be;

  • Any dates on or before the year 1900 are considered invalid and blanked out

  • Any dates after the current year are considered invalid and blanked out

  • Any valid dates that match the patterns should returned in the output yyyy-MM-dd HH:mm:ss (where there is a timestamp available) OR yyyy-MM-dd when there is no timestamp available.

Dates <= 1900 and after the current year are considered to be invalid as they are being loaded into another system, where these dates won't make sense in the context of the application. For the same reason, I need to return the dates in the aforementioned format so they can be loaded into the next application.

How can I modify my code below to handle dates that do not have a timestamp? The current code gives an error of: java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: HourOfDay when you try to call; SanitiseDate("01/01/2001")

Here is my code so far:

public static String SanitiseDate(String input) {
    DateTimeFormatter[] possibleFormats = {
            DateTimeFormatter.ofPattern("uuuu-MM-dd").withResolverStyle(ResolverStyle.STRICT),
            DateTimeFormatter.ofPattern("uuuu/MM/dd").withResolverStyle(ResolverStyle.STRICT),
            DateTimeFormatter.ofPattern("dd/MM/uuuu").withResolverStyle(ResolverStyle.STRICT),
            DateTimeFormatter.ofPattern("dd-MM-uuuu").withResolverStyle(ResolverStyle.STRICT),
            DateTimeFormatter.ofPattern("mm-DD-uuuu").withResolverStyle(ResolverStyle.STRICT),

            DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss").withResolverStyle(ResolverStyle.STRICT),
            DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm").withResolverStyle(ResolverStyle.STRICT),

            DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm").withResolverStyle(ResolverStyle.STRICT),
            DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss").withResolverStyle(ResolverStyle.STRICT),

            DateTimeFormatter.ofPattern("dd/MM/uuuu HH:mm:ss").withResolverStyle(ResolverStyle.STRICT),
            DateTimeFormatter.ofPattern("dd/MM/uuuu HH:mm").withResolverStyle(ResolverStyle.STRICT),

            DateTimeFormatter.ofPattern("dd-MM-uuuu HH:mm").withResolverStyle(ResolverStyle.STRICT),
            DateTimeFormatter.ofPattern("dd-MM-uuuu HH:mm:ss").withResolverStyle(ResolverStyle.STRICT),

            DateTimeFormatter.ofPattern("mm-DD-uuuu HH:mm").withResolverStyle(ResolverStyle.STRICT),
            DateTimeFormatter.ofPattern("mm-DD-uuuu HH:mm:ss").withResolverStyle(ResolverStyle.STRICT),
    };

    for (DateTimeFormatter format : possibleFormats) {
        try {
            LocalDate result = LocalDate.parse(input, format);
            if (result.getYear() <= 1900 || result.getYear() > Year.now().getValue())
            {
                return "";
            }
            return result.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        } catch (DateTimeParseException dtpe) {
            // ignore, try next format
        }
    }
    return "";
}

My tests:

@Test
public void sanitiseDateTest()
{
    assertEquals("", StringUtil.SanitiseDate(""));
    assertEquals("", StringUtil.SanitiseDate("01/01/1601"));
    assertEquals("", StringUtil.SanitiseDate("01/01/1501"));
    assertEquals("2001-01-01", StringUtil.SanitiseDate("01/01/2001"));
    assertEquals("1980-01-01", StringUtil.SanitiseDate("01/01/1980"));
    assertEquals("", StringUtil.SanitiseDate("05/05/1900"));
    assertEquals("", StringUtil.SanitiseDate("01/01/1989"));
    assertEquals("1901-01-01", StringUtil.SanitiseDate("01/01/1901"));
    assertEquals("2020-02-29", StringUtil.SanitiseDate("29/02/2020"));
    assertEquals("2020-01-29", StringUtil.SanitiseDate("29/01/2020"));
    assertEquals("2020-01-29 01:00:00", StringUtil.SanitiseDate("29/01/2020 01:00:00"));
    assertEquals("", StringUtil.SanitiseDate("12/12/2030 01:00:00"));
    assertEquals("", StringUtil.SanitiseDate("12/12/2030 01:00:00; 12/12/2030 01:00:00;"));
}
Joakim Danielson :

Since you want to handle two different inputs and also generate two kinds of output you need to split the logic between input dates with and without time and handle them separately. I didn't include the formatters but I have split them into two arrays, one for formatters without a time pattern and one for those with a time pattern

if (input.length() < 10) { // maybe add check for >
    return ""; 
}

if (input.length() == 10) {
    for (final DateTimeFormatter format : possibleFormats1) {
        try {
            final LocalDate result = LocalDate.parse(input, format);
            if (result.getYear() <= 1900 || result.getYear() > Year.now().getValue()) {
                return "";
            }
            return result.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } catch (final DateTimeParseException dtpe) {
            // ignore, try next format
        }
    }
} else {
    for (final DateTimeFormatter format : possibleFormats2) {

        try {
            final LocalDateTime result = LocalDateTime.parse(input, format);
            if (result.getYear() <= 1900 || result.getYear() > Year.now().getValue()) {
                return "";
            }
            return result.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        } catch (final DateTimeParseException dtpe) {
            // ignore, try next format
        }
    }
}
return "";

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=292225&siteId=1