Beispiel #1
0
/**
 * @bug 4060212
 */
void DateFormatRegressionTest::Test4060212(void) 
{
    UnicodeString dateString = "1995-040.05:01:29";

    logln( "dateString= " + dateString );
    logln("Using yyyy-DDD.hh:mm:ss");
    UErrorCode status = U_ZERO_ERROR;
    SimpleDateFormat *formatter = new SimpleDateFormat(UnicodeString("yyyy-DDD.hh:mm:ss"), status);
    if (failure(status, "new SimpleDateFormat", TRUE)) return;
    ParsePosition pos(0);
    UDate myDate = formatter->parse( dateString, pos );
    UnicodeString myString;
    DateFormat *fmt = DateFormat::createDateTimeInstance( DateFormat::FULL,
                                                            DateFormat::LONG);
    if (fmt == NULL) {
        dataerrln("Error calling DateFormat::createDateTimeInstance");
        delete formatter;
        return;
    }

    myString = fmt->format( myDate, myString);
    logln( myString );

    Calendar *cal = new GregorianCalendar(status);
    failure(status, "new GregorianCalendar");
    cal->setTime(myDate, status);
    failure(status, "cal->setTime");
    if ((cal->get(UCAL_DAY_OF_YEAR, status) != 40) || failure(status, "cal->get"))
        errln((UnicodeString) "Fail: Got " + cal->get(UCAL_DAY_OF_YEAR, status) +
                            " Want 40");

    // this is an odd usage of "ddd" and it doesn't
    // work now that date values are range checked per #3579.
    logln("Using yyyy-ddd.hh:mm:ss");
    delete formatter;
    formatter = NULL;
    formatter = new SimpleDateFormat(UnicodeString("yyyy-ddd.hh:mm:ss"), status);
    if(failure(status, "new SimpleDateFormat")) return;
    pos.setIndex(0);
    myDate = formatter->parse( dateString, pos );
    myString = fmt->format( myDate, myString );
    logln( myString );
    cal->setTime(myDate, status);
    failure(status, "cal->setTime");
    if ((cal->get(UCAL_DAY_OF_YEAR, status) != 40) || failure(status, "cal->get"))
        errln((UnicodeString) "Fail: Got " + cal->get(UCAL_DAY_OF_YEAR, status) +
                            " Want 40");

    delete formatter;
    delete fmt;
    delete cal;
}
Beispiel #2
0
// Mimics Date.getYear() etc.
void
CalendarTimeZoneTest::dateToFields(UDate date, int32_t& y, int32_t& m, int32_t& d, int32_t& hr, int32_t& min, int32_t& sec)
{
    Calendar* cal = getCalendar();
    if (cal == 0) return;
    UErrorCode status = U_ZERO_ERROR;
    cal->setTime(date, status);
    y = cal->get(UCAL_YEAR, status) - 1900;
    m = cal->get(UCAL_MONTH, status);
    d = cal->get(UCAL_DATE, status);
    hr = cal->get(UCAL_HOUR_OF_DAY, status);
    min = cal->get(UCAL_MINUTE, status);
    sec = cal->get(UCAL_SECOND, status);
    releaseCalendar(cal);
}
int32_t RelativeDateFormat::dayDifference(Calendar &cal, UErrorCode &status) {
    if(U_FAILURE(status)) {
        return 0;
    }
    // TODO: Cache the nowCal to avoid heap allocs? Would be difficult, don't know the calendar type
    Calendar *nowCal = cal.clone();
    nowCal->setTime(Calendar::getNow(), status);

    // For the day difference, we are interested in the difference in the (modified) julian day number
    // which is midnight to midnight.  Using fieldDifference() is NOT correct here, because
    // 6pm Jan 4th  to 10am Jan 5th should be considered "tomorrow".
    int32_t dayDiff = cal.get(UCAL_JULIAN_DAY, status) - nowCal->get(UCAL_JULIAN_DAY, status);

    delete nowCal;
    return dayDiff;
}
Beispiel #4
0
void
IslamicCalendar::initializeSystemDefaultCentury()
{
  // initialize systemDefaultCentury and systemDefaultCenturyYear based
  // on the current time.  They'll be set to 80 years before
  // the current time.
  // No point in locking as it should be idempotent.
  if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
  {
    UErrorCode status = U_ZERO_ERROR;
    Calendar *calendar = new IslamicCalendar(Locale("ar@calendar=islamic-civil"),status);
    if (calendar != NULL && U_SUCCESS(status))
    {
      calendar->setTime(Calendar::getNow(), status);
      calendar->add(UCAL_YEAR, -80, status);
      UDate    newStart =  calendar->getTime(status);
      int32_t  newYear  =  calendar->get(UCAL_YEAR, status);
      {
        Mutex m;
        fgSystemDefaultCenturyStart = newStart;
        fgSystemDefaultCenturyStartYear = newYear;
      }
      delete calendar;
    }
    // We have no recourse upon failure unless we want to propagate the failure
    // out.
  }
}
std::string resultDateInJson(const UDate& date)
{
    UErrorCode status = U_ZERO_ERROR;
    Calendar* cal = Calendar::createInstance(status);
    if (!cal) {
        slog2f(0, ID_G11N, SLOG2_ERROR, "GlobalizationNDK::resultInJson: failed to create Calendar instance: %d",
                status);
        return errorInJson(UNKNOWN_ERROR, "Failed to create Calendar instance!");
    }
    std::auto_ptr<Calendar> deleter(cal);

    cal->setTime(date, status);
    if (status != U_ZERO_ERROR && status != U_ERROR_WARNING_START) {
        slog2f(0, ID_G11N, SLOG2_ERROR, "GlobalizationNDK::resultInJson: failed to setTime: %d",
                status);
        return errorInJson(UNKNOWN_ERROR, "Failed to set Calendar time!");
    }

    Json::Value result;
    result["year"] = cal->get(UCAL_YEAR, status);
    result["month"] = cal->get(UCAL_MONTH, status);
    result["day"] = cal->get(UCAL_DAY_OF_MONTH, status);
    result["hour"] = cal->get(UCAL_HOUR, status);
    result["minute"] = cal->get(UCAL_MINUTE, status);
    result["second"] = cal->get(UCAL_SECOND, status);
    result["millisecond"] = cal->get(UCAL_MILLISECOND, status);

    Json::Value root;
    root["result"] = result;

    Json::FastWriter writer;
    return writer.write(root);
}
/**
 * @bug 4126678
 * CANNOT REPRODUDE
 *
 * Yet another _alleged_ bug in TimeZone::getOffset(), a method that never
 * should have been made public.  It's simply too hard to use correctly.
 *
 * The original test code failed to do the following:
 * (1) Call Calendar::setTime() before getting the fields!
 * (2) Use the right millis (as usual) for getOffset(); they were passing
 *     in the MILLIS field, instead of the STANDARD MILLIS IN DAY.
 * When you fix these two problems, the test passes, as expected.
 */
