summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew John Hughes <gnu_andrew@member.fsf.org>2014-12-22 01:31:38 +0000
committerAndrew John Hughes <gnu_andrew@member.fsf.org>2014-12-22 01:31:38 +0000
commitf74797dcba95e7902cb1364deb718c2633ff3bb3 (patch)
treea80b6458b16d2b5fb8f938cedf1696b33e96b48a
parent2016893a79012414f0dd2475230e17bf0b846aed (diff)
downloadclasspath-f74797dcba95e7902cb1364deb718c2633ff3bb3.tar.gz
PR64176: Week of year field during end of year transition is incorrect
2014-12-15 Andrew John Hughes <gnu_andrew@member.fsf.org> PR classpath/64176 * NEWS: Updated. * java/util/GregorianCalendar.java: (computeFields()): Handle the week that runs over the end of the year and the beginning of the next one, so that it is numbered the same in both years. (getBaseWeekOfYear(int,int,int)): Broken out of computeFields to avoid code duplication. (getRelativeWeekday(int)): Likewise. Signed-off-by: Andrew John Hughes <gnu_andrew@member.fsf.org>
-rw-r--r--ChangeLog12
-rw-r--r--NEWS1
-rw-r--r--java/util/GregorianCalendar.java90
3 files changed, 92 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 29d72c7f3..f2b03b028 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2014-12-15 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ PR classpath/64176
+ * NEWS: Updated.
+ * java/util/GregorianCalendar.java:
+ (computeFields()): Handle the week that runs over
+ the end of the year and the beginning of the next
+ one, so that it is numbered the same in both years.
+ (getBaseWeekOfYear(int,int,int)): Broken out of
+ computeFields to avoid code duplication.
+ (getRelativeWeekday(int)): Likewise.
+
2014-11-28 Andrew John Hughes <gnu_andrew@member.fsf.org>
PR classpath/64109
diff --git a/NEWS b/NEWS
index 80419405b..916184869 100644
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,7 @@ New in release 0.99.1 (XXX XX, 2012)
- PR57070: VMProcess needs to notifyAll() instead of notify()
- PR58688: gnu.java.security.x509.PolicyNodeImpl#addAllPolicyQualifiers does not work
- PR64109: Missing symbol in libjavautil.so
+ - PR64176: Week of year field during end of year transition is incorrect
New in release 0.99 (Feb 15, 2012)
diff --git a/java/util/GregorianCalendar.java b/java/util/GregorianCalendar.java
index b5d9e8c47..f83819900 100644
--- a/java/util/GregorianCalendar.java
+++ b/java/util/GregorianCalendar.java
@@ -838,13 +838,11 @@ public class GregorianCalendar extends Calendar
fields[DAY_OF_WEEK_IN_MONTH] = (fields[DAY_OF_MONTH] + 6) / 7;
- // which day of the week are we (0..6), relative to getFirstDayOfWeek
- int relativeWeekday = (7 + fields[DAY_OF_WEEK] - getFirstDayOfWeek()) % 7;
-
// which day of the week is the first of this month?
// nb 35 is the smallest multiple of 7 that ensures that
// the left hand side of the modulo operator is positive.
- int relativeWeekdayOfFirst = (relativeWeekday - fields[DAY_OF_MONTH]
+ int relativeWeekdayOfFirst = (getRelativeWeekday(fields[DAY_OF_WEEK])
+ - fields[DAY_OF_MONTH]
+ 1 + 35) % 7;
// which week of the month is the first of this month in?
@@ -855,14 +853,49 @@ public class GregorianCalendar extends Calendar
fields[WEEK_OF_MONTH] = (fields[DAY_OF_MONTH]
+ relativeWeekdayOfFirst - 1) / 7 + weekOfFirst;
- int weekOfYear = (fields[DAY_OF_YEAR] - relativeWeekday + 6) / 7;
+ int weekOfYear = getBaseWeekOfYear(fields[DAY_OF_WEEK], fields[DAY_OF_YEAR],
+ fields[YEAR]);
+
+ // Do the last days of this year constitute days from the
+ // first week of the new year?
+ if (fields[MONTH] == 11)
+ {
+ // Find out the weekday of the 1st of January in the next year
+ int firstDayInJan = getFirstDayOfMonth(fields[YEAR] + 1, 0);
+ // Find out the date of the end of that week
+ // e.g. if weeks start on Sundays, what date is the first Saturday?
+ int currentDay = firstDayInJan;
+ int dateOfEndOfWeek = 0;
+ while (currentDay != getFirstDayOfWeek())
+ {
+ ++currentDay;
+ ++dateOfEndOfWeek;
+ if (currentDay > SATURDAY) currentDay = SUNDAY;
+ }
+ // Do we have an incomplete week?
+ if (dateOfEndOfWeek < 7 && dateOfEndOfWeek >= minDays)
+ {
+ // Week one runs back into the preceding year
+ // Calculate where in December it starts and set weekOfYear
+ // to 1 if the date is equal to or greater than this date.
+ int daysInPrevYear = 7 - dateOfEndOfWeek;
+ int firstDayOfFirstWeek = 31 - (daysInPrevYear - 1);
+ if (fields[DAY_OF_MONTH] >= firstDayOfFirstWeek)
+ weekOfYear = 1;
+ }
+ }
+ if (weekOfYear == 0)
+ {
+ // There is an incomplete week at the start which
+ // is below the number of minimum days in the week.
+ // This is part of the last week of the previous year.
+ int lastYear = fields[YEAR] - 1;
+ int lastDayOfPrevYear = isLeapYear(lastYear) ? 366 : 365;
+ int lastWeekdayOfPrevYear = getWeekDay(lastYear, lastDayOfPrevYear);
+ weekOfYear = getBaseWeekOfYear(lastWeekdayOfPrevYear, lastDayOfPrevYear,
+ lastYear);
+ }
- // Do the Correction: getMinimalDaysInFirstWeek() is always in the
- // first week.
- int firstWeekday = (7 + getWeekDay(fields[YEAR], minDays)
- - getFirstDayOfWeek()) % 7;
- if (minDays - firstWeekday < 1)
- weekOfYear++;
fields[WEEK_OF_YEAR] = weekOfYear;
int hourOfDay = millisInDay / (60 * 60 * 1000);
@@ -1362,4 +1395,39 @@ public class GregorianCalendar extends Calendar
return maximums[field];
}
}
+
+ /**
+ * Calculates the base week of the year value, prior to adjustments
+ * for weeks that run across the end of the year.
+ *
+ * @param dayOfWeek the current weekday.
+ * @param dayOfYear the current day of the year.
+ * @param year the current year.
+ * @return the current week of the year.
+ */
+ private int getBaseWeekOfYear(int dayOfWeek, int dayOfYear, int year)
+ {
+ // which day of the week are we (0..6), relative to getFirstDayOfWeek
+ int relativeWeekday = getRelativeWeekday(dayOfWeek);
+ int weekOfYear = (dayOfYear - relativeWeekday + 6) / 7;
+ // Do the Correction: getMinimalDaysInFirstWeek() is always in the
+ // first week.
+ int firstWeekdayOfYear = (7 + getWeekDay(year, getMinimalDaysInFirstWeek())
+ - getFirstDayOfWeek()) % 7;
+ if (getMinimalDaysInFirstWeek() - firstWeekdayOfYear < 1)
+ weekOfYear++;
+ return weekOfYear;
+ }
+
+ /**
+ * Returns the day of the week (0..6), relative to getFirstDayOfWeek
+ *
+ * @param dayOfWeek the day of the week (SUNDAY..SATURDAY)
+ * @return the relative day of the week.
+ */
+ private int getRelativeWeekday(int dayOfWeek)
+ {
+ return (7 + dayOfWeek - getFirstDayOfWeek()) % 7;
+ }
+
}