1

Is there an easy way to achieve System.currentTimeMillis() to 2017-04-13T19:00:00+08:00 using java.time?

I have tried tremendous amount of methods so far, but it either gives the correct zone but in a wrong language, or does not give any zone at all.

Instant shanghai= Instant.ofEpochMilli(System.currentTimeMillis());
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL)
    .withZone(ZoneId.of("Asia/Shanghai"));
System.out.println(formatter.format(shanghai));

BTW, maybe it's because I haven't used Java 8 time API enough times to see its beauty, but I do feel it as "drawing snake with feet".

For example, withZone sounds like it shifts time result to accommodate zone. But it actually change the language too, which I think should only be related to Locale.

Tiina
  • 4,285
  • 7
  • 44
  • 73

3 Answers3

3

I'm going to suggest by-passing System.currentTimeMillis() and jump straight into the land of java.time:

System.out.println(OffsetDateTime.now());

For me prints: 2017-09-19T06:07:12.814+01:00

Joe C
  • 15,324
  • 8
  • 38
  • 50
3

The long returned by methods like System.currentTimeMillis() representing the milliseconds since the epoch describes an Instant (instantaneous point) on the time line and can be converted to an object representation using Instant.ofEpochMilli(…)

long l = System.currentTimeMillis();
System.out.println(Instant.ofEpochMilli(l));
2017-09-19T08:17:37.054Z

To convert it to a datetime with offset, you can use OffsetDateTime.ofInstant(…):

System.out.println(
    OffsetDateTime.ofInstant(Instant.ofEpochMilli(l), ZoneId.of("Asia/Shanghai")));
2017-09-19T16:17:37.054+08:00

Note that a formatter is not necessary here.

Holger
  • 285,553
  • 42
  • 434
  • 765
1

I finally got the ISO8601 time!

Instant shanghai = Instant.ofEpochMilli(System.currentTimeMillis());
OffsetDateTime o = OffsetDateTime.ofInstant(shanghai,ZoneId.systemDefault());
DateTimeFormatter dtf = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
System.out.println(dtf.format(o));

After DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(Instant.now()) complains something wrong with the offset, and after DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(...) complains about the year...

Tiina
  • 4,285
  • 7
  • 44
  • 73
  • Just keep in mind that the JVM default timezone [can be changed without notice, even at runtime](https://stackoverflow.com/a/45797132/7605325). If you know that the output must be in a specific zone (such as `Asia/Shanghai`), it's better to use the specific zone name (instead of `systemDefault()`), as explained in [@Holger's answer](https://stackoverflow.com/a/46295351/7605325) –  Sep 19 '17 at 18:03
  • @Hugo I am confused about new time api, like how to just change its zone, and how to just change its language, or difference between zone and locale. It seems that what Holger did with `OffsetDateTime`, would change the language too when using `DateTimeFormatter`. You see, they both specify a zone but behave inconsistently. – Tiina Sep 20 '17 at 00:31
  • A locale specify language sensitive data (if you use a formatter created with ofLocalizedDateTime, for example, it'll use the JVM default locale). The dates objects themselves, though, don't have any language specific data. Holger changed only the offset, and the formatter may change the language –  Sep 20 '17 at 00:36
  • A good starting point for the java.time API is [oracle's tutorial](https://docs.oracle.com/javase/tutorial/datetime/index.html). And for locales, there's [another tutorial](https://docs.oracle.com/javase/tutorial/i18n/locale/index.html) –  Sep 20 '17 at 00:43
  • But basically the OffsetDateTime has only the values that correspond to a date/time and offset. And the DateTimeFormatter can format these values in different formats, including different languages. But the values themselves don't change, just their representation. Example: the OffsetDateTime that has the value equivalent to `2017-09-19T16:17:37.054+08:00` can be formatted in many ways, such as `September 19th 2017`, `19/09/2017 16:17` and so on. The value (the date) is always the same and it's part of the OffsetDateTime, but the format is different and it can be changed by a DateTimeFormatter –  Sep 20 '17 at 00:48