0

I have a java.util.Date object. When I format it to String using:

String timeString = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss-Z").format(time);

I get:

2020-03-26-14:40:55-+0200

So, I somehow have the correct time zone (but I can have any time zone, not only +2), this is good.

I want to convert this date to UTC, and then convert it to String. If I send an object with a date to the client, then Jackson will automatically convert it to UTC. But I want to do this manually.

How can I do this?

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
konstantin_doncov
  • 2,725
  • 4
  • 40
  • 100
  • 1
    For what down vote? – konstantin_doncov Mar 26 '20 at 13:08
  • 1
    I recommend you don’t use `SimpleDateFormat` and `Date`. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Instead use for example `OffsetDateTime` and `DateTimeFormatter`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Mar 27 '20 at 05:56
  • 1
    It’s a peculiar format. Wouldn’t you prefer to have a string in [ISO 8601 format](https://en.wikipedia.org/wiki/ISO_8601)? – Ole V.V. Mar 27 '20 at 06:31
  • 2
    Inserting that hyphen before the offset is just bizarre, and terribly confusing. I strongly suggest you stick to using ISO 8601 standard formats. – Basil Bourque Mar 27 '20 at 06:43

2 Answers2

3

It is not recommended anymore to use java.util for date-time operations, especially not for time-zone or offset conversions...

Instead, use java.time:

public static void main(String[] args) {
    // the String (with a strange formatting) to be parsed
    String datetime = "2020-03-26-14:40:55-+0200";
    // parse it to an OffsetDateTime
    OffsetDateTime odt = OffsetDateTime.parse(datetime,
                                    // using a formatter for this specific pattern
                                    DateTimeFormatter.ofPattern("yyyy-MM-dd-HH:mm:ss-x"));
    // print the parsing result
    System.out.println(odt);
    // then convert it to UTC (keeping the moment & adjusting the offset)
    OffsetDateTime odtUtc = odt.withOffsetSameInstant(ZoneOffset.UTC);
    // print the conversion result
    System.out.println(odtUtc);
}

gives you the following output

2020-03-26T14:40:55+02:00
2020-03-26T12:40:55Z
deHaar
  • 17,687
  • 10
  • 38
  • 51
  • Thanks, I know that `java.util.Date` is deprecated. But I really need to use it now. – konstantin_doncov Mar 26 '20 at 13:10
  • @don-prog Can you tell me why you have to use it if what you are trying to get is just a `String`? – deHaar Mar 26 '20 at 13:19
  • Because I have code which has `java.util.Date` as fields everywhere. I don't know how much effort will be needed to migrate – konstantin_doncov Mar 26 '20 at 13:24
  • 1
    @don-prog Depends... You can try to use compatibility methods (I can't really recommend that) or refactor your entire code. If it is too much effort, you will have to stick to the troublesome and error-prone `java.util.Date`, your decision... [There`s more than a single reason for a new datetime API](https://www.oracle.com/technical-resources/articles/java/jf14-date-time.html) – deHaar Mar 26 '20 at 13:26
1

java.time

I understand that you have got a field of type java.util.Date that you cannot afford to change just now. For any operation on that Date you should still convert it to a modern Instant first and then do your further work from there. For converting it to a string in UTC you may use the very simple:

    String timeString = yourJavaUtilDate.toInstant().toString();
    System.out.println(timeString);

Example output:

2020-03-26T12:40:55Z

While an Instant is a point in time without time zone or offset, just like a Date is, Instant.toString() produces a string in UTC in ISO 8601 format, which I find quite nice. If you wanted the peculiar format mentioned in your question (you must have very special reasons for that):

    DateTimeFormatter formatter
            = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH:mm:ss-Z");
    String timeString = yourJavaUtilDate.toInstant()
            .atOffset(ZoneOffset.UTC)
            .format(formatter);

2020-03-26-12:40:55-+0000

Your format pattern string from SimpleDateFormat works with the modern DateTimeFormatter too. That is not always the case, there are differences between the sets of format pattern letters for the two, only many of the letters have the same or similar meaning.

I am myself working with a very old code base that over the years has acquired a messy mixture of outdated and modern date and time classes. So we’re constantly converting back and forth between Date, LocalDate, OffsetDateTime, XMLGregorianCalendar and many other classes, which is far from ideal, and it will take some years still to get to the sweet spot where we will be using the modern classes only.

Links

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