void CalendarRegressionTest::test4103271()
{
    UErrorCode status = U_ZERO_ERROR;
    SimpleDateFormat sdf(status);
    int32_t numYears=40, startYear=1997, numDays=15;
    UnicodeString output, testDesc, str, str2;
    GregorianCalendar *testCal = (GregorianCalendar*)Calendar::createInstance(status);
    if(U_FAILURE(status)) {
      dataerrln("Error creating calendar: %s", u_errorName(status));
      delete testCal;
      return;
    }
    testCal->clear();
    sdf.adoptCalendar(testCal);
    sdf.applyPattern("EEE dd MMM yyyy 'WOY'ww'-'YYYY 'DOY'DDD");
    UBool fail = FALSE;
    for (int32_t firstDay=1; firstDay<=2; firstDay++) {
        for (int32_t minDays=1; minDays<=7; minDays++) {
            testCal->setMinimalDaysInFirstWeek((uint8_t)minDays);
            testCal->setFirstDayOfWeek((UCalendarDaysOfWeek)firstDay);
            testDesc = (UnicodeString("Test") + firstDay + minDays);
            logln(testDesc + " => 1st day of week=" +
                               firstDay +
                               ", minimum days in first week=" +
                               minDays);
            for (int32_t j=startYear; j<=startYear+numYears; j++) {
                testCal->set(j,11,25);
                for(int32_t i=0; i<numDays; i++) {
                    testCal->add(UCAL_DATE,1,status);
                    UnicodeString calWOY;
                    int32_t actWOY = testCal->get(UCAL_WEEK_OF_YEAR,status);
                    if (actWOY < 1 || actWOY > 53) {
                        UDate d = testCal->getTime(status);
                        //calWOY = String.valueOf(actWOY);
                        UnicodeString temp;
                        FieldPosition pos(FieldPosition::DONT_CARE);
                        output = testDesc + " - " + sdf.format(d,temp,pos) + "\t";
                        output = output + "\t" + actWOY;
                        logln(output);
                        fail = TRUE;
                    }
                }
            }
        }
    }

    int32_t DATA [] = {
        3, 52, 52, 52, 52, 52, 52, 52,
            1,  1,  1,  1,  1,  1,  1,
            2,  2,  2,  2,  2,  2,  2,
        4, 52, 52, 52, 52, 52, 52, 52,
           53, 53, 53, 53, 53, 53, 53,
            1,  1,  1,  1,  1,  1,  1,
    };
    testCal->setFirstDayOfWeek(UCAL_SUNDAY);
    for (int32_t j=0; j<44; j+=22) {
        logln(UnicodeString("Minimal days in first week = ") + DATA[j] +
                           "  Week starts on Sunday");
        testCal->setMinimalDaysInFirstWeek((uint8_t)DATA[j]);
        testCal->set(1997, UCAL_DECEMBER, 21);
        for (int32_t i=0; i<21; ++i) {
            int32_t woy = testCal->get(UCAL_WEEK_OF_YEAR,status);
            str.remove();
            log(UnicodeString("") + sdf.format(testCal->getTime(status), str) +
                UnicodeString(" ") + woy);
            if (woy != DATA[j + 1 + i]) {
                log(" ERROR");
                fail = TRUE;
            }
            logln("");

            // Now compute the time from the fields, and make sure we
            // get the same answer back.  This is a round-trip test.
            UDate save = testCal->getTime(status);
            testCal->clear();
            testCal->set(UCAL_YEAR_WOY, DATA[j+1+i] < 25 ? 1998 : 1997);
            testCal->set(UCAL_WEEK_OF_YEAR, DATA[j+1+i]);
            testCal->set(UCAL_DAY_OF_WEEK, (i%7) + UCAL_SUNDAY);
            if (testCal->getTime(status) != save) {
                str.remove();
                logln(UnicodeString("  Parse failed: ") +
                      sdf.format(testCal->getTime(status), str));
                fail= TRUE;
            }

            testCal->setTime(save,status);
            testCal->add(UCAL_DATE, 1,status);
        }
    }
    // Test field disambiguation with a few special hard-coded cases.
    // This shouldn't fail if the above cases aren't failing.
    int32_t DISAM_int [] = {
        // y y_woy woy dow
        1997, 1998, 1, UCAL_SUNDAY,
        (1998), (1998), (2), (UCAL_SATURDAY),
        (1998), (1998), (53), (UCAL_THURSDAY),
        (1999), (1998), (53), (UCAL_FRIDAY)
    };

    UDate DISAM_date [] = {
            makeDate(1997, UCAL_DECEMBER, 28),
            makeDate(1998, UCAL_JANUARY, 10),
            makeDate(1998, UCAL_DECEMBER, 31),
            makeDate(1999, UCAL_JANUARY, 1)
    };

    testCal->setMinimalDaysInFirstWeek(3);
    testCal->setFirstDayOfWeek(UCAL_SUNDAY);
    int32_t i = 0;

    /* Enable this code to display various WOY values
    testCal->clear();
    for (i=25; i<38; ++i) {
        testCal->set(1996, Calendar::DECEMBER, i);
        UDate got = testCal->getTime(status);
        str.remove();
        logln(UnicodeString("") + sdf.format(got, str));
    }
    for (i=25; i<38; ++i) {
        testCal->set(1997, Calendar::DECEMBER, i);
        UDate got = testCal->getTime(status);
        str.remove();
        logln(UnicodeString("") + sdf.format(got, str));
    }
    for (i=25; i<38; ++i) {
        testCal->set(1998, UCAL_DECEMBER, i);
        UDate got = testCal->getTime(status);
        str.remove();
        logln(UnicodeString("") + sdf.format(got, str));
    }
    */

    for (i=0; i < 16; i += 4) {
        int32_t y = DISAM_int[i];
        int32_t ywoy = DISAM_int[i+1];
        int32_t woy = DISAM_int[i+2];
        int32_t dow = DISAM_int[i+3];
        UDate exp = DISAM_date[i/4];
        testCal->clear();
        testCal->set(UCAL_YEAR, y);
        testCal->set(UCAL_WEEK_OF_YEAR, woy);
        testCal->set(UCAL_DAY_OF_WEEK, dow);
        UDate got = testCal->getTime(status);
        str.remove();
        str2.remove();
        log(UnicodeString("Y") + y + "-W" + woy +
                         "-DOW" + dow + " expect:" + sdf.format(exp, str) +
                         " got:" + sdf.format(got, str2));
        if (got != exp) {
            log("  FAIL (%s:%d, i=%d)", __FILE__, __LINE__, i);
            logln(CalendarTest::calToStr(*testCal));
            testCal->setTime(exp, status);
            logln(CalendarTest::calToStr(*testCal) + UnicodeString( " <<< expected "));
            fail = TRUE;
        }
        logln("");

        testCal->clear();
        testCal->set(UCAL_YEAR_WOY, ywoy);
        testCal->set(UCAL_WEEK_OF_YEAR, woy);
        testCal->set(UCAL_DAY_OF_WEEK, dow);
        got = testCal->getTime(status);
        str.remove();
        str2.remove();
        log(UnicodeString("YWOY") + ywoy + "-W" + woy +
                         "-DOW" + dow + " expect:" + sdf.format(exp, str) +
                         " got:" + sdf.format(got, str2));
        if (got != exp) {
            log("  FAIL");
            fail = TRUE;
        }
        logln("");
    }
    // Now try adding and rolling
    UDate ADDROLL_date [] = {
        makeDate(1998, UCAL_DECEMBER, 25), makeDate(1999, UCAL_JANUARY, 1),
        makeDate(1997, UCAL_DECEMBER, 28), makeDate(1998, UCAL_JANUARY, 4),
        makeDate(1998, UCAL_DECEMBER, 27), makeDate(1997, UCAL_DECEMBER, 28),
        makeDate(1999, UCAL_JANUARY, 2), makeDate(1998, UCAL_JANUARY, 3),
    };

    int32_t ADDROLL_int []= {
        (1),
        (1),
        (1),
        (1)
    };


    UBool ADDROLL_bool [] = {
        TRUE,//ADD,
        TRUE,
        FALSE,
        FALSE
    };

    testCal->setMinimalDaysInFirstWeek(3);
    testCal->setFirstDayOfWeek(UCAL_SUNDAY);
    for (i=0; i<8; i += 2) {
        int32_t amount = ADDROLL_int[i/2];
        UDate before = ADDROLL_date[i];
        UDate after = ADDROLL_date[i+1];

        testCal->setTime(before,status);
        if (ADDROLL_bool[i/2])
            testCal->add(UCAL_WEEK_OF_YEAR, amount,status);
        else
            testCal->roll(UCAL_WEEK_OF_YEAR, amount,status);
        UDate got = testCal->getTime(status);
        str.remove();
        str2.remove();
        UnicodeString opTypeStr;
        if (ADDROLL_bool[i/2]) {
            opTypeStr = UnicodeString("add(WOY,", "");
        } else {
            opTypeStr = UnicodeString("roll(WOY,", "");
        }
        log(opTypeStr + amount + ") " + sdf.format(before, str) + " => " +
                    sdf.format(got, str2));
        if (after != got) {
            str.remove();
            logln(UnicodeString("  exp:") + sdf.format(after, str) + "  FAIL");
            fail = TRUE;
        }
        else logln(" ok");

        testCal->setTime(after,status);
        if (ADDROLL_bool[i/2])
            testCal->add(UCAL_WEEK_OF_YEAR, -amount,status);
        else
            testCal->roll(UCAL_WEEK_OF_YEAR, -amount,status);
        got = testCal->getTime(status);
        str.remove();
        str2.remove();
        log(opTypeStr + (-amount) + ") " + sdf.format(after, str) + " => " +
                sdf.format(got, str2));
        if (before != got) {
            str.remove();
            logln(UnicodeString("  exp:") + sdf.format(before, str) + "  FAIL");
            fail = TRUE;
        }
        else logln(" ok");
    }
    if (fail)
        errln("Fail: Week of year misbehaving");
}