void TimeZoneRegressionTest:: Test4126678() 
{
    UErrorCode status = U_ZERO_ERROR;
    Calendar *cal = Calendar::createInstance(status);
    if(U_FAILURE(status)) {
      dataerrln("Error creating calendar %s", u_errorName(status));
      delete cal;
      return;
    }
    failure(status, "Calendar::createInstance");
    TimeZone *tz = TimeZone::createTimeZone("PST");
    cal->adoptTimeZone(tz);

    cal->set(1998, UCAL_APRIL, 5, 10, 0);
    
    if (! tz->useDaylightTime() || U_FAILURE(status))
        dataerrln("We're not in Daylight Savings Time and we should be. - %s", u_errorName(status));

    //cal.setTime(dt);
    int32_t era = cal->get(UCAL_ERA, status);
    int32_t year = cal->get(UCAL_YEAR, status);
    int32_t month = cal->get(UCAL_MONTH, status);
    int32_t day = cal->get(UCAL_DATE, status);
    int32_t dayOfWeek = cal->get(UCAL_DAY_OF_WEEK, status);
    int32_t millis = cal->get(UCAL_MILLISECOND, status) +
        (cal->get(UCAL_SECOND, status) +
         (cal->get(UCAL_MINUTE, status) +
          (cal->get(UCAL_HOUR, status) * 60) * 60) * 1000) -
        cal->get(UCAL_DST_OFFSET, status);

    failure(status, "cal->get");
    int32_t offset = tz->getOffset((uint8_t)era, year, month, day, (uint8_t)dayOfWeek, millis, status);
    int32_t raw_offset = tz->getRawOffset();

    if (offset == raw_offset)
        dataerrln("Offsets should match");

    delete cal;
}
Beispiel #7
0
int32_t
Calendar::getActualMaximum(UCalendarDateFields field, UErrorCode& status) const
{
    int32_t fieldValue = getLeastMaximum(field);
    int32_t endValue = getMaximum(field);

    // if we know that the maximum value is always the same, just return it
    if (fieldValue == endValue) {
        return fieldValue;
    }

    // clone the calendar so we don't mess with the real one, and set it to
    // accept anything for the field values
    Calendar *work = (Calendar*)this->clone();
    work->setLenient(TRUE);

    // if we're counting weeks, set the day of the week to Sunday.  We know the
    // last week of a month or year will contain the first day of the week.
    if (field == UCAL_WEEK_OF_YEAR || field == UCAL_WEEK_OF_MONTH)
        work->set(UCAL_DAY_OF_WEEK, fFirstDayOfWeek);

    // now try each value from getLeastMaximum() to getMaximum() one by one until
    // we get a value that normalizes to another value.  The last value that
    // normalizes to itself is the actual maximum for the current date
    int32_t result = fieldValue;

    do {
        work->set(field, fieldValue);
        if(work->get(field, status) != fieldValue) {
            break;
        } 
        else {
            result = fieldValue;
            fieldValue++;
        }
    } while (fieldValue <= endValue);

    delete work;

    /* Test for buffer overflows */
    if(U_FAILURE(status)) {
        return 0;
    }

    return result;
}
Beispiel #8
0
int32_t
Calendar::getActualMinimum(UCalendarDateFields field, UErrorCode& status) const
{
    int32_t fieldValue = getGreatestMinimum(field);
    int32_t endValue = getMinimum(field);

    // if we know that the minimum value is always the same, just return it
    if (fieldValue == endValue) {
        return fieldValue;
    }

    // clone the calendar so we don't mess with the real one, and set it to
    // accept anything for the field values
    Calendar *work = (Calendar*)this->clone();
    work->setLenient(TRUE);

    // now try each value from getLeastMaximum() to getMaximum() one by one until
    // we get a value that normalizes to another value.  The last value that
    // normalizes to itself is the actual minimum for the current date
    int32_t result = fieldValue;

    do {
        work->set(field, fieldValue);
        if (work->get(field, status) != fieldValue) {
            break;
        } 
        else {
            result = fieldValue;
            fieldValue--;
        }
    } while (fieldValue >= endValue);

    delete work;

    /* Test for buffer overflows */
    if(U_FAILURE(status)) {
        return 0;
    }
    return result;
}
/**
 * Verify the Persian Calendar.
 */
