From 515788594c821e2bf932732bb7a6da525277f2ee Mon Sep 17 00:00:00 2001
From: Yoshito Umaoka <y.umaoka@gmail.com>
Date: Tue, 5 Jul 2011 22:42:14 +0000
Subject: [PATCH] ICU-8596 Fixed the actual maximum week problem.

X-SVN-Rev: 30276
---
 icu4c/source/i18n/calendar.cpp          |  7 +++-
 icu4c/source/test/intltest/calregts.cpp | 44 +++++++++++++++++++++++++
 icu4c/source/test/intltest/calregts.h   |  1 +
 3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/icu4c/source/i18n/calendar.cpp b/icu4c/source/i18n/calendar.cpp
index b6a904aff02..72e60849b2e 100644
--- a/icu4c/source/i18n/calendar.cpp
+++ b/icu4c/source/i18n/calendar.cpp
@@ -3079,7 +3079,7 @@ Calendar::getActualMaximum(UCalendarDateFields field, UErrorCode& status) const
             if(U_FAILURE(status)) return 0;
             Calendar *cal = clone();
             if(!cal) { status = U_MEMORY_ALLOCATION_ERROR; return 0; }
-			cal->setLenient(TRUE);
+            cal->setLenient(TRUE);
             cal->prepareGetActual(field,FALSE,status);
             result = handleGetYearLength(cal->get(UCAL_EXTENDED_YEAR, status));
             delete cal;
@@ -3201,6 +3201,11 @@ int32_t Calendar::getActualHelper(UCalendarDateFields field, int32_t startValue,
     if(U_FAILURE(status)) return startValue;
     Calendar *work = clone();
     if(!work) { status = U_MEMORY_ALLOCATION_ERROR; return startValue; }
+
+    // need to resolve time here, otherwise, fields set for actual limit
+    // may cause conflict with fields previously set (but not yet resolved).
+    work->complete(status);
+
     work->setLenient(TRUE);
     work->prepareGetActual(field, delta < 0, status);
 
diff --git a/icu4c/source/test/intltest/calregts.cpp b/icu4c/source/test/intltest/calregts.cpp
index bc97a551440..e797744675b 100644
--- a/icu4c/source/test/intltest/calregts.cpp
+++ b/icu4c/source/test/intltest/calregts.cpp
@@ -84,6 +84,7 @@ CalendarRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &
         CASE(45,TestT5555);
         CASE(46,TestT6745);
         CASE(47,TestT8057);
+        CASE(48,TestT8596);
     default: name = ""; break;
     }
 }
@@ -2811,4 +2812,47 @@ void CalendarRegressionTest::TestT8057(void) {
     delete cal;
 }
 
+// Test case for ticket#8596.
+// Setting an year followed by getActualMaximum(Calendar.WEEK_OF_YEAR)
+// may result wrong maximum week.
+void CalendarRegressionTest::TestT8596(void) {
+    UErrorCode status = U_ZERO_ERROR;
+    GregorianCalendar *gc = new GregorianCalendar(*TimeZone::getGMT(), status);
+
+    if (U_FAILURE(status)) {
+        dataerrln("Error creating Calendar: %s", u_errorName(status));
+        delete gc;
+        return;
+    }
+
+    gc->setFirstDayOfWeek(UCAL_MONDAY);
+    gc->setMinimalDaysInFirstWeek(4);
+
+    // Force the calender to resolve the fields once.
+    // The maximum week number in 2011 is 52.
+    gc->set(UCAL_YEAR, 2011);
+    gc->get(UCAL_YEAR, status);
+
+    // Set a date in year 2009, but not calling get to resolve
+    // the calendar's internal field yet.
+    gc->set(2009, UCAL_JULY, 1);
+
+    // Then call getActuamMaximum for week of year.
+    // #8596 was caused by conflict between year set
+    // above and internal work calendar field resolution.
+    int32_t maxWeeks = gc->getActualMaximum(UCAL_WEEK_OF_YEAR, status);
+
+    if (U_FAILURE(status)) {
+        errln("Error calendar calculation: %s", u_errorName(status));
+        delete gc;
+        return;
+    }
+
+    if (maxWeeks != 53) {
+        errln((UnicodeString)"FAIL: Max week in 2009 in ISO calendar is 53, but got " + maxWeeks);
+    }
+
+    delete gc;
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/icu4c/source/test/intltest/calregts.h b/icu4c/source/test/intltest/calregts.h
index d03be6be3bb..984a88b55cd 100644
--- a/icu4c/source/test/intltest/calregts.h
+++ b/icu4c/source/test/intltest/calregts.h
@@ -72,6 +72,7 @@ public:
     void TestWeekShift(void);
     void TestTimeZoneTransitionAdd(void);
     void TestDeprecates(void);
+    void TestT8596(void);
 
     void printdate(GregorianCalendar *cal, const char *string);
     void dowTest(UBool lenient) ;
-- 
2.40.0