1

I´m trying to pase the next String using LocalDateTime, but I always get de unparsed text found error:

java.time.format.DateTimeParseException: Text '2020-10-16T18:04:59+0300' could not be parsed at index 24

Need: from 2020-10-16T18:04:59+0300 to 2020-10-16 18:04.

My code:

    public String getFormattingData(String sourceData) {
        DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ''e", Locale.ENGLISH);
        DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern("dd-MM-yyy HH:mm", Locale.ENGLISH);
        LocalDate date = LocalDate.parse("2020-10-16T18:04:59+0300", sourceFormatter);
        return newFormatter.format(date);
    }

What am I doing wrong?

NeverSleeps
  • 1,439
  • 1
  • 11
  • 39
  • 1
    What's that `''e` doing at the end of the pattern there? – Sweeper Oct 17 '20 at 00:46
  • I added this for +0300. I think my pattern is wrong – NeverSleeps Oct 17 '20 at 00:49
  • 2
    `Z` already matches `+0300`. What did you think the `Z` was doing? :-) – Sweeper Oct 17 '20 at 00:51
  • Related question: [Format a date using the new date time API](https://stackoverflow.com/questions/23069370/format-a-date-using-the-new-date-time-api) – geocodezip Oct 17 '20 at 01:26
  • Use type ZonedDateTime or OffsetDateTime for zoned time, read more here: https://stackoverflow.com/questions/32437550/whats-the-difference-between-instant-and-localdatetime . Answer with 900+ upvotes. – DigitShifter Oct 17 '20 at 07:15
  • Thanks, @DigitShifter, for the link. According to it `OffsetDateTime` is the good fit for the situation in this question, not `ZonedDateTime`. – Ole V.V. Oct 17 '20 at 07:20
  • Try this for both Zoned and Offset Type: DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm", Locale.ENGLISH); String stringFromOffset = OffsetDateTime.parse("2020-10-16T18:04:59+03:00").format(dateTimeFormatter); String stringFromZoned = ZonedDateTime.parse("2020-10-16T18:04:59+03:00").format(dateTimeFormatter); System.out.println(stringFromOffset); System.out.println(stringFromZoned); – DigitShifter Oct 17 '20 at 08:23

3 Answers3

2

See the related question: Format a date using the new date time API

  1. The source format you are looking for is: "yyyy-MM-dd'T'HH:mm:ssZ" (as mentioned by @Sweeper in his comment)
  2. If you want the HH:mm in the output format, you need to use a LocalDateTime rather than a LocalDate

The code below works for me:

public String getFormattingData(String sourceData) {
    DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ", Locale.ENGLISH);
    DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm", Locale.ENGLISH);
    LocalDateTime date = LocalDateTime.parse("2020-10-16T18:04:59+0300", sourceFormatter);
    return newFormatter.format(date);

result:

16-10-2020 18:04

geocodezip
  • 158,664
  • 13
  • 220
  • 245
1

You just need to correct the date pattern of source date like this:

public static String formatDate(String strDate, String srcPattern, String tgtPattern) {
  DateTimeFormatter srcFormatter = DateTimeFormatter.ofPattern(srcPattern, Locale.ENGLISH);
  DateTimeFormatter tgtFormatter = DateTimeFormatter.ofPattern(tgtPattern, Locale.ENGLISH);
  return tgtFormatter.format(LocalDateTime.parse(strDate, srcFormatter));
}

You can also use SimpleDateFormat:

public static String formatDate(String strDate, String srcPattern,
    String tgtPattern) throws ParseException {
  SimpleDateFormat srcFormatter = new SimpleDateFormat(srcPattern, Locale.ENGLISH);
  SimpleDateFormat tgtFormatter = new SimpleDateFormat(tgtPattern, Locale.ENGLISH);
  return tgtFormatter.format(srcFormatter.parse(strDate));
}

And then call it with any pattern that you want:

System.out.println(formatDate("2020-10-16T18:04:59+0300", "yyyy-MM-dd'T'HH:mm:ssZ", "dd-MM-yyy HH:mm"));
1218985
  • 7,531
  • 2
  • 25
  • 31
  • Using `SimpleDateFormat` is a horrible idea, excuse my frankness. That class is a notorious troublemaker and long outdated. Staying with `DateTimeFormatter` is the wise choice. – Ole V.V. Oct 17 '20 at 05:57
1
  1. Don’t write a method that converts a date and time from a string in one format to a string in a different format. In your program keep dates and times as proper date-time objects. Just like you don’t keep numbers and Boolean values in strings (I hope!) When you receive string input, parse into a date-time object at once. Only when you need to give string output, format into an appropriate string.
  2. When I receive a string containing date, time and UTC offset, like yours does, I prefer to parse it into a OffsetDateTime so I get all the information. It’s easier to throw unneeded information away later than to invent the information that we neglected to parse. Also a LocalDate will not work for your purpose since it doesn’t contain time of day. So you cannot format one into 2020-10-16 18:04 format.

For parsing your string I would use:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .appendOffset("+HHmm", "Z")
            .toFormatter();
    
    String sourceData = "2020-10-16T18:04:59+0300";
    
    OffsetDateTime dateTime = OffsetDateTime.parse(sourceData, formatter);
    
    System.out.println(dateTime);

Output is:

2020-10-16T18:04:59+03:00

The definition of the formatter is longish but has the advantage of reusing predefined formatters for date and time.

For displaying a formatted date and time to the user, don’t you want to use the user’s time zone rather then the offset that happened to be in the string (+03:00 in your case)?

    ZoneId zone = ZoneId.of("Antarctica/South_Pole");
    DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm", Locale.ENGLISH);
    String formatted = dateTime.atZoneSameInstant(zone).format(newFormatter);
    System.out.println(formatted);

17-10-2020 04:04

What went wrong in your code?

As others have said, yyyy-MM-dd'T'HH:mm:ssZ in your format pattern string for parsing parses your entire date-time string of 2020-10-16T18:04:59+0300 nicely. The ''e at the end of the format pattern is the culprit. This would require an additional single quote (apostrophe) and the number of the day of the week to be present (pattern letter e is for localized day of week). Since Java had successfully parsed 24 chars and then failed to parse an apostrophe, it threw the exception mentioning thst the string could not be parsed at index 24.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161