Closed jodastephen closed 11 years ago
diff -r 6bbcad16b876 src/share/classes/java/time/temporal/WeekFields.java
--- a/src/share/classes/java/time/temporal/WeekFields.java Sun May 26 00:05:48 2013 +0100
+++ b/src/share/classes/java/time/temporal/WeekFields.java Thu May 30 01:02:29 2013 +0100
@@ -75,6 +75,7 @@
import java.io.InvalidObjectException;
import java.io.Serializable;
+import java.time.DateTimeException;
import java.time.DayOfWeek;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.Chronology;
@@ -395,6 +396,11 @@
* <p>
* For example, if the first day-of-week is Sunday, then that will have the
* value 1, with other days ranging from Monday as 2 to Saturday as 7.
+ * <p>
+ * In the resolving phase of parsing, a localized day-of-week will be converted
+ * to a standardized {@code ChronoField} day-of-week.
+ * The day-of-week must be in the valid range 1 to 7.
+ * Other fields in this class build dates using the standardized day-of-week.
*
* @return a field providing access to the day-of-week with localized numbering, not null
*/
@@ -421,6 +427,26 @@
* - if the 5th day of the month is a Monday, week two starts on the 5th and the 1st to 4th is in week one<br>
* <p>
* This field can be used with any calendar system.
+ * <p>
+ * In the resolving phase of parsing, a date can be created from a year,
+ * week-of-month, month-of-year and day-of-week.
+ * <p>
+ * In {@linkplain ResolverStyle#STRICT strict mode}, all four fields are
+ * validated against their range of valid values. The week-of-month field
+ * is validated to ensure that the resulting month is the month requested.
+ * <p>
+ * In {@linkplain ResolverStyle#SMART smart mode}, all four fields are
+ * validated against their range of valid values. The week-of-month field
+ * is validated from 0 to 6, meaning that the resulting date can be in a
+ * different month to that specified.
+ * <p>
+ * In {@linkplain ResolverStyle#LENIENT lenient mode}, the year and day-of-week
+ * are validated against the range of valid values. The resulting date is calculated
+ * equivalent to the following four stage approach.
+ * First, create a date on the first day of the first week of January in the requested year.
+ * Then take the month-of-year, subtract one, and add the amount in months to the date.
+ * Then take the week-of-month, subtract one, and add the amount in weeks to the date.
+ * Finally, adjust to the correct day-of-week within the localized week.
*
* @return a field providing access to the week-of-month, not null
*/
@@ -447,6 +473,25 @@
* - if the 5th day of the year is a Monday, week two starts on the 5th and the 1st to 4th is in week one<br>
* <p>
* This field can be used with any calendar system.
+ * <p>
+ * In the resolving phase of parsing, a date can be created from a year,
+ * week-of-year and day-of-week.
+ * <p>
+ * In {@linkplain ResolverStyle#STRICT strict mode}, all three fields are
+ * validated against their range of valid values. The week-of-year field
+ * is validated to ensure that the resulting year is the year requested.
+ * <p>
+ * In {@linkplain ResolverStyle#SMART smart mode}, all three fields are
+ * validated against their range of valid values. The week-of-month field
+ * is validated from 0 to 54, meaning that the resulting date can be in a
+ * different year to that specified.
+ * <p>
+ * In {@linkplain ResolverStyle#LENIENT lenient mode}, the year and day-of-week
+ * are validated against the range of valid values. The resulting date is calculated
+ * equivalent to the following three stage approach.
+ * First, create a date on the first day of the first week in the requested year.
+ * Then take the week-of-year, subtract one, and add the amount in weeks to the date.
+ * Finally, adjust to the correct day-of-week within the localized week.
*
* @return a field providing access to the week-of-year, not null
*/
@@ -477,6 +522,26 @@
* the 1st to 4th is in week one<br>
* <p>
* This field can be used with any calendar system.
+ * <p>
+ * In the resolving phase of parsing, a date can be created from a week-based-year,
+ * week-of-year and day-of-week.
+ * <p>
+ * In {@linkplain ResolverStyle#STRICT strict mode}, all three fields are
+ * validated against their range of valid values. The week-of-year field
+ * is validated to ensure that the resulting week-based-year is the
+ * week-based-year requested.
+ * <p>
+ * In {@linkplain ResolverStyle#SMART smart mode}, all three fields are
+ * validated against their range of valid values. The week-of-week-based-year field
+ * is validated from 1 to 53, meaning that the resulting date can be in the
+ * following week-based-year to that specified.
+ * <p>
+ * In {@linkplain ResolverStyle#LENIENT lenient mode}, the year and day-of-week
+ * are validated against the range of valid values. The resulting date is calculated
+ * equivalent to the following three stage approach.
+ * First, create a date on the first day of the first week in the requested week-based-year.
+ * Then take the week-of-week-based-year, subtract one, and add the amount in weeks to the date.
+ * Finally, adjust to the correct day-of-week within the localized week.
*
* @return a field providing access to the week-of-week-based-year, not null
*/
@@ -499,6 +564,26 @@
* is in the last week of the previous year.
* <p>
* This field can be used with any calendar system.
+ * <p>
+ * In the resolving phase of parsing, a date can be created from a week-based-year,
+ * week-of-year and day-of-week.
+ * <p>
+ * In {@linkplain ResolverStyle#STRICT strict mode}, all three fields are
+ * validated against their range of valid values. The week-of-year field
+ * is validated to ensure that the resulting week-based-year is the
+ * week-based-year requested.
+ * <p>
+ * In {@linkplain ResolverStyle#SMART smart mode}, all three fields are
+ * validated against their range of valid values. The week-of-week-based-year field
+ * is validated from 1 to 53, meaning that the resulting date can be in the
+ * following week-based-year to that specified.
+ * <p>
+ * In {@linkplain ResolverStyle#LENIENT lenient mode}, the year and day-of-week
+ * are validated against the range of valid values. The resulting date is calculated
+ * equivalent to the following three stage approach.
+ * First, create a date on the first day of the first week in the requested week-based-year.
+ * Then take the week-of-week-based-year, subtract one, and add the amount in weeks to the date.
+ * Finally, adjust to the correct day-of-week within the localized week.
*
* @return a field providing access to the week-based-year, not null
*/
@@ -801,66 +886,114 @@
@Override
public Map<TemporalField, Long> resolve(TemporalAccessor temporal, long value, ResolverStyle resolverStyle) {
- int newValue = range.checkValidIntValue(value, this);
- int sow = weekDef.getFirstDayOfWeek().getValue();
+ final int newValue = Math.toIntExact(value); // broad limit makes overflow checking lighter
+ // first convert localized day-of-week to ISO day-of-week
+ // doing this first handles case where both ISO and localized were parsed and might mismatch
+ // day-of-week is always strict as two different day-of-week values makes lenient complex
if (rangeUnit == WEEKS) { // day-of-week
- int isoDow = Math.floorMod((sow - 1) + (newValue - 1), 7) + 1;
- return Collections.<TemporalField, Long>singletonMap(DAY_OF_WEEK, (long) isoDow);
+ final int checkedValue = range.checkValidIntValue(value, this); // no leniency as too complex
+ final int startDow = weekDef.getFirstDayOfWeek().getValue();
+ long isoDow = Math.floorMod((startDow - 1) + (checkedValue - 1), 7) + 1;
+ return Collections.<TemporalField, Long>singletonMap(DAY_OF_WEEK, isoDow);
}
+
+ // can only build date if ISO day-of-week is present
if (temporal.isSupported(DAY_OF_WEEK) == false) {
return null;
}
+ int dow = localizedDayOfWeek(temporal);
+
+ // build date
Chronology chrono = Chronology.from(temporal); // defaults to ISO
- int dow = localizedDayOfWeek(temporal);
if (temporal.isSupported(YEAR)) {
- int year = temporal.get(YEAR);
- if (rangeUnit == MONTHS) { // week-of-month
- if (temporal.isSupported(MONTH_OF_YEAR) == false) {
- return null;
- }
- int month = temporal.get(ChronoField.MONTH_OF_YEAR);
- @SuppressWarnings("rawtypes")
- ChronoLocalDate date = chrono.date(year, month, 1);
- int dateDow = localizedDayOfWeek(date);
- long weeks = newValue - localizedWeekOfMonth(date);
- int days = dow - dateDow;
- date = date.plus(weeks * 7 + days, DAYS);
- Map<TemporalField, Long> result = new HashMap<>(4, 1.0f);
- result.put(EPOCH_DAY, date.toEpochDay());
- result.put(YEAR, null);
- result.put(MONTH_OF_YEAR, null);
- result.put(DAY_OF_WEEK, null);
- return result;
- } else if (rangeUnit == YEARS) { // week-of-year
- @SuppressWarnings("rawtypes")
- ChronoLocalDate date = chrono.date(year, 1, 1);
- int dateDow = localizedDayOfWeek(date);
- long weeks = newValue - localizedWeekOfYear(date);
- int days = dow - dateDow;
- date = date.plus(weeks * 7 + days, DAYS);
- Map<TemporalField, Long> result = new HashMap<>(4, 1.0f);
- result.put(EPOCH_DAY, date.toEpochDay());
- result.put(YEAR, null);
- result.put(DAY_OF_WEEK, null);
- return result;
+ int year = temporal.get(YEAR); // validate
+ if (rangeUnit == MONTHS && temporal.isSupported(MONTH_OF_YEAR)) { // week-of-month
+ long month = temporal.getLong(MONTH_OF_YEAR); // not validates yet
+ return resolveWoM(chrono, year, month, newValue, dow, resolverStyle);
}
- } else if (rangeUnit == WEEK_BASED_YEARS || rangeUnit == FOREVER) {
- if (temporal.isSupported(weekDef.weekBasedYear) &&
- temporal.isSupported(weekDef.weekOfWeekBasedYear)) {
- // week-of-week-based-year and year-of-week-based-year
- int yowby = temporal.get(weekDef.weekBasedYear);
- int wowby = temporal.get(weekDef.weekOfWeekBasedYear);
- ChronoLocalDate<?> date = ofWeekBasedYear(Chronology.from(temporal), yowby, wowby, dow);
+ if (rangeUnit == YEARS) { // week-of-year
+ return resolveWoY(chrono, year, newValue, dow, resolverStyle);
+ }
+ } else if ((rangeUnit == WEEK_BASED_YEARS || rangeUnit == FOREVER) &&
+ temporal.isSupported(weekDef.weekBasedYear) &&
+ temporal.isSupported(weekDef.weekOfWeekBasedYear)) { // week-of-week-based-year and year-of-week-based-year
+ return resolveWBY(chrono, temporal, dow, resolverStyle);
+ }
+ return null;
+ }
- Map<TemporalField, Long> result = new HashMap<>(4, 1.0f);
- result.put(EPOCH_DAY, date.toEpochDay());
- result.put(DAY_OF_WEEK, null);
- result.put(weekDef.weekOfWeekBasedYear, null);
- result.put(weekDef.weekBasedYear, null);
- return result;
+ private Map<TemporalField, Long> resolveWoM(
+ Chronology chrono, int year, long month, long wom, int localDow, ResolverStyle resolverStyle) {
+ ChronoLocalDate<?> date;
+ if (resolverStyle == ResolverStyle.LENIENT) {
+ date = chrono.date(year, 1, 1).plus(Math.subtractExact(month, 1), MONTHS);
+ long weeks = Math.subtractExact(wom, localizedWeekOfMonth(date));
+ int days = localDow - localizedDayOfWeek(date); // safe from overflow
+ date = date.plus(Math.addExact(Math.multiplyExact(weeks, 7), days), DAYS);
+ } else {
+ int monthValid = MONTH_OF_YEAR.checkValidIntValue(month); // validate
+ date = chrono.date(year, monthValid, 1);
+ int womInt = range.checkValidIntValue(wom, this); // validate
+ int weeks = (int) (womInt - localizedWeekOfMonth(date)); // safe from overflow
+ int days = localDow - localizedDayOfWeek(date); // safe from overflow
+ date = date.plus(weeks * 7 + days, DAYS);
+ if (resolverStyle == ResolverStyle.STRICT && date.getLong(MONTH_OF_YEAR) != month) {
+ throw new DateTimeException("Strict mode rejected resolved date as it is in a different month");
}
}
- return null;
+ Map<TemporalField, Long> result = new HashMap<>(4, 1.0f);
+ result.put(YEAR, null);
+ result.put(MONTH_OF_YEAR, null);
+ result.put(DAY_OF_WEEK, null);
+ result.put(EPOCH_DAY, date.toEpochDay());
+ return result;
+ }
+
+ private Map<TemporalField, Long> resolveWoY(
+ Chronology chrono, int year, long woy, int localDow, ResolverStyle resolverStyle) {
+ ChronoLocalDate<?> date = chrono.date(year, 1, 1);
+ if (resolverStyle == ResolverStyle.LENIENT) {
+ long weeks = Math.subtractExact(woy, localizedWeekOfYear(date));
+ int days = localDow - localizedDayOfWeek(date); // safe from overflow
+ date = date.plus(Math.addExact(Math.multiplyExact(weeks, 7), days), DAYS);
+ } else {
+ int womInt = range.checkValidIntValue(woy, this); // validate
+ int weeks = (int) (womInt - localizedWeekOfYear(date)); // safe from overflow
+ int days = localDow - localizedDayOfWeek(date); // safe from overflow
+ date = date.plus(weeks * 7 + days, DAYS);
+ if (resolverStyle == ResolverStyle.STRICT && date.getLong(YEAR) != year) {
+ throw new DateTimeException("Strict mode rejected resolved date as it is in a different year");
+ }
+ }
+ Map<TemporalField, Long> result = new HashMap<>(4, 1.0f);
+ result.put(YEAR, null);
+ result.put(DAY_OF_WEEK, null);
+ result.put(EPOCH_DAY, date.toEpochDay());
+ return result;
+ }
+
+ private Map<TemporalField, Long> resolveWBY(
+ Chronology chrono, TemporalAccessor temporal, int localDow, ResolverStyle resolverStyle) {
+ int yowby = temporal.get(weekDef.weekBasedYear);
+ ChronoLocalDate<?> date;
+ if (resolverStyle == ResolverStyle.LENIENT) {
+ date = ofWeekBasedYear(chrono, yowby, 1, localDow);
+ long wowby = temporal.getLong(weekDef.weekOfWeekBasedYear);
+ long weeks = Math.subtractExact(wowby, 1);
+ date = date.plus(weeks, WEEKS);
+ } else {
+ int wowby = temporal.get(weekDef.weekOfWeekBasedYear); // validate
+ date = ofWeekBasedYear(chrono, yowby, wowby, localDow);
+ if (resolverStyle == ResolverStyle.STRICT && localizedWeekBasedYear(date) != yowby) {
+ throw new DateTimeException("Strict mode rejected resolved date as it is in a different week-based-year");
+ }
+ }
+ Map<TemporalField, Long> result = new HashMap<>(4, 1.0f);
+ result.put(weekDef.weekBasedYear, null);
+ result.put(weekDef.weekOfWeekBasedYear, null);
+ result.put(DAY_OF_WEEK, null);
+ result.put(EPOCH_DAY, date.toEpochDay());
+ return result;
}
//-----------------------------------------------------------------------
diff -r 6bbcad16b876 test/java/time/tck/java/time/temporal/TCKWeekFields.java
--- a/test/java/time/tck/java/time/temporal/TCKWeekFields.java Sun May 26 00:05:48 2013 +0100
+++ b/test/java/time/tck/java/time/temporal/TCKWeekFields.java Thu May 30 01:02:29 2013 +0100
@@ -56,6 +56,10 @@
*/
package tck.java.time.temporal;
+import static java.time.format.ResolverStyle.LENIENT;
+import static java.time.format.ResolverStyle.SMART;
+import static java.time.format.ResolverStyle.STRICT;
+import static java.time.temporal.ChronoField.AMPM_OF_DAY;
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoField.DAY_OF_WEEK;
import static java.time.temporal.ChronoField.DAY_OF_YEAR;
@@ -64,14 +68,20 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertSame;
+import static org.testng.Assert.fail;
import java.io.IOException;
+import java.time.DateTimeException;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
+import java.time.format.ResolverStyle;
import java.time.temporal.ChronoUnit;
+import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
+import java.time.temporal.TemporalQuery;
import java.time.temporal.ValueRange;
import java.time.temporal.WeekFields;
@@ -376,14 +386,13 @@
TemporalField womField = week.weekOfMonth();
for (int i = 1; i <= 60; i++) {
- // Test that with dayOfWeek and Week of month it computes the date
DateTimeFormatter f = new DateTimeFormatterBuilder()
- .appendValue(YEAR).appendLiteral('-')
- .appendValue(MONTH_OF_YEAR).appendLiteral('-')
- .appendValue(womField).appendLiteral('-')
- .appendValue(DAY_OF_WEEK).toFormatter();
- String str = date.getYear() + "-" + date.getMonthValue() + "-" +
- date.get(womField) + "-" + date.get(DAY_OF_WEEK);
+ .appendValue(YEAR).appendLiteral(':')
+ .appendValue(MONTH_OF_YEAR).appendLiteral(':')
+ .appendValue(womField).appendLiteral(':')
+ .appendValue(DAY_OF_WEEK).toFormatter().withResolverStyle(SMART);
+ String str = date.getYear() + ":" + date.getMonthValue() + ":" +
+ date.get(womField) + ":" + date.get(DAY_OF_WEEK);
LocalDate parsed = LocalDate.parse(str, f);
assertEquals(parsed, date, " ::" + str + "::" + i);
@@ -392,6 +401,52 @@
}
@Test(dataProvider="weekFields")
+ public void test_parse_resolve_localizedWom_lenient(DayOfWeek firstDayOfWeek, int minDays) {
+ LocalDate date = LocalDate.of(2012, 12, 15);
+ WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
+ TemporalField womField = week.weekOfMonth();
+
+ for (int i = 1; i <= 60; i++) {
+ DateTimeFormatter f = new DateTimeFormatterBuilder()
+ .appendValue(YEAR).appendLiteral(':')
+ .appendValue(MONTH_OF_YEAR).appendLiteral(':')
+ .appendValue(womField).appendLiteral(':')
+ .appendValue(DAY_OF_WEEK).toFormatter().withResolverStyle(LENIENT);
+ int wom = date.get(womField);
+ int dow = date.get(DAY_OF_WEEK);
+ for (int j = wom - 10; j < wom + 10; j++) {
+ String str = date.getYear() + ":" + date.getMonthValue() + ":" + j + ":" + dow;
+ LocalDate parsed = LocalDate.parse(str, f);
+ assertEquals(parsed, date.plusWeeks(j - wom), " ::" + str + ": :" + i + "::" + j);
+ }
+
+ date = date.plusDays(1);
+ }
+ }
+
+ @Test(dataProvider="weekFields")
+ public void test_parse_resolve_localizedWom_strict(DayOfWeek firstDayOfWeek, int minDays) {
+ WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
+ TemporalField womField = week.weekOfMonth();
+ DateTimeFormatter f = new DateTimeFormatterBuilder()
+ .appendValue(YEAR).appendLiteral(':')
+ .appendValue(MONTH_OF_YEAR).appendLiteral(':')
+ .appendValue(womField).appendLiteral(':')
+ .appendValue(DAY_OF_WEEK).toFormatter().withResolverStyle(STRICT);
+ String str = "2012:1:0:1";
+ try {
+ LocalDate date = LocalDate.parse(str, f);
+ assertEquals(date.getYear(), 2012);
+ assertEquals(date.getMonthValue(), 1);
+ assertEquals(date.get(womField), 0);
+ assertEquals(date.get(DAY_OF_WEEK), 1);
+ } catch (DateTimeException ex) {
+ // expected
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ @Test(dataProvider="weekFields")
public void test_parse_resolve_localizedWomDow(DayOfWeek firstDayOfWeek, int minDays) {
LocalDate date = LocalDate.of(2012, 12, 15);
WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
@@ -399,14 +454,13 @@
TemporalField womField = week.weekOfMonth();
for (int i = 1; i <= 15; i++) {
- // Test that with dayOfWeek and Week of month it computes the date
DateTimeFormatter f = new DateTimeFormatterBuilder()
- .appendValue(YEAR).appendLiteral('-')
- .appendValue(MONTH_OF_YEAR).appendLiteral('-')
- .appendValue(womField).appendLiteral('-')
+ .appendValue(YEAR).appendLiteral(':')
+ .appendValue(MONTH_OF_YEAR).appendLiteral(':')
+ .appendValue(womField).appendLiteral(':')
.appendValue(dowField).toFormatter();
- String str = date.getYear() + "-" + date.getMonthValue() + "-" +
- date.get(womField) + "-" + date.get(dowField);
+ String str = date.getYear() + ":" + date.getMonthValue() + ":" +
+ date.get(womField) + ":" + date.get(dowField);
LocalDate parsed = LocalDate.parse(str, f);
assertEquals(parsed, date, " :: " + str + " " + i);
@@ -415,20 +469,44 @@
}
@Test(dataProvider="weekFields")
+ public void test_parse_resolve_localizedWomDow_lenient(DayOfWeek firstDayOfWeek, int minDays) {
+ LocalDate date = LocalDate.of(2012, 12, 15);
+ WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
+ TemporalField dowField = week.dayOfWeek();
+ TemporalField womField = week.weekOfMonth();
+
+ for (int i = 1; i <= 60; i++) {
+ DateTimeFormatter f = new DateTimeFormatterBuilder()
+ .appendValue(YEAR).appendLiteral(':')
+ .appendValue(MONTH_OF_YEAR).appendLiteral(':')
+ .appendValue(womField).appendLiteral(':')
+ .appendValue(dowField).toFormatter().withResolverStyle(LENIENT);
+ int wom = date.get(womField);
+ int dow = date.get(dowField);
+ for (int j = wom - 10; j < wom + 10; j++) {
+ String str = date.getYear() + ":" + date.getMonthValue() + ":" + j + ":" + dow;
+ LocalDate parsed = LocalDate.parse(str, f);
+ assertEquals(parsed, date.plusWeeks(j - wom), " ::" + str + ": :" + i + "::" + j);
+ }
+
+ date = date.plusDays(1);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ @Test(dataProvider="weekFields")
public void test_parse_resolve_localizedWoy(DayOfWeek firstDayOfWeek, int minDays) {
LocalDate date = LocalDate.of(2012, 12, 15);
WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
TemporalField woyField = week.weekOfYear();
for (int i = 1; i <= 60; i++) {
- // Test that with dayOfWeek and Week of month it computes the date
DateTimeFormatter f = new DateTimeFormatterBuilder()
- .appendValue(YEAR).appendLiteral('-')
- .appendValue(MONTH_OF_YEAR).appendLiteral('-')
- .appendValue(woyField).appendLiteral('-')
+ .appendValue(YEAR).appendLiteral(':')
+ .appendValue(woyField).appendLiteral(':')
.appendValue(DAY_OF_WEEK).toFormatter();
- String str = date.getYear() + "-" + date.getMonthValue() + "-" +
- date.get(woyField) + "-" + date.get(DAY_OF_WEEK);
+ String str = date.getYear() + ":" +
+ date.get(woyField) + ":" + date.get(DAY_OF_WEEK);
LocalDate parsed = LocalDate.parse(str, f);
assertEquals(parsed, date, " :: " + str + " " + i);
@@ -437,6 +515,49 @@
}
@Test(dataProvider="weekFields")
+ public void test_parse_resolve_localizedWoy_lenient(DayOfWeek firstDayOfWeek, int minDays) {
+ LocalDate date = LocalDate.of(2012, 12, 15);
+ WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
+ TemporalField woyField = week.weekOfYear();
+
+ for (int i = 1; i <= 60; i++) {
+ DateTimeFormatter f = new DateTimeFormatterBuilder()
+ .appendValue(YEAR).appendLiteral(':')
+ .appendValue(woyField).appendLiteral(':')
+ .appendValue(DAY_OF_WEEK).toFormatter().withResolverStyle(LENIENT);
+ int woy = date.get(woyField);
+ int dow = date.get(DAY_OF_WEEK);
+ for (int j = woy - 60; j < woy + 60; j++) {
+ String str = date.getYear() + ":" + j + ":" + dow;
+ LocalDate parsed = LocalDate.parse(str, f);
+ assertEquals(parsed, date.plusWeeks(j - woy), " ::" + str + ": :" + i + "::" + j);
+ }
+
+ date = date.plusDays(1);
+ }
+ }
+
+ @Test(dataProvider="weekFields")
+ public void test_parse_resolve_localizedWoy_strict(DayOfWeek firstDayOfWeek, int minDays) {
+ WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
+ TemporalField woyField = week.weekOfYear();
+ DateTimeFormatter f = new DateTimeFormatterBuilder()
+ .appendValue(YEAR).appendLiteral(':')
+ .appendValue(woyField).appendLiteral(':')
+ .appendValue(DAY_OF_WEEK).toFormatter().withResolverStyle(STRICT);
+ String str = "2012:0:1";
+ try {
+ LocalDate date = LocalDate.parse(str, f);
+ assertEquals(date.getYear(), 2012);
+ assertEquals(date.get(woyField), 0);
+ assertEquals(date.get(DAY_OF_WEEK), 1);
+ } catch (DateTimeException ex) {
+ // expected
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ @Test(dataProvider="weekFields")
public void test_parse_resolve_localizedWoyDow(DayOfWeek firstDayOfWeek, int minDays) {
LocalDate date = LocalDate.of(2012, 12, 15);
WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
@@ -444,14 +565,13 @@
TemporalField woyField = week.weekOfYear();
for (int i = 1; i <= 60; i++) {
- // Test that with dayOfWeek and Week of month it computes the date
DateTimeFormatter f = new DateTimeFormatterBuilder()
- .appendValue(YEAR).appendLiteral('-')
- .appendValue(MONTH_OF_YEAR).appendLiteral('-')
- .appendValue(woyField).appendLiteral('-')
+ .appendValue(YEAR).appendLiteral(':')
+ .appendValue(MONTH_OF_YEAR).appendLiteral(':')
+ .appendValue(woyField).appendLiteral(':')
.appendValue(dowField).toFormatter();
- String str = date.getYear() + "-" + date.getMonthValue() + "-" +
- date.get(woyField) + "-" + date.get(dowField);
+ String str = date.getYear() + ":" + date.getMonthValue() + ":" +
+ date.get(woyField) + ":" + date.get(dowField);
LocalDate parsed = LocalDate.parse(str, f);
assertEquals(parsed, date, " :: " + str + " " + i);
@@ -460,6 +580,31 @@
}
@Test(dataProvider="weekFields")
+ public void test_parse_resolve_localizedWoyDow_lenient(DayOfWeek firstDayOfWeek, int minDays) {
+ LocalDate date = LocalDate.of(2012, 12, 15);
+ WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
+ TemporalField dowField = week.dayOfWeek();
+ TemporalField woyField = week.weekOfYear();
+
+ for (int i = 1; i <= 60; i++) {
+ DateTimeFormatter f = new DateTimeFormatterBuilder()
+ .appendValue(YEAR).appendLiteral(':')
+ .appendValue(woyField).appendLiteral(':')
+ .appendValue(dowField).toFormatter().withResolverStyle(LENIENT);
+ int woy = date.get(woyField);
+ int dow = date.get(dowField);
+ for (int j = woy - 60; j < woy + 60; j++) {
+ String str = date.getYear() + ":" + j + ":" + dow;
+ LocalDate parsed = LocalDate.parse(str, f);
+ assertEquals(parsed, date.plusWeeks(j - woy), " ::" + str + ": :" + i + "::" + j);
+ }
+
+ date = date.plusDays(1);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ @Test(dataProvider="weekFields")
public void test_parse_resolve_localizedWoWBY(DayOfWeek firstDayOfWeek, int minDays) {
LocalDate date = LocalDate.of(2012, 12, 31);
WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
@@ -467,12 +612,11 @@
TemporalField yowbyField = week.weekBasedYear();
for (int i = 1; i <= 60; i++) {
- // Test that with dayOfWeek, week of year and year of week-based-year it computes the date
DateTimeFormatter f = new DateTimeFormatterBuilder()
- .appendValue(yowbyField).appendLiteral('-')
- .appendValue(wowbyField).appendLiteral('-')
+ .appendValue(yowbyField).appendLiteral(':')
+ .appendValue(wowbyField).appendLiteral(':')
.appendValue(DAY_OF_WEEK).toFormatter();
- String str = date.get(yowbyField) + "-" + date.get(wowbyField) + "-" +
+ String str = date.get(yowbyField) + ":" + date.get(wowbyField) + ":" +
date.get(DAY_OF_WEEK);
LocalDate parsed = LocalDate.parse(str, f);
assertEquals(parsed, date, " :: " + str + " " + i);
@@ -482,6 +626,51 @@
}
@Test(dataProvider="weekFields")
+ public void test_parse_resolve_localizedWoWBY_lenient(DayOfWeek firstDayOfWeek, int minDays) {
+ LocalDate date = LocalDate.of(2012, 12, 31);
+ WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
+ TemporalField wowbyField = week.weekOfWeekBasedYear();
+ TemporalField yowbyField = week.weekBasedYear();
+
+ for (int i = 1; i <= 60; i++) {
+ DateTimeFormatter f = new DateTimeFormatterBuilder()
+ .appendValue(yowbyField).appendLiteral(':')
+ .appendValue(wowbyField).appendLiteral(':')
+ .appendValue(DAY_OF_WEEK).toFormatter().withResolverStyle(LENIENT);
+ int wowby = date.get(wowbyField);
+ int dow = date.get(DAY_OF_WEEK);
+ for (int j = wowby - 60; j < wowby + 60; j++) {
+ String str = date.get(yowbyField) + ":" + j + ":" + dow;
+ LocalDate parsed = LocalDate.parse(str, f);
+ assertEquals(parsed, date.plusWeeks(j - wowby), " ::" + str + ": :" + i + "::" + j);
+ }
+
+ date = date.plusDays(1);
+ }
+ }
+
+ @Test(dataProvider="weekFields")
+ public void test_parse_resolve_localizedWoWBY_strict(DayOfWeek firstDayOfWeek, int minDays) {
+ WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
+ TemporalField wowbyField = week.weekOfWeekBasedYear();
+ TemporalField yowbyField = week.weekBasedYear();
+ DateTimeFormatter f = new DateTimeFormatterBuilder()
+ .appendValue(yowbyField).appendLiteral(':')
+ .appendValue(wowbyField).appendLiteral(':')
+ .appendValue(DAY_OF_WEEK).toFormatter().withResolverStyle(STRICT);
+ String str = "2012:0:1";
+ try {
+ LocalDate date = LocalDate.parse(str, f);
+ assertEquals(date.get(yowbyField), 2012);
+ assertEquals(date.get(wowbyField), 0);
+ assertEquals(date.get(DAY_OF_WEEK), 1);
+ } catch (DateTimeException ex) {
+ // expected
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ @Test(dataProvider="weekFields")
public void test_parse_resolve_localizedWoWBYDow(DayOfWeek firstDayOfWeek, int minDays) {
LocalDate date = LocalDate.of(2012, 12, 31);
WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
@@ -490,12 +679,11 @@
TemporalField yowbyField = week.weekBasedYear();
for (int i = 1; i <= 60; i++) {
- // Test that with dayOfWeek, week of year and year of week-based-year it computes the date
DateTimeFormatter f = new DateTimeFormatterBuilder()
- .appendValue(yowbyField).appendLiteral('-')
- .appendValue(wowbyField).appendLiteral('-')
+ .appendValue(yowbyField).appendLiteral(':')
+ .appendValue(wowbyField).appendLiteral(':')
.appendValue(dowField).toFormatter();
- String str = date.get(yowbyField) + "-" + date.get(wowbyField) + "-" +
+ String str = date.get(yowbyField) + ":" + date.get(wowbyField) + ":" +
date.get(dowField);
LocalDate parsed = LocalDate.parse(str, f);
assertEquals(parsed, date, " :: " + str + " " + i);
@@ -504,6 +692,31 @@
}
}
+ @Test(dataProvider="weekFields")
+ public void test_parse_resolve_localizedWoWBYDow_lenient(DayOfWeek firstDayOfWeek, int minDays) {
+ LocalDate date = LocalDate.of(2012, 12, 31);
+ WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
+ TemporalField dowField = week.dayOfWeek();
+ TemporalField wowbyField = week.weekOfWeekBasedYear();
+ TemporalField yowbyField = week.weekBasedYear();
+
+ for (int i = 1; i <= 60; i++) {
+ DateTimeFormatter f = new DateTimeFormatterBuilder()
+ .appendValue(yowbyField).appendLiteral(':')
+ .appendValue(wowbyField).appendLiteral(':')
+ .appendValue(dowField).toFormatter().withResolverStyle(LENIENT);
+ int wowby = date.get(wowbyField);
+ int dow = date.get(dowField);
+ for (int j = wowby - 60; j < wowby + 60; j++) {
+ String str = date.get(yowbyField) + ":" + j + ":" + dow;
+ LocalDate parsed = LocalDate.parse(str, f);
+ assertEquals(parsed, date.plusWeeks(j - wowby), " ::" + str + ": :" + i + "::" + j);
+ }
+
+ date = date.plusDays(1);
+ }
+ }
+
//-----------------------------------------------------------------------
@Test(dataProvider="weekFields")
public void test_serializable_singleton(DayOfWeek firstDayOfWeek, int minDays) throws IOException, ClassNotFoundException {
In WeekFields: @@ -447,6 +473,25 @@
" The week-of-month field
Should probably be week-of-year.
The rest looks fine.
Allow lenient/strict/smart parsing of
WeekFields
. Breakout from #282