void IntlCalendarTest::TestPersian() {
    UDate timeA = Calendar::getNow();
    
    Calendar *cal;
    UErrorCode status = U_ZERO_ERROR;
    cal = Calendar::createInstance("fa_IR@calendar=persian", status);
    CHECK(status, UnicodeString("Creating fa_IR@calendar=persian calendar"));
    // Sanity check the calendar 
    UDate timeB = Calendar::getNow();
    UDate timeCal = cal->getTime(status);

    if(!(timeA <= timeCal) || !(timeCal <= timeB)) {
      errln((UnicodeString)"Error: Calendar time " + timeCal +
            " is not within sampled times [" + timeA + " to " + timeB + "]!");
    }
    // end sanity check

    // Test various dates to be sure of validity
    int32_t data[] = { 
        1925, 4, 24, 1304, 2, 4,
        2011, 1, 11, 1389, 10, 21,
        1986, 2, 25, 1364, 12, 6, 
        1934, 3, 14, 1312, 12, 23,

        2090, 3, 19, 1468, 12, 29,
        2007, 2, 22, 1385, 12, 3,
        1969, 12, 31, 1348, 10, 10,
        1945, 11, 12, 1324, 8, 21,
        1925, 3, 31, 1304, 1, 11,

        1996, 3, 19, 1374, 12, 29,
        1996, 3, 20, 1375, 1, 1,
        1997, 3, 20, 1375, 12, 30,
        1997, 3, 21, 1376, 1, 1,

        2008, 3, 19, 1386, 12, 29,
        2008, 3, 20, 1387, 1, 1,
        2004, 3, 19, 1382, 12, 29,
        2004, 3, 20, 1383, 1, 1,

        2006, 3, 20, 1384, 12, 29,
        2006, 3, 21, 1385, 1, 1,

        2005, 4, 20, 1384, 1, 31,
        2005, 4, 21, 1384, 2, 1,
        2005, 5, 21, 1384, 2, 31,
        2005, 5, 22, 1384, 3, 1,
        2005, 6, 21, 1384, 3, 31,
        2005, 6, 22, 1384, 4, 1,
        2005, 7, 22, 1384, 4, 31,
        2005, 7, 23, 1384, 5, 1,
        2005, 8, 22, 1384, 5, 31,
        2005, 8, 23, 1384, 6, 1,
        2005, 9, 22, 1384, 6, 31,
        2005, 9, 23, 1384, 7, 1,
        2005, 10, 22, 1384, 7, 30,
        2005, 10, 23, 1384, 8, 1,
        2005, 11, 21, 1384, 8, 30,
        2005, 11, 22, 1384, 9, 1,
        2005, 12, 21, 1384, 9, 30,
        2005, 12, 22, 1384, 10, 1,
        2006, 1, 20, 1384, 10, 30,
        2006, 1, 21, 1384, 11, 1,
        2006, 2, 19, 1384, 11, 30,
        2006, 2, 20, 1384, 12, 1,
        2006, 3, 20, 1384, 12, 29,
        2006, 3, 21, 1385, 1, 1,

        // The 2820-year cycle arithmetical algorithm would fail this one.
        2025, 3, 21, 1404, 1, 1,
        
        -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
    };

    Calendar *grego = Calendar::createInstance("fa_IR@calendar=gregorian", status);
    for (int32_t i=0; data[i]!=-1; ) {
        int32_t gregYear = data[i++];
        int32_t gregMonth = data[i++]-1;
        int32_t gregDay = data[i++];
        int32_t persYear = data[i++];
        int32_t persMonth = data[i++]-1;
        int32_t persDay = data[i++];
        
        // Test conversion from Persian dates
        grego->clear();
        grego->set(gregYear, gregMonth, gregDay);

        cal->clear();
        cal->set(persYear, persMonth, persDay);

        UDate persTime = cal->getTime(status);
        UDate gregTime = grego->getTime(status);

        if (persTime != gregTime) {
          errln(UnicodeString("Expected ") + gregTime + " but got " + persTime);
        }

        // Test conversion to Persian dates
        cal->clear();
        cal->setTime(gregTime, status);

        int32_t computedYear = cal->get(UCAL_YEAR, status);
        int32_t computedMonth = cal->get(UCAL_MONTH, status);
        int32_t computedDay = cal->get(UCAL_DATE, status);

        if ((persYear != computedYear) ||
            (persMonth != computedMonth) ||
            (persDay != computedDay)) {
          errln(UnicodeString("Expected ") + persYear + "/" + (persMonth+1) + "/" + persDay +
                " but got " +  computedYear + "/" + (computedMonth+1) + "/" + computedDay);
        }

    }

    delete cal;
    delete grego;
}
/**
 * Run a test of a quasi-Gregorian calendar.  This is a calendar
 * that behaves like a Gregorian but has different year/era mappings.
 * The int[] data array should have the format:
 * 
 * { era, year, gregorianYear, month, dayOfMonth, ...  ... , -1 }
 */
