Search code examples
javadatesimpledateformat

Change Date Format Java


I am using this code :

final String OLD_FORMAT = "dd-MMM-yy";
final String NEW_FORMAT = "dd/MM/yyyy";

String oldDateString = "16-OCT-19";
String newDateString;
SimpleDateFormat sdf = new SimpleDateFormat(OLD_FORMAT);
Date d = sdf.parse(oldDateString);
sdf.applyPattern(NEW_FORMAT);
newDateString = sdf.format(d);
System.out.println(newDateString);

Is it posible to convert without a conversion to Date first so we don't see the format before (OLD_FORMAT)?

I have a String that can be any format date. example "dd-MM-yyyy", "dd-MMM-yyyy", "dd-MMMM-yyyy", or anything. and I want to format into specific format date "dd/MM/yyyy".


Solution

  • You can definitely use the approach that utilizes a list of possible or expected patterns and give each one a try, but you should use the most optimized library for it instead of one which is only still alive due to a mass of legacy code referencing it.

    tl;dr
    Your friends for this task (since Java 8) are

    • java.time.LocalDate
    • java.time.format.DateTimeFormatter
    • java.time.format.DateTimeFormatterBuilder
    • java.time.format.DateTimeParseException

    Here's an example:

    public static void main(String[] args) {
        // start with an example String
        String oldDateString = "16-OCT-19";
        
        // build up a list of possible / possibly expected patterns
        List<String> patterns = List.of(
                "dd-MM-uu", "dd-MMM-uu", "dd-MMMM-uu",
                "dd-MM-uuuu", "dd-MMM-uuuu", "dd-MMMM-uuuu"
        );
        
        // then build a formatter for the desired output
        DateTimeFormatter outFmt = DateTimeFormatter.ofPattern("dd/MM/uuuu");
        
        // for each pattern in your list
        for (String pattern : patterns) {
            try {
                // build a formatter that
                DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                                                // doesn't care about case
                                                .parseCaseInsensitive()
                                                // uses the current pattern and
                                                .appendPattern(pattern)
                                                // considers the language/locale
                                                .toFormatter(Locale.ENGLISH);
                // then try to parse the String with that formatter and
                LocalDate localDate = LocalDate.parse(oldDateString, dtf);
                // print it using the desired output formatter
                System.out.println(localDate.format(outFmt));
                // finally stop the iteration in case of success
                break;
            } catch (DateTimeParseException dtpEx) {
                // build some meaningful statements
                String msg = String.format(
                                "%s !\n  ——> you cannot parse '%s' using pattern %s",
                                dtpEx.getMessage(), oldDateString, pattern);
                // and print it for each parsing fail
                System.err.println(msg);
            }
        }
    }
    

    Try it with different inputs and maybe extend the pattern list.

    However, this code example fails for the first pattern in the list but the second one is a match, so this prints

    Text '16-OCT-19' could not be parsed at index 3 !
      ——> you cannot parse '16-OCT-19' using pattern dd-MM-uu
    16/10/2019
    

    The remaining patterns are skipped.