1

I've taken all of the answers given on SOF and other websites and tried to do this:

String fromDateTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sssX").format(new DateTime().plusMonths(-6));

But I'm being given the exception:

Exception in thread "main" java.lang.IllegalArgumentException: Cannot format given Object as a Date

What am I doing wrong?

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Marco
  • 322
  • 1
  • 3
  • 15
  • 1
    What `DateTime` class is it you're using? – khelwood Feb 04 '19 at 11:30
  • 2
    Using Joda-Time? Then just stick to it and use its formatter too (not `SimpleDateFormat`, it’s notoriously troublesome, and Joda-Time has got a replacement). Alternatively skip both and use [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/) entirely. – Ole V.V. Feb 04 '19 at 11:30
  • 1
    Or use the new java date time classes: `ZonedDateTime.now().minusMonths(6).toString()`. – Joop Eggen Feb 04 '19 at 11:35
  • @Arnaud That was indeed the problem. A toDate made it right. The actual problem was I had no compilation errors whatsoever. Kinda strange, since there is no connection between Date and DateTime (polymorphism). I wonder how it couldn't give me any tips or even errors. – Marco Feb 04 '19 at 11:39
  • @Marco `Date` and `DateTime` are from unrelated frameworks, so no polymorphic relationship. Just the opposite, the second is from Joda-Time (apparently) and was intended to *replace* the first not supplement. The creator of Joda-Time went on to create its successor, JSR 310 and the *java.time* classes built into Java 8 and later. So no reason to ever again touch the terrible wretched awful `Date` and `Calendar` and `SimpleDateFormat` classes. Use only classes from the *java.time* package. – Basil Bourque Feb 04 '19 at 16:29

2 Answers2

6

java.time

    String fromDateTime = OffsetDateTime.now(ZoneId.systemDefault()).minusMonths(6).toString();
    System.out.println(fromDateTime);

Output when running on my computer just now:

2018-08-04T12:45:34.087966+01:00

java.time is the modern Java date and time API and has effectively replaced Joda-Time. From the home page:

Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).

In the code I am taking advantage of the fact that the java.time classes’ toString methods produce ISO 8601 format, the format you were asking for. I find it unlikely that the extra decimals on the seconds will pose any problem since thay are allowed within the standard.

Joda-Time

    String fromDateTime = new DateTime().minusMonths(6).toString();

Example output:

2018-08-04T12:50:36.071+02:00

new DateTime() only has millisecond precision. You will always get exactly 3 decimals on the seconds.

I gotta use old java libraries, cause I work for a company that uses java version < 8

java.time works nicely on Java 6 and 7 too, and all things being equal I recommend it over Joda-Time. Only if forced to use Java 5, Joda-Time is no doubt the good choice.

  • In Java 8 and later and on newer Android devices (from API level 26) java.time comes built-in.
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

What went wrong in your code?

Your code can be compiled without signs of errors, but issues a java.lang.IllegalArgumentException: Cannot format given Object as a Date when run. This is because a SimpleDateFormat cannot format a Joda-Time DateTime object. We would of course have expected this to be reported on compile time. But in addition to SimpleDateFormat.format(Date) there is also an overridden format(Object) inherited from Format. It works for formatting either a Date or a Number (for milliseconds since the epoch). This method is the one that the compiler chooses when you pass a DateTime. Which is why there is no compile-time error message.

Tip: When you don’t immediately understand an error message, paste it into your search engine. It will very often lead you to an explanation and a solution. Also in this case.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • You couldn't be any more specific in ALL aspects. Thank you man, you actually taught me a lot! You just deserved the green check. – Marco Feb 04 '19 at 21:15
1

Try the following:

String fromDateTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sssX").format(new DateTime().minusMonths(6).toDate());

You have to convert the DateTime to a Date before formatting, using the toDate() method will do the job.

API for toDate() and API for minusMonths, I would recommend to you check the API for new methods

nortontgueno
  • 2,553
  • 1
  • 24
  • 36
  • 1
    Will work, but not the recommended way. You are going from the good library (Joda-Time) into the bad one (`Date`and `SimpleDateFormat`). – Ole V.V. Feb 04 '19 at 11:31
  • this indeed solved my problem. But I wonder: you talk about good and bad libraries. What's the point, if eventually I get things working fine? – Marco Feb 04 '19 at 11:34
  • for some scenarios you may have incompatibility problems using multiple libraries, wrong conversion, etc... – nortontgueno Feb 04 '19 at 11:40
  • 1
    @ngueno Yeah you're right, but in my scenario I see no problems at all :p Thanks everybody for your (date_) time! – Marco Feb 04 '19 at 11:41
  • On [this](https://stackoverflow.com/questions/20331163/how-to-format-joda-time-datetime-to-only-mm-dd-yyyy) answer you may find some other examples using other libraries. – nortontgueno Feb 04 '19 at 11:41
  • @Marco SimpleDateFormat is not thread safe. Joda and Java 8 libraries give you thread-safe formatters. It's never recommended to mix different libraries, but using the old Java date-related classes is really to be avoided. – RealSkeptic Feb 04 '19 at 11:42
  • I gotta use old java libraries, cause I work for a company that uses java version < 8 – Marco Feb 04 '19 at 11:44
  • 1
    You should consider rewriting the formatter using [Joda DateTimeFormatter](https://www.joda.org/joda-time/apidocs/org/joda/time/format/DateTimeFormatter.html), which is thread safe and available in the Joda package – nortontgueno Feb 04 '19 at 11:46
  • Ok, I'll do. Thanks for your suggestion – Marco Feb 04 '19 at 11:47
  • The problem with using multiple libraries and/or a bad library is for those maintaining your code. Using two libraries renders the code unnecessarily complex (even though we’re talking just one extra method call in this case). Using a troublesome library class is likely to cause trouble if someone wants to modify the code later (which is likely of your program is to last, say, a couple of years). – Ole V.V. Feb 04 '19 at 11:54