void IntlCalendarTest::quasiGregorianTest(Calendar& cal, const Locale& gcl, const int32_t *data) {
  UErrorCode status = U_ZERO_ERROR;
  // As of JDK 1.4.1_01, using the Sun JDK GregorianCalendar as
  // a reference throws us off by one hour.  This is most likely
  // due to the JDK 1.4 incorporation of historical time zones.
  //java.util.Calendar grego = java.util.Calendar.getInstance();
  Calendar *grego = Calendar::createInstance(gcl, status);
  if (U_FAILURE(status)) {
    dataerrln("Error calling Calendar::createInstance"); 
    return;
  }

  int32_t tz1 = cal.get(UCAL_ZONE_OFFSET,status);
  int32_t tz2 = grego -> get (UCAL_ZONE_OFFSET, status);
  if(tz1 != tz2) { 
    errln((UnicodeString)"cal's tz " + tz1 + " != grego's tz " + tz2);
  }

  for (int32_t i=0; data[i]!=-1; ) {
    int32_t era = data[i++];
    int32_t year = data[i++];
    int32_t gregorianYear = data[i++];
    int32_t month = data[i++];
    int32_t dayOfMonth = data[i++];
    
    grego->clear();
    grego->set(gregorianYear, month, dayOfMonth);
    UDate D = grego->getTime(status);
    
    cal.clear();
    cal.set(UCAL_ERA, era);
    cal.set(year, month, dayOfMonth);
    UDate d = cal.getTime(status);
#ifdef U_DEBUG_DUMPCALS
    logln((UnicodeString)"cal  : " + CalendarTest::calToStr(cal));
    logln((UnicodeString)"grego: " + CalendarTest::calToStr(*grego));
#endif
    if (d == D) {
      logln(UnicodeString("OK: ") + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth +
            " => " + d + " (" + UnicodeString(cal.getType()) + ")");
    } else {
      errln(UnicodeString("Fail: (fields to millis)") + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth +
            " => " + d + ", expected " + D + " (" + UnicodeString(cal.getType()) + "Off by: " + (d-D));
    }
    
    // Now, set the gregorian millis on the other calendar
    cal.clear();
    cal.setTime(D, status);
    int e = cal.get(UCAL_ERA, status);
    int y = cal.get(UCAL_YEAR, status);
#ifdef U_DEBUG_DUMPCALS
    logln((UnicodeString)"cal  : " + CalendarTest::calToStr(cal));
    logln((UnicodeString)"grego: " + CalendarTest::calToStr(*grego));
#endif
    if (y == year && e == era) {
      logln((UnicodeString)"OK: " + D + " => " + cal.get(UCAL_ERA, status) + ":" +
            cal.get(UCAL_YEAR, status) + "/" +
            (cal.get(UCAL_MONTH, status)+1) + "/" + cal.get(UCAL_DATE, status) +  " (" + UnicodeString(cal.getType()) + ")");
    } else {
      errln((UnicodeString)"Fail: (millis to fields)" + D + " => " + cal.get(UCAL_ERA, status) + ":" +
            cal.get(UCAL_YEAR, status) + "/" +
            (cal.get(UCAL_MONTH, status)+1) + "/" + cal.get(UCAL_DATE, status) +
            ", expected " + era + ":" + year + "/" + (month+1) + "/" +
            dayOfMonth +  " (" + UnicodeString(cal.getType()));
    }
  }
  delete grego;
  CHECK(status, "err during quasiGregorianTest()");
}
Beispiel #11
0
void
CalendarLimitTest::doLimitsTest(Calendar& cal,
                                const int32_t* fieldsToTest,
                                UDate startDate,
                                int32_t testDuration) {
    static const int32_t FIELDS[] = {
        UCAL_ERA,
        UCAL_YEAR,
        UCAL_MONTH,
        UCAL_WEEK_OF_YEAR,
        UCAL_WEEK_OF_MONTH,
        UCAL_DAY_OF_MONTH,
        UCAL_DAY_OF_YEAR,
        UCAL_DAY_OF_WEEK_IN_MONTH,
        UCAL_YEAR_WOY,
        UCAL_EXTENDED_YEAR,
        -1,
    };

    static const char* FIELD_NAME[] = {
        "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH",
        "DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK",
        "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR", "HOUR_OF_DAY",
        "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET",
        "DST_OFFSET", "YEAR_WOY", "DOW_LOCAL", "EXTENDED_YEAR",
        "JULIAN_DAY", "MILLISECONDS_IN_DAY",
        "IS_LEAP_MONTH"
    };

    UErrorCode status = U_ZERO_ERROR;
    int32_t i, j;
    UnicodeString ymd;

    GregorianCalendar greg(status);
    if (failure(status, "new GregorianCalendar")) {
        return;
    }
    greg.setTime(startDate, status);
    if (failure(status, "GregorianCalendar::setTime")) {
        return;
    }
    logln((UnicodeString)"Start: " + startDate);

    if (fieldsToTest == NULL) {
        fieldsToTest = FIELDS;
    }


    // Keep a record of minima and maxima that we actually see.
    // These are kept in an array of arrays of hashes.
    int32_t limits[UCAL_FIELD_COUNT][4];
    for (j = 0; j < UCAL_FIELD_COUNT; j++) {
        limits[j][0] = INT32_MAX;
        limits[j][1] = INT32_MIN;
        limits[j][2] = INT32_MAX;
        limits[j][3] = INT32_MIN;
    }

    // This test can run for a long time; show progress.
    UDate millis = ucal_getNow();
    UDate mark = millis + 5000; // 5 sec
    millis -= testDuration * 1000; // stop time if testDuration<0

    for (i = 0;
         testDuration > 0 ? i < testDuration
                        : ucal_getNow() < millis;
         ++i) {
        if (ucal_getNow() >= mark) {
            logln((UnicodeString)"(" + i + " days)");
            mark += 5000; // 5 sec
        }
        UDate testMillis = greg.getTime(status);
        cal.setTime(testMillis, status);
        cal.setMinimalDaysInFirstWeek(1);
        if (failure(status, "Calendar set/getTime")) {
            return;
        }
        for (j = 0; fieldsToTest[j] >= 0; ++j) {
            UCalendarDateFields f = (UCalendarDateFields)fieldsToTest[j];
            int32_t v = cal.get(f, status);
            int32_t minActual = cal.getActualMinimum(f, status);
            int32_t maxActual = cal.getActualMaximum(f, status);
            int32_t minLow = cal.getMinimum(f);
            int32_t minHigh = cal.getGreatestMinimum(f);
            int32_t maxLow = cal.getLeastMaximum(f);
            int32_t maxHigh = cal.getMaximum(f);

            if (limits[j][0] > minActual) {
                // the minimum
                limits[j][0] = minActual;
            }
            if (limits[j][1] < minActual) {
                // the greatest minimum
                limits[j][1] = minActual;
            }
            if (limits[j][2] > maxActual) {
                // the least maximum
                limits[j][2] = maxActual;
            }
            if (limits[j][3] < maxActual) {
                // the maximum
                limits[j][3] = maxActual;
            }

            if (minActual < minLow || minActual > minHigh) {
                errln((UnicodeString)"Fail: [" + cal.getType() + "] " +
                      ymdToString(cal, ymd) +
                      " Range for min of " + FIELD_NAME[f] + "(" + f +
                      ")=" + minLow + ".." + minHigh +
                      ", actual_min=" + minActual);
            }
            if (maxActual < maxLow || maxActual > maxHigh) {
                if ( uprv_strcmp(cal.getType(), "chinese") == 0 &&
                        testMillis >= 2842992000000.0  && testMillis <= 2906668800000.0 &&
                     logKnownIssue("12620", "chinese calendar failures for some actualMax tests")) {
                    logln((UnicodeString)"KnownFail: [" + cal.getType() + "] " +
                          ymdToString(cal, ymd) +
                          " Range for max of " + FIELD_NAME[f] + "(" + f +
                          ")=" + maxLow + ".." + maxHigh +
                          ", actual_max=" + maxActual);
                } else {
                    errln((UnicodeString)"Fail: [" + cal.getType() + "] " +
                          ymdToString(cal, ymd) +
                          " Range for max of " + FIELD_NAME[f] + "(" + f +
                          ")=" + maxLow + ".." + maxHigh +
                          ", actual_max=" + maxActual);
                }
            }
            if (v < minActual || v > maxActual) {
                // timebomb per #9967, fix with #9972
                if ( uprv_strcmp(cal.getType(), "dangi") == 0 &&
                        testMillis >= 1865635198000.0  &&
                     logKnownIssue("9972", "as per #9967")) { // Feb 2029 gregorian, end of dangi 4361
                    logln((UnicodeString)"KnownFail: [" + cal.getType() + "] " +
                          ymdToString(cal, ymd) +
                          " " + FIELD_NAME[f] + "(" + f + ")=" + v +
                          ", actual=" + minActual + ".." + maxActual +
                          ", allowed=(" + minLow + ".." + minHigh + ")..(" +
                          maxLow + ".." + maxHigh + ")");
                } else if ( uprv_strcmp(cal.getType(), "chinese") == 0 &&
                        testMillis >= 2842992000000.0  && testMillis <= 2906668800000.0 &&
                     logKnownIssue("12620", "chinese calendar failures for some actualMax tests")) {
                    logln((UnicodeString)"KnownFail: [" + cal.getType() + "] " +
                          ymdToString(cal, ymd) +
                          " " + FIELD_NAME[f] + "(" + f + ")=" + v +
                          ", actual=" + minActual + ".." + maxActual +
                          ", allowed=(" + minLow + ".." + minHigh + ")..(" +
                          maxLow + ".." + maxHigh + ")");
                } else {
                    errln((UnicodeString)"Fail: [" + cal.getType() + "] " +
                          ymdToString(cal, ymd) +
                          " " + FIELD_NAME[f] + "(" + f + ")=" + v +
                          ", actual=" + minActual + ".." + maxActual +
                          ", allowed=(" + minLow + ".." + minHigh + ")..(" +
                          maxLow + ".." + maxHigh + ")");
                }
            }
        }
        greg.add(UCAL_DAY_OF_YEAR, 1, status);
        if (failure(status, "Calendar::add")) {
            return;
        }
    }

    // Check actual maxima and minima seen against ranges returned
    // by API.
    UnicodeString buf;
    for (j = 0; fieldsToTest[j] >= 0; ++j) {
        int32_t rangeLow, rangeHigh;
        UBool fullRangeSeen = TRUE;
        UCalendarDateFields f = (UCalendarDateFields)fieldsToTest[j];

        buf.remove();
        buf.append((UnicodeString)"[" + cal.getType() + "] " + FIELD_NAME[f]);

        // Minumum
        rangeLow = cal.getMinimum(f);
        rangeHigh = cal.getGreatestMinimum(f);
        if (limits[j][0] != rangeLow || limits[j][1] != rangeHigh) {
            fullRangeSeen = FALSE;
        }
        buf.append((UnicodeString)" minima range=" + rangeLow + ".." + rangeHigh);
        buf.append((UnicodeString)" minima actual=" + limits[j][0] + ".." + limits[j][1]);

        // Maximum
        rangeLow = cal.getLeastMaximum(f);
        rangeHigh = cal.getMaximum(f);
        if (limits[j][2] != rangeLow || limits[j][3] != rangeHigh) {
            fullRangeSeen = FALSE;
        }
        buf.append((UnicodeString)" maxima range=" + rangeLow + ".." + rangeHigh);
        buf.append((UnicodeString)" maxima actual=" + limits[j][2] + ".." + limits[j][3]);

        if (fullRangeSeen) {
            logln((UnicodeString)"OK: " + buf);
        } else {
            // This may or may not be an error -- if the range of dates
            // we scan over doesn't happen to contain a minimum or
            // maximum, it doesn't mean some other range won't.
            logln((UnicodeString)"Warning: " + buf);
        }
    }

    logln((UnicodeString)"End: " + greg.getTime(status));
}
Beispiel #12
0
/**
* Return the maximum value that this field could have, given the current date.
* For example, with the date "Feb 3, 1997" and the DAY_OF_MONTH field, the actual
* maximum would be 28; for "Feb 3, 1996" it s 29.  Similarly for a Hebrew calendar,
* for some years the actual maximum for MONTH is 12, and for others 13.
* @stable ICU 2.0
*/
int32_t GregorianCalendar::getActualMaximum(UCalendarDateFields field, UErrorCode& status) const
{
    /* It is a known limitation that the code here (and in getActualMinimum)
    * won't behave properly at the extreme limits of GregorianCalendar's
    * representable range (except for the code that handles the YEAR
    * field).  That's because the ends of the representable range are at
    * odd spots in the year.  For calendars with the default Gregorian
    * cutover, these limits are Sun Dec 02 16:47:04 GMT 292269055 BC to Sun
    * Aug 17 07:12:55 GMT 292278994 AD, somewhat different for non-GMT
    * zones.  As a result, if the calendar is set to Aug 1 292278994 AD,
    * the actual maximum of DAY_OF_MONTH is 17, not 30.  If the date is Mar
    * 31 in that year, the actual maximum month might be Jul, whereas is
    * the date is Mar 15, the actual maximum might be Aug -- depending on
    * the precise semantics that are desired.  Similar considerations
    * affect all fields.  Nonetheless, this effect is sufficiently arcane
    * that we permit it, rather than complicating the code to handle such
    * intricacies. - liu 8/20/98

    * UPDATE: No longer true, since we have pulled in the limit values on
    * the year. - Liu 11/6/00 */

    switch (field) {

    case UCAL_YEAR:
        /* The year computation is no different, in principle, from the
        * others, however, the range of possible maxima is large.  In
        * addition, the way we know we've exceeded the range is different.
        * For these reasons, we use the special case code below to handle
        * this field.
        *
        * The actual maxima for YEAR depend on the type of calendar:
        *
        *     Gregorian = May 17, 292275056 BC - Aug 17, 292278994 AD
        *     Julian    = Dec  2, 292269055 BC - Jan  3, 292272993 AD
        *     Hybrid    = Dec  2, 292269055 BC - Aug 17, 292278994 AD
        *
        * We know we've exceeded the maximum when either the month, date,
        * time, or era changes in response to setting the year.  We don't
        * check for month, date, and time here because the year and era are
        * sufficient to detect an invalid year setting.  NOTE: If code is
        * added to check the month and date in the future for some reason,
        * Feb 29 must be allowed to shift to Mar 1 when setting the year.
        */
        {
            if(U_FAILURE(status)) return 0;
            Calendar *cal = clone();
            if(!cal) {
                status = U_MEMORY_ALLOCATION_ERROR;
                return 0;
            }

            cal->setLenient(TRUE);

            int32_t era = cal->get(UCAL_ERA, status);
            UDate d = cal->getTime(status);

            /* Perform a binary search, with the invariant that lowGood is a
            * valid year, and highBad is an out of range year.
            */
            int32_t lowGood = kGregorianCalendarLimits[UCAL_YEAR][1];
            int32_t highBad = kGregorianCalendarLimits[UCAL_YEAR][2]+1;
            while ((lowGood + 1) < highBad) {
                int32_t y = (lowGood + highBad) / 2;
                cal->set(UCAL_YEAR, y);
                if (cal->get(UCAL_YEAR, status) == y && cal->get(UCAL_ERA, status) == era) {
                    lowGood = y;
                } else {
                    highBad = y;
                    cal->setTime(d, status); // Restore original fields
                }
            }

            delete cal;
            return lowGood;
        }

    default:
        return Calendar::getActualMaximum(field,status);
    }
}
Beispiel #13
0
/**
    * Check that the given year/month/dom/hour maps to and from the
    * given epochHours.  This verifies the functioning of the
    * calendar and time zone in conjunction with one another,
    * including the calendar time->fields and fields->time and
    * the time zone getOffset method.
    *
    * @param epochHours hours after Jan 1 1970 0:00 GMT.
    */
