-1

I've tried several methods with Java Joda Time, Date Time with locale and commons-lang and can't get this date formatted.

Input

Mon Dec 28 15:18:16 UTC 2020

Output

Desired output format yyyy-MM-dd HH:mm:ss.SSS

When I use a format pattern like EEE MMM dd HH:mm:ss Z YYYY the date is off my a couple days and the timezone seems completely wrong.

Formatter:

  private static final DateTimeFormatter DATE_TIME_FORMATTER =
    DateTimeFormatter
      .ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
      .withLocale(Locale.US)
      .withZone(ZoneId.systemDefault());
DateUtils.parseDate (Optional
        .ofNullable(record)
        .map(CustomerModel::getCustomerAudit)
        .map(customerAudit::getCreated)
        .map(auditItem::getDate).get ().toString (), "EEE MMM dd HH:mm:ss YYYY")
Ryan
  • 1,102
  • 1
  • 15
  • 30
  • what is the input, what is the code, what is the output? – luk2302 Dec 30 '20 at 18:46
  • @luk2302 updated desire output with the given input. – Ryan Dec 30 '20 at 18:47
  • Could you add which type of class do you use for the input? (String, LocalDate, LocalDateTime) – Andres Sacco Dec 30 '20 at 18:59
  • @OneCricketeer Added some more code – Ryan Dec 30 '20 at 19:01
  • 1
    Do you need commons-lang? java.time classes should work fine – OneCricketeer Dec 30 '20 at 19:02
  • I do not, just been trying different things to get working and struggling – Ryan Dec 30 '20 at 19:02
  • Agree with @OneCricketeer, you should not want to use the old `DateUtils` but prefer java.time throughout. `DateUtils` tried to make up for some of the bad things about the old classes like `Date`, but since we don’t want to use `Date` anymore, we also don’t need `DateUtils`. – Ole V.V. Dec 30 '20 at 20:05
  • The string that you have got no doubt is the result of `toString` from an old-fashioned `java.util.Date` object. For how to parse it see [how to parse output of new Date().toString()](https://stackoverflow.com/questions/4713825/how-to-parse-output-of-new-date-tostring) and [DateTimeParse Exception](https://stackoverflow.com/questions/62105691/datetimeparse-exception) and [Date format parse exception - “EEE MMM dd HH:mm:ss Z yyyy” \[duplicate\]](https://stackoverflow.com/questions/19861642/date-format-parse-exception-eee-mmm-dd-hhmmss-z-yyyy). – Ole V.V. Dec 30 '20 at 20:26

4 Answers4

3

When debugging parsing issues, if possible, reverse the operation and generate the text you're supposed to be parsing, to verify the parsing rules, i.e. the date format string. This applies to date parsing, JAXB parsing, and any other (de)serializing operation that is bi-directional. It makes finding conversion rule issues a lot easier.

So, let us check the format string in the question, with the shown date value:

ZonedDateTime dateTime = ZonedDateTime.of(2020, 12, 28, 15, 18, 16, 0, ZoneOffset.UTC);
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss Z YYYY", Locale.US);
System.out.println(dateTime.format(fmt));

Output

Mon Dec 28 15:18:16 +0000 2021

Oops! That doesn't fit the expected output, aka the input we desire to parse:

Mon Dec 28 15:18:16 UTC 2020

So what went wrong?

  1. The year is wrong because it's supposed to be uuuu (year), not YYYY (week-based-year).

  2. The time zone is wrong because Z does support a text representation. Use VV or z instead.

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z uuuu", Locale.US);

ZonedDateTime dateTime = ZonedDateTime.parse("Mon Dec 28 15:18:16 UTC 2020", fmt);
System.out.println(dateTime);
System.out.println(dateTime.format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS")));

Output

2020-12-28T15:18:16Z[UTC]
2020-12-28 15:18:16.000

As you can see, it now parsed correctly.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • Can this also work with something like 2020-12-28T15:18:17.461525Z[Etc/UTC]? I'm confused on these UTC type values. – Ryan Dec 30 '20 at 19:34
  • 1
    @Ryan That text is the natural format for a [`ZonedDateTime`](https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html), so just call the [`parse(text)`](https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html#parse-java.lang.CharSequence-) method, e.g. `ZonedDateTime.parse("2020-12-28T15:18:17.461525Z[Etc/UTC]")` – Andreas Dec 30 '20 at 19:38
2

The code in the question makes little sense:

  • It is formatting a Date value to text using toString(), just to attempt parsing that back.

  • It is using Optional for simple null-handling (which is discouraged), but then unconditionally calling get(), which means a null value will throw exception anyway.

The code should be:

record.getCustomerAudit().getCreated().getDate().toInstant()

This of course makes the entire question moot.

Andreas
  • 154,647
  • 11
  • 152
  • 247
1

Works fine for me.

String s = "Mon Dec 28 15:18:16 UTC 2020";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss VV yyyy",
                                                          Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(s, formatter);
formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
System.out.println(zdt.format(formatter));

Output is

2020-12-28 15:18:16.000

Am I missing something?

Abra
  • 19,142
  • 7
  • 29
  • 41
  • Can this also work with something like 2020-12-28T15:18:17.461525Z[Etc/UTC]? I'm confused on these UTC type values. – Ryan Dec 30 '20 at 19:35
  • @Ryan What do you mean *with*? The `zdt` in this answer is `2020-12-28T15:18:16Z[UTC]`, it’s somehow close, obviously it hasn’t got the microseconds. We’d like to explain if you can tell us more precisely what’s confusing to you. – Ole V.V. Dec 30 '20 at 20:21
0

Have you tried with SimpleDateFormat?

String dateString = "Mon Dec 28 15:18:16 UTC 2020";

SimpleDateFormat input = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
SimpleDateFormat output = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);

System.out.println(output.format(input.parse(dateString)));

With timezone:

String dateString = "Mon Dec 28 15:18:16 UTC 2020";

SimpleDateFormat input = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
SimpleDateFormat output = new SimpleDateFormat("yyyy-MM-dd z HH:mm:ss.SSS");
input.setTimeZone(TimeZone.getTimeZone("UTC"));
output.setTimeZone(TimeZone.getTimeZone("UTC"));

System.out.println(output.format(input.parse(dateString)));
DarkMatter
  • 1,007
  • 7
  • 13
  • 1
    Please don’t teach the young ones to use the long outdated and notoriously troublesome `SimpleDateFormat` class. At least not as the first option. And not without any reservation. Today we have so much better in [`java.time`, the modern Java date and time API,](https://docs.oracle.com/javase/tutorial/datetime/) and its `DateTimeFormatter`. OP is already using java.time. DarkMatter, you are showing the way backwards, to where we should never want to go again. – Ole V.V. Dec 30 '20 at 20:07
  • Words of wisdom? To be honest, I wouldn't know.. The truth is I despise Date/Time conversions and avoid it like the plague. Mayhaps that time has passed me by in this regard (does that count as a pun?) and I'm left in the past. But, SimpleDateFormat has always served me well. Do feel free, however, to edit my answer and add a warning to future generations if you feel like it. (In my defense I'd like to add, my answer was hardly the first.) Well met @OleV.V. – DarkMatter Dec 30 '20 at 20:15