-2

I have a DateFormat like

DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");

I have a date like this:

2017-02-23T11:00:04.072625

This "date" is a UTC date (Z is null). This parses fine. However, it seems to be interpreted as the timezone of the machine. So, my machine is EST, this ends up as

2017-02-23T11:00:04.072625-0500

Which is wrong. I can explicitly set the timezone with like

format.setTimeZone(TimeZone.getTimeZone("UTC"));

But if the time came in a different zone in the future, that would not be right either.

If I add a "Z" or "z" to the SimpleDateFormat string, this fails to parse.

Any ideas on how to handle this correctly?

MichaelB
  • 1,092
  • 2
  • 16
  • 32
  • 1
    Are you using Java 8? – Markus Benko Feb 28 '17 at 17:50
  • If you set the time zone it will take the value , otherwise it will take your machine time zone by default. You have both options, what are you looking for? – Yohannes Gebremariam Feb 28 '17 at 17:55
  • 1
    Markus, yes Java 8 – MichaelB Feb 28 '17 at 17:57
  • Yohannes, The point is that the date string does infer a timezone, but java thinks it doesnt. – MichaelB Feb 28 '17 at 17:58
  • *But if the time came in a different zone in the future, that would not be right either*: you would then change the parsing code to use this new timezone. There is no way to deduce a timezone from such a format, so you won't be able to find any way to automagically adapt to a different timezone. – JB Nizet Feb 28 '17 at 18:13
  • 1
    This string format is defined by the [ISO 8601](https://en.m.wikipedia.org/wiki/ISO_8601) standard. These standard formats are used by default in the java.time classes. Parsing such strings has been covered *many* times already on Stack Overflow. Please search thoroughly before posting. – Basil Bourque Feb 28 '17 at 19:58

1 Answers1

1

First, since you are using Java 8, start by discarding the old classes Date, DateFormat, SimpleDateFormat and TimeZone. They will more likely than not give you trouble you don’t want. Instead use the classes in java.time introduces in Java 8. Here you go:

    String yourDateTime = "2017-02-23T11:00:04.072625";

    LocalDateTime ldt = LocalDateTime.parse(yourDateTime);
    Instant i = ldt.atOffset(ZoneOffset.UTC).toInstant();

Instant is the new class that best corresponds to the old Date. In this case you get

2017-02-23T11:00:04.072625Z

(Z means UTC)

If in the future you get the date in a different time zone, you may do something like

    ZoneId zi = ZoneId.of("Europe/Paris");
    Instant i = ldt.atZone(zi).toInstant();     

In this case you get instead

2017-02-23T10:00:04.072625Z

Should you for some reason require an oldfashioned Date instance, for example for use with old code, it’s easy:

    Date oldfashionedDate = Date.from(i);
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 1
    Might be simpler to just append the `Z` to the input string and parse as `Instant` directly, skipping the `LocalDateTime` step. `Instant.parse( "2017-02-23T11:00:04.072625" + "Z" )` I'm not saying it is better, just an option. – Basil Bourque Feb 28 '17 at 19:51