void TimeZoneBoundaryTest::verifyMapping(Calendar& cal, int year, int month, int dom, int hour,
                    double epochHours) {
    double H = 3600000.0;
    UErrorCode status = U_ZERO_ERROR;
    cal.clear();
    cal.set(year, month, dom, hour, 0, 0);
    UDate e = cal.getTime(status)/ H;
    UDate ed = (epochHours * H);
    if (e == epochHours) {
        logln(UnicodeString("Ok: ") + year + "/" + (month+1) + "/" + dom + " " + hour + ":00 => " +
                e + " (" + ed + ")");
    } else {
        dataerrln(UnicodeString("FAIL: ") + year + "/" + (month+1) + "/" + dom + " " + hour + ":00 => " +
                e + " (" + (e * H) + ")" +
                ", expected " + epochHours + " (" + ed + ")");
    }
    cal.setTime(ed, status);
    if (cal.get(UCAL_YEAR, status) == year &&
        cal.get(UCAL_MONTH, status) == month &&
        cal.get(UCAL_DATE, status) == dom &&
        cal.get(UCAL_MILLISECONDS_IN_DAY, status) == hour * 3600000) {
        logln(UnicodeString("Ok: ") + epochHours + " (" + ed + ") => " +
                cal.get(UCAL_YEAR, status) + "/" +
                (cal.get(UCAL_MONTH, status)+1) + "/" +
                cal.get(UCAL_DATE, status) + " " +
                cal.get(UCAL_MILLISECOND, status)/H);
    } else {
        dataerrln(UnicodeString("FAIL: ") + epochHours + " (" + ed + ") => " +
                cal.get(UCAL_YEAR, status) + "/" +
                (cal.get(UCAL_MONTH, status)+1) + "/" +
                cal.get(UCAL_DATE, status) + " " +
                cal.get(UCAL_MILLISECOND, status)/H +
                ", expected " + year + "/" + (month+1) + "/" + dom +
                " " + hour);
    }
}
Beispiel #14
0
/**
 * Get values of date-time fields
 *
 * @param time
 * @param locale
 * @param tz
 *
 * @return list
 *
 * @version 0.5-1 (Marek Gagolewski, 2015-01-01)
 * @version 0.5-1 (Marek Gagolewski, 2015-03-03) tz arg added
 */
