Search code examples
javadatesimpledateformat

Parse string date Unparseable date java


I'm trying to parse a String date like :Mon Dec 28 15:18:16 2021 into some thing like this: yyyy-MM-dd HH:mm:ss z. This is my code.

public void parseDate(String stringDate) throws ParseException {
    SimpleDateFormat formatRecived = new SimpleDateFormat("Www Mmm dd HH:mm:ss YYYY");
    try{
        Date date = formatRecived.parse(stringDate);
        System.out.println(date);
    }catch (ParseException parseException){
        System.out.println(parseException.getMessage());
    }

}

my exception message is Unparseable date: "Mon Dec 28 15:18:16 2021"

can you help me pls?


Solution

  • tl;dr

    LocalDateTime
            .parse(
                    "Tue Dec 28 15:18:16 2021" ,      // Tuesday, not Monday.
                    DateTimeFormatter
                            .ofPattern( "EEE MMM dd HH:mm:ss uuuu" )
                            .withLocale( Locale.US )  // Critical to parsing name of month, day of week, etc.
            )                                         // Returns a `LocalDateTime` object.
            .toString()                               // Returns a `String`, with text in standard ISO 8601 format.
            .replace( "T" , " " )                     // Returns another `String` object.
    

    2021-12-28 15:18:16

    Incorrect data

    To begin with, your input data is flawed. 2021-12-28 was a Tuesday, not a Monday. So your input example should be:

    String input = "Tue Dec 28 15:18:16 2021";
    

    Avoid legacy date-time classes

    You are using terribly flawed date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310.

    Define formatting pattern

    Let's write a formatting pattern that matches our input.

    DateTimeFormatter f =
            DateTimeFormatter
                    .ofPattern( "EEE MMM dd HH:mm:ss uuuu" )
                    .withLocale( Locale.US );
    

    LocalDateTime

    Then parse as a LocalDateTime. This class represents a date with time-of-day, but lacks the context of a time zone or offset-from-UTC.

    LocalDateTime ldt = LocalDateTime.parse( input , f );
    

    Unzoned to zoned?

    Your input string has no time zone or offset. Yet you expect one in your output, where you specify z.

    This makes no sense. You would have to specify a time zone (or offset) you know was intended for the input data. But you have presented insufficient information to make that happen.

    You can apply a ZoneId to a LocalDateTime to get a ZonedDateTime. Adjust to UTC by extracting an Instant.

    ISO 8601

    Otherwise, your desired output text has a format similar to the standard ISO 8601 format used by default in LocalDateTime#toString.

    2021-12-28T15:18:16

    You can replace the T in the middle with a SPACE by doing simple text manipulation. (Or you could define another custom formatting pattern.)

    String output = ldt.toString().replace( "T" , " " ) ;