2

This is the code:

LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(1451438792953L), ZoneId.of("UTC"));
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd'T'HH:mm:ss.SSS'Z'");
String output = dateTimeFormatter.format(localDateTime);

This is the value of localDateTime:

2015-12-30T01:26:32.953

This is the value of output:

2016-12-30T01:26:32.953Z

Why does it add a year?

In java.time.temporal.WeekFields there are a couple of methods with a newYearWeek which increment the year by 1 on occasion. Why?

This is a strange bug.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
user3268232
  • 227
  • 1
  • 8

2 Answers2

8

From Wikipedia:

[YYYY] indicates the ISO week-numbering year which is slightly different from the traditional Gregorian calendar year (see below).

  1. YYYY is an ISO-8601 style representation of the year.
  2. yyyy is the Gregorian year-of-era representation.

Since the the calculation of the two can be different by +1 or -1, hence the formatting. More useful info at YEAR_OF_ERA, YEAR, and weekBasedYear.

nobeh
  • 9,784
  • 10
  • 49
  • 66
0

There are FIVE problems in your code

Problem#1:

LocalDateTime is not supposed to have time-zone information but you have formatted it in that way by forcibly putting a 'Z' in the DateTimeFormatter pattern.

Problem#2:

Note that 'Z' is not the same as Z. So, you should never use 'Z' in the date-time formatting/parsing API.

Problem#3:

Y (week-based-year) is not the same as y (year-of-era). Check this Q/A to understand more about the difference between these two.

Problem#4:

If all you need to specify is the UTC time-zone offset, you should use ZoneOffset.UTC. A ZoneId is more appropriate to specify a time-zone ID in the Region/Time-zone-reference-city format e.g. Europe/London.

Problem#5:

You do not need a DateTimeFormatter for the output you want. The java.time API is based on ISO 8601 standards and therefore the toString implementation of a java.time type returns a string in ISO 8601 format by default. All you needed is the string representation of Instant:

String output = Instant.ofEpochMilli(1451438792953L).toString();

The Z (stands for Zulu) in the output represents a date-time in UTC and has a ZoneOffset of +00:00.

Demo:

import java.time.Instant;

public class Main {
    public static void main(String[] args) {
        String output = Instant.ofEpochMilli(1451438792953L).toString();
        System.out.println(output);
    }
}

Output:

2015-12-30T01:26:32.953Z

Learn more about the modern Date-Time API from Trail: Date Time.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110