diff options
author | Andrew John Hughes <gnu_andrew@member.fsf.org> | 2014-12-22 01:31:38 +0000 |
---|---|---|
committer | Andrew John Hughes <gnu_andrew@member.fsf.org> | 2014-12-22 01:31:38 +0000 |
commit | f74797dcba95e7902cb1364deb718c2633ff3bb3 (patch) | |
tree | a80b6458b16d2b5fb8f938cedf1696b33e96b48a | |
parent | 2016893a79012414f0dd2475230e17bf0b846aed (diff) | |
download | classpath-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-- | ChangeLog | 12 | ||||
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | java/util/GregorianCalendar.java | 90 |
3 files changed, 92 insertions, 11 deletions
@@ -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 @@ -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; + } + } |