2
String ip="2011-05-01T06:47:35.422-05:00";
ZonedDateTime mzt = ZonedDateTime.parse(ip).toInstant().atZone(ZoneOffset.UTC);
System.out.println(mzt);

System.out.println("-----");

String ip2="2011-05-01T00:00:00.000-05:00";
ZonedDateTime mzt2 = ZonedDateTime.parse(ip2).toInstant().atZone(ZoneOffset.UTC);
System.out.println(mzt2);

Output:

2011-05-01T11:47:35.422Z
-----
2011-05-01T05:00Z

Why is the date format getting changed in case 2? I am getting SQLServer Database error due to this.

Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
  • 1
    By the way, you are using the wrong class for your inputs and your manipulations. `OffsetDateTime` is appropriate here, whereas `ZonedDateTime` is for when you have a time zone, `Continent/Region`, such as `America/Montreal` or `Africa/Tunis`. And when you want UTC, just stick with `Instant`. – Basil Bourque May 02 '18 at 01:19
  • Please read [the class documentation](https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html) before posting a Question on such a simple method call. – Basil Bourque May 02 '18 at 01:25

2 Answers2

7

This is what toString from documentation said

The format used will be the shortest that outputs the full value of the time where the omitted parts are implied to be zero.

To solve this problem, you need another formatter :

String result = mzt2.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSS'Z'"));

Output

2011-05-01T11:47:35.422Z
2011-05-01T05:00:00:000Z
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
  • 1
    Your answer gets the correct result. But i want the ZonedDateTime Object – Sujan Davangere Sunil May 01 '18 at 18:19
  • 1
    @SujanDavangereSunil You already have the `ZonedDateTime Object` but you can't get the expected result because when you try to print this Object It will call the `toString` method so this method will return that result you shared It will ommit the last zeros from the `ZonedDateTime` so can you please share more information about your problem so we can help you to solve it? – Youcef LAIDANI May 01 '18 at 18:23
  • I have printed in System.out here just to see the output. All i want is the ZonedDateTimeObject in that format which case 1 is. – Sujan Davangere Sunil May 01 '18 at 18:27
  • 2
    A `ZonedDateTime` cannot have a format. It only has a `toString` method, and you cannot change how that method works. If you want a specific format, you need to have that format in a `String` (not in a `ZonedDateTime`). This is also a sound distinction: Use a `ZonedDateTime` for your model and a `String` for your presentation. Also, why do you want that specific format when ISO 8601 allows for the freedom that `toString` takes? – Ole V.V. May 01 '18 at 18:34
  • @SujanDavangereSunil read the comment of Ole V.V. please, it answer your previous question – Youcef LAIDANI May 01 '18 at 18:49
  • I want the value of mzt2 to be 2011-05-01T05:00:00:000Z. Using System.out.print will make use of formatter to print this. In my case i am making a entry into Database which needs the ZonedDateTime Object value to be 2011-05-01T05:00:00:000Z – Sujan Davangere Sunil May 13 '18 at 22:40
  • 1
    @SujanDavangereSunil You have an [XY problem](https://meta.stackexchange.com/q/66377/351454) here. You think your problem is that `toString()` is generating the wrong string for insert into database, when your real problem is that you're calling `toString()` at all. Don't convert the date value to a string for insert into database, insert the date value itself. If your JDBC driver cannot handle the new Java Time objects, convert to `Timestamp` instead. – Andreas Jan 30 '20 at 04:50
3

Just to complement YCF_L's answer:

Using a quoted letter in the pattern, like it was done with the Z (it's inside quotes: 'Z') is wrong. This will treat Z as a literal and ignore the object's offset.

For this particular case, it works, but the "Z" in the end means that the date is in UTC, and you can't hardcode it as a literal. Putting it inside quotes will always print "Z" no matter what's the offset, giving wrong results.

Example:

// wrong: it uses Z inside quotes
DateTimeFormatter wrong = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSS'Z'");

// correct: it uses the offset pattern (X)
DateTimeFormatter correct = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSSXXX");

// print a date/time not in UTC
String ip2 = "2011-05-01T00:00:00.000-05:00";
ZonedDateTime mzt = ZonedDateTime.parse(ip2);

System.out.println(mzt.format(wrong)); // 2011-05-01T00:00:00:000Z
System.out.println(mzt.format(correct)); // 2011-05-01T00:00:00:000-05:00

Note that the wrong formatter prints Z, which is wrong, because the offset of mzt is -05:00.

The wrong formatter works for your case because you're using UTC:

// convert to UTC
ZonedDateTime mzt2 = mzt.withZoneSameInstant(ZoneOffset.UTC);
System.out.println(mzt2.format(wrong)); // 2011-05-01T05:00:00:000Z
System.out.println(mzt2.format(correct)); // 2011-05-01T05:00:00:000Z

In this case, both formatters prints the correct result, but that's a coincidence, because mzt2 is in UTC (so the offset is "Z"). But for any offset different than UTC, only the correct formatter will work.

Also note that I used withZoneSameInstant, that has the same result as using .toInstant().atZone(ZoneOffset.UTC).

wowmin
  • 31
  • 1