4

Conversion

I have a timestamp with an offset (-6) in the following format:

2019-11-30T00:01:00.000-06:00

and I want to convert it to an UTC timestamp, like:

2019-11-30T06:01:00.000Z

Attempt

I tried it the following way:

String text = "2019-11-30T00:01:00.000-06:00";

LocalDate date = LocalDate.parse(text, DateTimeFormatter.BASIC_ISO_DATE);

System.out.println(date.toInstant());

but it is not compiling:

The method toInstant() is undefined for the type LocalDate

How am I supposed to do this correctly?

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
F0cus
  • 585
  • 3
  • 18
  • 52
  • 3
    Your _date_ is not just a date, it also has time. It is also not a _local_ date/time, it has offset information. You probably intended to parse this text as `OffsetDateTime` or perhaps as `ZonedDateTime`, and then go to `Instant`. – Zabuzard Apr 25 '23 at 07:57
  • `BASIC_ISO_DATE` will accept `20191130-0600`. As you can see, this is not the format of your string. Also `LocalDate` hasn’t got a `toInstant` method (last time I checked). – Ole V.V. Apr 25 '23 at 08:12
  • 1
    In newer Java versions `Instant.parse()` directly accepts your string. `Instant.parse(date).toString()` yields `2019-11-30T06:01:00Z`. – Ole V.V. Apr 25 '23 at 08:13
  • 3
    @Zabuzard Very nice edit! Thanks. user_che_ban, may this serve as inspiration for your next Stack Overflow questions? – Ole V.V. Apr 25 '23 at 08:15
  • 1
    Do you know for sure that you need the `.000` fraction of second when it is zero? You are asking for [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format, and in ISO 8601 the fraction is optional when it is zero. So the receiver of your string probably doesn’t care. Asking because the classes of java.time (`Instant` and also `OffsetDateTime`) print ISO 8601 from their `toString` methods but include the fraction of second only if it is non-zero. – Ole V.V. Apr 25 '23 at 08:24
  • in the existing application they are setting the value like that , with `.000` , I am also following the same. – F0cus Apr 25 '23 at 08:25

2 Answers2

4

tl;dr

String text = "2019-11-30T00:01:00.000-06:00";
OffsetDateTime offsetDateTime = OffsetDateTime.parse(text);
Instant instant = offsetDateTime.toInstant();

System.out.println(instant); // 2019-11-30T06:01:00Z

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
  .withZone(ZoneOffset.UTC);
System.out.println(formatter.format(instant)); // 2019-11-30T06:01:00.000Z

Explanation

Your date is not just a date, it also has time. So LocalDate would not work. If at all, then LocalDateTime.

But, it is also not a local date/time, it has offset information. You need to use OffsetDateTime instead, and then go to Instant from there.

To actually get the desired output for your Instant, you also have to create a proper DateTimeFormatter, since the default representation does not include the millis.

Zabuzard
  • 25,064
  • 8
  • 58
  • 82
4

Slightly different approach to what Zabuzard posted due to not using an Instant explicitly…

You will need to

  • parse the String,
  • adjust the offset from -06:00 to UTC and then
  • get the desired String representation by means of a DateTimeFormatter

So… tl;dr:

public static void main(String[] args) {
    // example input
    String someDateTime = "2019-11-30T00:01:00.000-06:00";
    // parse directly
    OffsetDateTime odt = OffsetDateTime.parse(someDateTime);
    // define a DateTimeFormatter for the desired output
    DateTimeFormatter dtf = DateTimeFormatter
                                .ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXX");
    // print the parsing result using the DateTimeFormatter
    System.out.println("Origin: " 
            + odt.format(dtf));
    // adjust the offset from -06:00 to UTC
    OffsetDateTime utcOdt = odt.withOffsetSameInstant(ZoneOffset.UTC);
    // print the result — again using the DateTimeFormatter
    System.out.println("UTC:    " 
            + utcOdt.format(dtf));
}

Output:

Origin: 2019-11-30T00:01:00.000-06:00
UTC:    2019-11-30T06:01:00.000Z
deHaar
  • 17,687
  • 10
  • 38
  • 51
  • 2
    Both the posted answers are very good. I tend to prefer this solution, to me the code is a bit clearer. – Ole V.V. Apr 25 '23 at 08:36