SEXP stri_datetime_fields(SEXP time, SEXP tz, SEXP locale) {
   PROTECT(time = stri_prepare_arg_POSIXct(time, "time"));
   const char* locale_val = stri__prepare_arg_locale(locale, "locale", true);
   if (!isNull(tz)) PROTECT(tz = stri_prepare_arg_string_1(tz, "tz"));
   else             PROTECT(tz); /* needed to set tzone attrib */

   TimeZone* tz_val = stri__prepare_arg_timezone(tz, "tz", true/*allowdefault*/);
   Calendar* cal = NULL;
   STRI__ERROR_HANDLER_BEGIN(2)
   R_len_t vectorize_length = LENGTH(time);
   StriContainerDouble time_cont(time, vectorize_length);

   UErrorCode status = U_ZERO_ERROR;
   cal = Calendar::createInstance(locale_val, status);
   STRI__CHECKICUSTATUS_THROW(status, {/* do nothing special on err */})

   cal->adoptTimeZone(tz_val);
   tz_val = NULL; /* The Calendar takes ownership of the TimeZone. */

   SEXP ret;
#define STRI__FIELDS_NUM 14
   STRI__PROTECT(ret = Rf_allocVector(VECSXP, STRI__FIELDS_NUM));
   for (R_len_t j=0; j<STRI__FIELDS_NUM; ++j)
      SET_VECTOR_ELT(ret, j, Rf_allocVector(INTSXP, vectorize_length));

   for (R_len_t i=0; i<vectorize_length; ++i) {
      if (time_cont.isNA(i)) {
         for (R_len_t j=0; j<STRI__FIELDS_NUM; ++j)
            INTEGER(VECTOR_ELT(ret, j))[i] = NA_INTEGER;
         continue;
      }

      status = U_ZERO_ERROR;
      cal->setTime((UDate)(time_cont.get(i)*1000.0), status);
      STRI__CHECKICUSTATUS_THROW(status, {/* do nothing special on err */})

      for (R_len_t j=0; j<STRI__FIELDS_NUM; ++j) {
         UCalendarDateFields units_field;
         switch (j) {
            case 0:  units_field = UCAL_EXTENDED_YEAR;          break;
            case 1:  units_field = UCAL_MONTH;                  break;
            case 2:  units_field = UCAL_DAY_OF_MONTH;           break;
            case 3:  units_field = UCAL_HOUR_OF_DAY;            break;
            case 4:  units_field = UCAL_MINUTE;                 break;
            case 5:  units_field = UCAL_SECOND;                 break;
            case 6:  units_field = UCAL_MILLISECOND;            break;
            case 7:  units_field = UCAL_WEEK_OF_YEAR;           break;
            case 8:  units_field = UCAL_WEEK_OF_MONTH;          break;
            case 9:  units_field = UCAL_DAY_OF_YEAR;            break;
            case 10: units_field = UCAL_DAY_OF_WEEK;            break;
            case 11: units_field = UCAL_HOUR;                   break;
            case 12: units_field = UCAL_AM_PM;                  break;
            case 13: units_field = UCAL_ERA;                    break;
            default: throw StriException(MSG__INCORRECT_MATCH_OPTION, "units");
         }
         //UCAL_IS_LEAP_MONTH
         //UCAL_MILLISECONDS_IN_DAY -> SecondsInDay

         // UCAL_AM_PM -> "AM" or "PM" (localized? or factor?+index in stri_datetime_symbols) add arg use_symbols????
         // UCAL_DAY_OF_WEEK -> (localized? or factor?) SUNDAY, MONDAY
         // UCAL_DAY_OF_YEAR '

         // isWekend

         status = U_ZERO_ERROR;
         INTEGER(VECTOR_ELT(ret, j))[i] = cal->get(units_field, status);
         STRI__CHECKICUSTATUS_THROW(status, {/* do nothing special on err */})

         if (units_field == UCAL_MONTH)      ++INTEGER(VECTOR_ELT(ret, j))[i]; // month + 1
         else if (units_field == UCAL_AM_PM) ++INTEGER(VECTOR_ELT(ret, j))[i]; // ampm + 1
         else if (units_field == UCAL_ERA)   ++INTEGER(VECTOR_ELT(ret, j))[i]; // era + 1
      }