Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -94,22 +94,17 @@ Function<String, ZonedDateTime> getFunction(String format, ZoneId zoneId, Locale
format = format.substring(1);
}

boolean isUtc = ZoneOffset.UTC.equals(zoneId);

DateFormatter dateFormatter = DateFormatter.forPattern(format)
.withLocale(locale);
// if UTC zone is set here, the time zone specified in the format will be ignored, leading to wrong dates
if (isUtc == false) {
dateFormatter = dateFormatter.withZone(zoneId);
}

final DateFormatter formatter = dateFormatter;
return text -> {
TemporalAccessor accessor = formatter.parse(text);
// if there is no year nor year-of-era, we fall back to the current one and
// fill the rest of the date up with the parsed date
if (accessor.isSupported(ChronoField.YEAR) == false
&& accessor.isSupported(ChronoField.YEAR_OF_ERA) == false
&& accessor.isSupported(WeekFields.of(locale).weekOfWeekBasedYear()) == false) {
&& accessor.isSupported(WeekFields.of(locale).weekBasedYear()) == false) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change unrelated to the timezone issue?

Copy link
Contributor Author

@pgomulka pgomulka Dec 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not related to the timezone issue, but also mentioned by a user #63458 (comment)

I realised I have not added a test case for it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to isolate such a separate fix, so that the commit message is associated with what is being fixed, rather than a seemingly unrelated change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a good idea, better to isolate this change.
A separate PR #65717

int year = LocalDate.now(ZoneOffset.UTC).getYear();
ZonedDateTime newTime = Instant.EPOCH.atZone(ZoneOffset.UTC).withYear(year);
for (ChronoField field : FIELDS) {
Expand All @@ -121,11 +116,9 @@ Function<String, ZonedDateTime> getFunction(String format, ZoneId zoneId, Locale
accessor = newTime.withZoneSameLocal(zoneId);
}

if (isUtc) {
return DateFormatters.from(accessor, locale).withZoneSameInstant(ZoneOffset.UTC);
} else {
return DateFormatters.from(accessor, locale);
}
return DateFormatters.from(accessor, locale, zoneId)
.withZoneSameInstant(zoneId);

};
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,60 @@ public void testParseJavaDefaultYear() {
}

public void testParseWeekBased() {
String format = randomFrom("YYYY-ww");
String format = "YYYY-ww";
ZoneId timezone = DateUtils.of("Europe/Amsterdam");
Function<String, ZonedDateTime> javaFunction = DateFormat.Java.getFunction(format, timezone, Locale.ROOT);
ZonedDateTime dateTime = javaFunction.apply("2020-33");
assertThat(dateTime, equalTo(ZonedDateTime.of(2020,8,10,0,0,0,0,timezone)));
}

public void testParseWeekBasedWithLocale() {
String format = randomFrom("YYYY-ww");
String format = "YYYY-ww";
ZoneId timezone = DateUtils.of("Europe/Amsterdam");
Function<String, ZonedDateTime> javaFunction = DateFormat.Java.getFunction(format, timezone, Locale.US);
ZonedDateTime dateTime = javaFunction.apply("2020-33");
//33rd week of 2020 starts on 9th August 2020 as per US locale
assertThat(dateTime, equalTo(ZonedDateTime.of(2020,8,9,0,0,0,0,timezone)));
}

public void testNoTimezoneOnPatternAndOverride() {
{
String format = "yyyy-MM-dd'T'HH:mm";
ZoneId timezone = ZoneId.of("UTC");
Function<String, ZonedDateTime> javaFunction = DateFormat.Java.getFunction(format, timezone, Locale.ROOT);
// this means that hour will be 10:00 at UTC as timezone was provided on a pattern,
ZonedDateTime dateTime = javaFunction.apply("2020-01-01T01:00");
assertThat(dateTime, equalTo(ZonedDateTime.of(2020, 01, 01, 01, 0, 0, 0, timezone)));
}
{
String format = "yyyy-MM-dd'T'HH:mm";
ZoneId timezone = ZoneId.of("-01:00");
Function<String, ZonedDateTime> javaFunction = DateFormat.Java.getFunction(format, timezone, Locale.ROOT);
// this means that hour will be 10:00 at -01:00 as timezone was provided on a pattern,
ZonedDateTime dateTime = javaFunction.apply("2020-01-01T01:00");
assertThat(dateTime, equalTo(ZonedDateTime.of(2020, 01, 01, 01, 0, 0, 0, timezone)));
}
}

public void testTimezoneOnAPatternAndNonUTCOverride() {
String format = "yyyy-MM-dd'T'HH:mm XXX";
ZoneId timezone = ZoneId.of("-01:00");
Function<String, ZonedDateTime> javaFunction = DateFormat.Java.getFunction(format, timezone, Locale.ROOT);
// this means that hour will be 01:00 at -02:00 as timezone was provided. Converted to -01:00 as requested on timezone -01:00 param

ZonedDateTime dateTime = javaFunction.apply("2020-01-01T01:00 -02:00");
assertThat(dateTime, equalTo(ZonedDateTime.of(2020, 01, 01, 02, 0, 0, 0, timezone)));
}

public void testDefaultHourDefaultedToTimezoneOverride() {
String format = "yyyy-MM-dd";
ZoneId timezone = ZoneId.of("-01:00");
Function<String, ZonedDateTime> javaFunction = DateFormat.Java.getFunction(format, timezone, Locale.ROOT);
// this means that hour will be 00:00 at -01:00 as timezone was provided on in pattern
ZonedDateTime dateTime = javaFunction.apply("2020-01-01");
assertThat(dateTime, equalTo(ZonedDateTime.of(2020, 01, 01, 0, 0, 0, 0, timezone)));
}

public void testParseUnixMs() {
assertThat(DateFormat.UnixMs.getFunction(null, ZoneOffset.UTC, null).apply("1000500").toInstant().toEpochMilli(),
equalTo(1000500L));
Expand Down