3737import java .time .temporal .ChronoField ;
3838import java .time .temporal .IsoFields ;
3939import java .time .temporal .TemporalAccessor ;
40+ import java .time .temporal .TemporalAdjusters ;
4041import java .time .temporal .TemporalQueries ;
4142import java .time .temporal .TemporalQuery ;
4243import java .time .temporal .WeekFields ;
5253import static java .time .temporal .ChronoField .SECOND_OF_MINUTE ;
5354
5455public class DateFormatters {
55- public static final WeekFields WEEK_FIELDS = WeekFields .of (DayOfWeek .MONDAY ,4 );
56+ // when run with JDK8, WeekFields for Locale.ROOT would return WeekFields.of(DayOfWeek.SUNDAY,1)
57+ public static final WeekFields WEEK_FIELDS_ROOT = WeekFields .of (DayOfWeek .MONDAY ,4 );
5658
5759 private static final DateTimeFormatter TIME_ZONE_FORMATTER_NO_COLON = new DateTimeFormatterBuilder ()
5860 .appendOffset ("+HHmm" , "Z" )
@@ -946,14 +948,14 @@ public class DateFormatters {
946948 * Returns a formatter for a four digit weekyear
947949 */
948950 private static final DateFormatter STRICT_WEEKYEAR = new JavaDateFormatter ("strict_weekyear" , new DateTimeFormatterBuilder ()
949- .appendValue (WEEK_FIELDS .weekBasedYear (), 4 , 10 , SignStyle .EXCEEDS_PAD )
951+ .appendValue (WEEK_FIELDS_ROOT .weekBasedYear (), 4 , 10 , SignStyle .EXCEEDS_PAD )
950952 .toFormatter (Locale .ROOT )
951953 .withResolverStyle (ResolverStyle .STRICT ));
952954
953955 private static final DateTimeFormatter STRICT_WEEKYEAR_WEEK_FORMATTER = new DateTimeFormatterBuilder ()
954- .appendValue (WEEK_FIELDS .weekBasedYear (), 4 , 10 , SignStyle .EXCEEDS_PAD )
956+ .appendValue (WEEK_FIELDS_ROOT .weekBasedYear (), 4 , 10 , SignStyle .EXCEEDS_PAD )
955957 .appendLiteral ("-W" )
956- .appendValue (WEEK_FIELDS .weekOfWeekBasedYear (), 2 , 2 , SignStyle .NOT_NEGATIVE )
958+ .appendValue (WEEK_FIELDS_ROOT .weekOfWeekBasedYear (), 2 , 2 , SignStyle .NOT_NEGATIVE )
957959 .toFormatter (Locale .ROOT )
958960 .withResolverStyle (ResolverStyle .STRICT );
959961
@@ -972,7 +974,7 @@ public class DateFormatters {
972974 new DateTimeFormatterBuilder ()
973975 .append (STRICT_WEEKYEAR_WEEK_FORMATTER )
974976 .appendLiteral ("-" )
975- .appendValue (WEEK_FIELDS .dayOfWeek ())
977+ .appendValue (WEEK_FIELDS_ROOT .dayOfWeek ())
976978 .toFormatter (Locale .ROOT )
977979 .withResolverStyle (ResolverStyle .STRICT ));
978980
@@ -1162,7 +1164,7 @@ public class DateFormatters {
11621164 * Returns a formatter for a four digit weekyear. (YYYY)
11631165 */
11641166 private static final DateFormatter WEEK_YEAR = new JavaDateFormatter ("week_year" ,
1165- new DateTimeFormatterBuilder ().appendValue (WEEK_FIELDS .weekBasedYear ()).toFormatter (Locale .ROOT )
1167+ new DateTimeFormatterBuilder ().appendValue (WEEK_FIELDS_ROOT .weekBasedYear ()).toFormatter (Locale .ROOT )
11661168 .withResolverStyle (ResolverStyle .STRICT ));
11671169
11681170 /*
@@ -1591,9 +1593,9 @@ public class DateFormatters {
15911593 */
15921594 private static final DateFormatter WEEKYEAR_WEEK = new JavaDateFormatter ("weekyear_week" , STRICT_WEEKYEAR_WEEK_FORMATTER ,
15931595 new DateTimeFormatterBuilder ()
1594- .appendValue (WEEK_FIELDS .weekBasedYear ())
1596+ .appendValue (WEEK_FIELDS_ROOT .weekBasedYear ())
15951597 .appendLiteral ("-W" )
1596- .appendValue (WEEK_FIELDS .weekOfWeekBasedYear ())
1598+ .appendValue (WEEK_FIELDS_ROOT .weekOfWeekBasedYear ())
15971599 .toFormatter (Locale .ROOT )
15981600 .withResolverStyle (ResolverStyle .STRICT )
15991601 );
@@ -1606,15 +1608,15 @@ public class DateFormatters {
16061608 new DateTimeFormatterBuilder ()
16071609 .append (STRICT_WEEKYEAR_WEEK_FORMATTER )
16081610 .appendLiteral ("-" )
1609- .appendValue (WEEK_FIELDS .dayOfWeek ())
1611+ .appendValue (WEEK_FIELDS_ROOT .dayOfWeek ())
16101612 .toFormatter (Locale .ROOT )
16111613 .withResolverStyle (ResolverStyle .STRICT ),
16121614 new DateTimeFormatterBuilder ()
1613- .appendValue (WEEK_FIELDS .weekBasedYear ())
1615+ .appendValue (WEEK_FIELDS_ROOT .weekBasedYear ())
16141616 .appendLiteral ("-W" )
1615- .appendValue (WEEK_FIELDS .weekOfWeekBasedYear ())
1617+ .appendValue (WEEK_FIELDS_ROOT .weekOfWeekBasedYear ())
16161618 .appendLiteral ("-" )
1617- .appendValue (WEEK_FIELDS .dayOfWeek ())
1619+ .appendValue (WEEK_FIELDS_ROOT .dayOfWeek ())
16181620 .toFormatter (Locale .ROOT )
16191621 .withResolverStyle (ResolverStyle .STRICT )
16201622 );
@@ -1836,10 +1838,14 @@ static DateFormatter forPattern(String input) {
18361838 * @return The converted zoned date time
18371839 */
18381840 public static ZonedDateTime from (TemporalAccessor accessor ) {
1839- return from (accessor , ZoneOffset .UTC );
1841+ return from (accessor , Locale . ROOT , ZoneOffset .UTC );
18401842 }
18411843
1842- public static ZonedDateTime from (TemporalAccessor accessor , ZoneId defaultZone ) {
1844+ public static ZonedDateTime from (TemporalAccessor accessor , Locale locale ) {
1845+ return from (accessor , locale , ZoneOffset .UTC );
1846+ }
1847+
1848+ public static ZonedDateTime from (TemporalAccessor accessor , Locale locale , ZoneId defaultZone ) {
18431849 if (accessor instanceof ZonedDateTime ) {
18441850 return (ZonedDateTime ) accessor ;
18451851 }
@@ -1862,7 +1868,7 @@ public static ZonedDateTime from(TemporalAccessor accessor, ZoneId defaultZone)
18621868 } else if (isLocalDateSet ) {
18631869 return localDate .atStartOfDay (zoneId );
18641870 } else if (isLocalTimeSet ) {
1865- return of (getLocalDate (accessor ), localTime , zoneId );
1871+ return of (getLocalDate (accessor , locale ), localTime , zoneId );
18661872 } else if (accessor .isSupported (ChronoField .YEAR ) || accessor .isSupported (ChronoField .YEAR_OF_ERA ) ) {
18671873 if (accessor .isSupported (MONTH_OF_YEAR )) {
18681874 return getFirstOfMonth (accessor ).atStartOfDay (zoneId );
@@ -1872,26 +1878,28 @@ public static ZonedDateTime from(TemporalAccessor accessor, ZoneId defaultZone)
18721878 }
18731879 } else if (accessor .isSupported (MONTH_OF_YEAR )) {
18741880 // missing year, falling back to the epoch and then filling
1875- return getLocalDate (accessor ).atStartOfDay (zoneId );
1876- } else if (accessor .isSupported (WEEK_FIELDS .weekBasedYear ())) {
1877- return localDateFromWeekBasedDate (accessor ).atStartOfDay (zoneId );
1881+ return getLocalDate (accessor , locale ).atStartOfDay (zoneId );
1882+ } else if (accessor .isSupported (WeekFields . of ( locale ) .weekBasedYear ())) {
1883+ return localDateFromWeekBasedDate (accessor , locale ).atStartOfDay (zoneId );
18781884 }
18791885
18801886 // we should not reach this piece of code, everything being parsed we should be able to
18811887 // convert to a zoned date time! If not, we have to extend the above methods
18821888 throw new IllegalArgumentException ("temporal accessor [" + accessor + "] cannot be converted to zoned date time" );
18831889 }
18841890
1885- private static LocalDate localDateFromWeekBasedDate (TemporalAccessor accessor ) {
1886- if (accessor .isSupported (WEEK_FIELDS .weekOfWeekBasedYear ())) {
1891+ private static LocalDate localDateFromWeekBasedDate (TemporalAccessor accessor , Locale locale ) {
1892+ WeekFields weekFields = WeekFields .of (locale );
1893+ if (accessor .isSupported (weekFields .weekOfWeekBasedYear ())) {
18871894 return LocalDate .ofEpochDay (0 )
1888- .with (WEEK_FIELDS .weekBasedYear (), accessor .get (WEEK_FIELDS .weekBasedYear ()))
1889- .with (WEEK_FIELDS .weekOfWeekBasedYear (), accessor .get (WEEK_FIELDS .weekOfWeekBasedYear ()))
1890- .with (ChronoField . DAY_OF_WEEK , WEEK_FIELDS .getFirstDayOfWeek (). getValue ( ));
1895+ .with (weekFields .weekBasedYear (), accessor .get (weekFields .weekBasedYear ()))
1896+ .with (weekFields .weekOfWeekBasedYear (), accessor .get (weekFields .weekOfWeekBasedYear ()))
1897+ .with (TemporalAdjusters . previousOrSame ( weekFields .getFirstDayOfWeek ()));
18911898 } else {
18921899 return LocalDate .ofEpochDay (0 )
1893- .with (WEEK_FIELDS .weekBasedYear (), accessor .get (WEEK_FIELDS .weekBasedYear ()))
1894- .with (ChronoField .DAY_OF_WEEK , WEEK_FIELDS .getFirstDayOfWeek ().getValue ());
1900+ .with (weekFields .weekBasedYear (), accessor .get (weekFields .weekBasedYear ()))
1901+ .with (TemporalAdjusters .previousOrSame (weekFields .getFirstDayOfWeek ()));
1902+
18951903 }
18961904 }
18971905
@@ -1922,9 +1930,9 @@ public String toString() {
19221930 }
19231931 };
19241932
1925- private static LocalDate getLocalDate (TemporalAccessor accessor ) {
1926- if (accessor .isSupported (WEEK_FIELDS .weekBasedYear ())) {
1927- return localDateFromWeekBasedDate (accessor );
1933+ private static LocalDate getLocalDate (TemporalAccessor accessor , Locale locale ) {
1934+ if (accessor .isSupported (WeekFields . of ( locale ) .weekBasedYear ())) {
1935+ return localDateFromWeekBasedDate (accessor , locale );
19281936 } else if (accessor .isSupported (MONTH_OF_YEAR )) {
19291937 int year = getYear (accessor );
19301938 if (accessor .isSupported (DAY_OF_MONTH )) {
0 commit comments