void iCalConverter::setSource(Calendar& inputCalendar) { if(calendar) delete calendar; calendar = (Calendar *)inputCalendar.clone(); if(iCalendar) { delete [] iCalendar; iCalendar = NULL; } }
//---------------------------------------------------------------------- void DateFormat::setCalendar(const Calendar& newCalendar) { Calendar* newCalClone = newCalendar.clone(); if (newCalClone != NULL) { adoptCalendar(newCalClone); } }
/* {{{ proto bool datefmt_set_calendar(IntlDateFormatter $mf, mixed $calendar) * Set formatter's calendar. */ U_CFUNC PHP_FUNCTION(datefmt_set_calendar) { zval *calendar_zv; DATE_FORMAT_METHOD_INIT_VARS; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz", &object, IntlDateFormatter_ce_ptr, &calendar_zv) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_set_calendar: unable to parse input params", 0 TSRMLS_CC); RETURN_FALSE; } DATE_FORMAT_METHOD_FETCH_OBJECT; Calendar *cal; long cal_type; bool cal_owned; Locale locale = Locale::createFromName(dfo->requested_locale); // getting the actual locale from the DateFormat is not enough // because we would have lost modifiers such as @calendar. We // must store the requested locale on object creation if (datefmt_process_calendar_arg(calendar_zv, locale, "datefmt_set_calendar", INTL_DATA_ERROR_P(dfo), cal, cal_type, cal_owned TSRMLS_CC) == FAILURE) { RETURN_FALSE; } if (cal_owned) { /* a non IntlCalendar was specified, we want to keep the timezone */ TimeZone *old_timezone = fetch_datefmt(dfo)->getTimeZone().clone(); if (old_timezone == NULL) { intl_errors_set(INTL_DATA_ERROR_P(dfo), U_MEMORY_ALLOCATION_ERROR, "datefmt_set_calendar: Out of memory when cloning calendar", 0 TSRMLS_CC); delete cal; RETURN_FALSE; } cal->adoptTimeZone(old_timezone); } else { cal = cal->clone(); if (cal == NULL) { intl_errors_set(INTL_DATA_ERROR_P(dfo), U_MEMORY_ALLOCATION_ERROR, "datefmt_set_calendar: Out of memory when cloning calendar", 0 TSRMLS_CC); RETURN_FALSE; } } fetch_datefmt(dfo)->adoptCalendar(cal); dfo->calendar = cal_type; RETURN_TRUE; }
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; }
void IntlCalendarTest::TestJapanese3860() { Calendar *cal; UErrorCode status = U_ZERO_ERROR; cal = Calendar::createInstance("ja_JP@calendar=japanese", status); CHECK(status, UnicodeString("Creating ja_JP@calendar=japanese calendar")); Calendar *cal2 = cal->clone(); SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("HH:mm:ss.S MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status); UnicodeString str; { // Test simple parse/format with adopt UDate aDate = 0; // Test parse with missing era (should default to current era, heisei) // Test parse with incomplete information logln("Testing parse w/ missing era..."); SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("y.M.d"), Locale("ja_JP@calendar=japanese"), status); CHECK(status, "creating date format instance"); if(!fmt) { errln("Coudln't create en_US instance"); } else { UErrorCode s2 = U_ZERO_ERROR; cal2->clear(); UnicodeString samplestr("1.1.9"); logln(UnicodeString() + "Test Year: " + samplestr); aDate = fmt->parse(samplestr, s2); ParsePosition pp=0; fmt->parse(samplestr, *cal2, pp); CHECK(s2, "parsing the 1.1.9 string"); logln("*cal2 after 119 parse:"); str.remove(); fmt2->format(aDate, str); logln(UnicodeString() + "as Gregorian Calendar: " + str); cal2->setTime(aDate, s2); int32_t gotYear = cal2->get(UCAL_YEAR, s2); int32_t gotEra = cal2->get(UCAL_ERA, s2); int32_t expectYear = 1; int32_t expectEra = JapaneseCalendar::getCurrentEra(); if((gotYear!=1) || (gotEra != expectEra)) { errln(UnicodeString("parse "+samplestr+" of 'y.m.d' as Japanese Calendar, expected year ") + expectYear + UnicodeString(" and era ") + expectEra +", but got year " + gotYear + " and era " + gotEra + " (Gregorian:" + str +")"); } else { logln(UnicodeString() + " year: " + gotYear + ", era: " + gotEra); } delete fmt; } } { // Test simple parse/format with adopt UDate aDate = 0; // Test parse with missing era (should default to current era, heisei) // Test parse with incomplete information logln("Testing parse w/ just year..."); SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("y"), Locale("ja_JP@calendar=japanese"), status); CHECK(status, "creating date format instance"); if(!fmt) { errln("Coudln't create en_US instance"); } else { UErrorCode s2 = U_ZERO_ERROR; cal2->clear(); UnicodeString samplestr("1"); logln(UnicodeString() + "Test Year: " + samplestr); aDate = fmt->parse(samplestr, s2); ParsePosition pp=0; fmt->parse(samplestr, *cal2, pp); CHECK(s2, "parsing the 1 string"); logln("*cal2 after 1 parse:"); str.remove(); fmt2->format(aDate, str); logln(UnicodeString() + "as Gregorian Calendar: " + str); cal2->setTime(aDate, s2); int32_t gotYear = cal2->get(UCAL_YEAR, s2); int32_t gotEra = cal2->get(UCAL_ERA, s2); int32_t expectYear = 1; int32_t expectEra = 235; //JapaneseCalendar::kCurrentEra; if((gotYear!=1) || (gotEra != expectEra)) { errln(UnicodeString("parse "+samplestr+" of 'y' as Japanese Calendar, expected year ") + expectYear + UnicodeString(" and era ") + expectEra +", but got year " + gotYear + " and era " + gotEra + " (Gregorian:" + str +")"); } else { logln(UnicodeString() + " year: " + gotYear + ", era: " + gotEra); } delete fmt; } } delete cal2; delete cal; delete fmt2; }
void IntlCalendarTest::TestJapaneseFormat() { Calendar *cal; UErrorCode status = U_ZERO_ERROR; cal = Calendar::createInstance("ja_JP_TRADITIONAL", status); CHECK(status, UnicodeString("Creating ja_JP_TRADITIONAL calendar")); Calendar *cal2 = cal->clone(); delete cal; cal = NULL; // Test simple parse/format with adopt UDate aDate = 999932400000.0; SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yy G"), Locale("en_US@calendar=japanese"), status); SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status); CHECK(status, "creating date format instance"); if(!fmt) { errln("Coudln't create en_US instance"); } else { UnicodeString str; fmt2->format(aDate, str); logln(UnicodeString() + "Test Date: " + str); str.remove(); fmt->format(aDate, str); logln(UnicodeString() + "as Japanese Calendar: " + str); UnicodeString expected("September 8, 13 Heisei"); if(str != expected) { errln("Expected " + expected + " but got " + str); } UDate otherDate = fmt->parse(expected, status); if(otherDate != aDate) { UnicodeString str3; ParsePosition pp; fmt->parse(expected, *cal2, pp); fmt->format(otherDate, str3); errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " + " = " + otherDate + ", " + str3 + " = " + CalendarTest::calToStr(*cal2) ); } else { logln("Parsed OK: " + expected); } delete fmt; } // Test parse with incomplete information fmt = new SimpleDateFormat(UnicodeString("G y"), Locale("en_US@calendar=japanese"), status); aDate = -3197117222000.0; CHECK(status, "creating date format instance"); if(!fmt) { errln("Coudln't create en_US instance"); } else { UnicodeString str; fmt2->format(aDate, str); logln(UnicodeString() + "Test Date: " + str); str.remove(); fmt->format(aDate, str); logln(UnicodeString() + "as Japanese Calendar: " + str); UnicodeString expected("Meiji 1"); if(str != expected) { errln("Expected " + expected + " but got " + str); } UDate otherDate = fmt->parse(expected, status); if(otherDate != aDate) { UnicodeString str3; ParsePosition pp; fmt->parse(expected, *cal2, pp); fmt->format(otherDate, str3); errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " + " = " + otherDate + ", " + str3 + " = " + CalendarTest::calToStr(*cal2) ); } else { logln("Parsed OK: " + expected); } delete fmt; } delete cal2; delete fmt2; CHECK(status, "Error occured"); // Now, try in Japanese { UnicodeString expect = CharsToUnicodeString("\\u5e73\\u621013\\u5e749\\u67088\\u65e5\\u571f\\u66dc\\u65e5"); UDate expectDate = 999932400000.0; // Testing a recent date Locale loc("ja_JP@calendar=japanese"); status = U_ZERO_ERROR; simpleTest(loc, expect, expectDate, status); } { UnicodeString expect = CharsToUnicodeString("\\u5e73\\u621013\\u5e749\\u67088\\u65e5\\u571f\\u66dc\\u65e5"); UDate expectDate = 999932400000.0; // Testing a recent date Locale loc("ja_JP_TRADITIONAL"); // legacy status = U_ZERO_ERROR; simpleTest(loc, expect, expectDate, status); } { UnicodeString expect = CharsToUnicodeString("\\u5b89\\u6c385\\u5e747\\u67084\\u65e5\\u6728\\u66dc\\u65e5"); UDate expectDate = -6106032422000.0; // 1776-07-04T00:00:00Z-075258 Locale loc("ja_JP@calendar=japanese"); status = U_ZERO_ERROR; simpleTest(loc, expect, expectDate, status); } { // Jitterbug 1869 - this is an ambiguous era. (Showa 64 = Jan 6 1989, but Showa could be 2 other eras) ) UnicodeString expect = CharsToUnicodeString("\\u662d\\u548c64\\u5e741\\u67086\\u65e5\\u91d1\\u66dc\\u65e5"); UDate expectDate = 600076800000.0; Locale loc("ja_JP@calendar=japanese"); status = U_ZERO_ERROR; simpleTest(loc, expect, expectDate, status); } { // This Feb 29th falls on a leap year by gregorian year, but not by Japanese year. UnicodeString expect = CharsToUnicodeString("\\u5EB7\\u6B632\\u5e742\\u670829\\u65e5\\u65e5\\u66dc\\u65e5"); UDate expectDate = -16214400422000.0; // 1456-03-09T00:00Z-075258 Locale loc("ja_JP@calendar=japanese"); status = U_ZERO_ERROR; simpleTest(loc, expect, expectDate, status); } }
void RelativeDateFormat::parse( const UnicodeString& text, Calendar& cal, ParsePosition& pos) const { int32_t startIndex = pos.getIndex(); if (fDatePattern.isEmpty()) { // no date pattern, try parsing as time fDateTimeFormatter->applyPattern(fTimePattern); fDateTimeFormatter->parse(text,cal,pos); } else if (fTimePattern.isEmpty() || fCombinedFormat == NULL) { // no time pattern or way to combine, try parsing as date // first check whether text matches a relativeDayString UBool matchedRelative = FALSE; for (int n=0; n < fDatesLen && !matchedRelative; n++) { if (fDates[n].string != NULL && text.compare(startIndex, fDates[n].len, fDates[n].string) == 0) { // it matched, handle the relative day string UErrorCode status = U_ZERO_ERROR; matchedRelative = TRUE; // Set the calendar to now+offset cal.setTime(Calendar::getNow(),status); cal.add(UCAL_DATE,fDates[n].offset, status); if(U_FAILURE(status)) { // failure in setting calendar field, set offset to beginning of rel day string pos.setErrorIndex(startIndex); } else { pos.setIndex(startIndex + fDates[n].len); } } } if (!matchedRelative) { // just parse as normal date fDateTimeFormatter->applyPattern(fDatePattern); fDateTimeFormatter->parse(text,cal,pos); } } else { // Here we replace any relativeDayString in text with the equivalent date // formatted per fDatePattern, then parse text normally using the combined pattern. UnicodeString modifiedText(text); FieldPosition fPos; int32_t dateStart = 0, origDateLen = 0, modDateLen = 0; UErrorCode status = U_ZERO_ERROR; for (int n=0; n < fDatesLen; n++) { int32_t relativeStringOffset; if (fDates[n].string != NULL && (relativeStringOffset = modifiedText.indexOf(fDates[n].string, fDates[n].len, startIndex)) >= startIndex) { // it matched, replace the relative date with a real one for parsing UnicodeString dateString; Calendar * tempCal = cal.clone(); // Set the calendar to now+offset tempCal->setTime(Calendar::getNow(),status); tempCal->add(UCAL_DATE,fDates[n].offset, status); if(U_FAILURE(status)) { pos.setErrorIndex(startIndex); delete tempCal; return; } fDateTimeFormatter->applyPattern(fDatePattern); fDateTimeFormatter->format(*tempCal, dateString, fPos); dateStart = relativeStringOffset; origDateLen = fDates[n].len; modDateLen = dateString.length(); modifiedText.replace(dateStart, origDateLen, dateString); delete tempCal; break; } } UnicodeString combinedPattern; fCombinedFormat->format(fTimePattern, fDatePattern, combinedPattern, status); fDateTimeFormatter->applyPattern(combinedPattern); fDateTimeFormatter->parse(modifiedText,cal,pos); // Adjust offsets UBool noError = (pos.getErrorIndex() < 0); int32_t offset = (noError)? pos.getIndex(): pos.getErrorIndex(); if (offset >= dateStart + modDateLen) { // offset at or after the end of the replaced text, // correct by the difference between original and replacement offset -= (modDateLen - origDateLen); } else if (offset >= dateStart) { // offset in the replaced text, set it to the beginning of that text // (i.e. the beginning of the relative day string) offset = dateStart; } if (noError) { pos.setIndex(offset); } else { pos.setErrorIndex(offset); } } }
//---------------------------------------------------------------------- void DateFormat::setCalendar(const Calendar& newCalendar) { adoptCalendar(newCalendar.clone()); }
void IntlCalendarTest::TestJapaneseFormat() { Calendar *cal; UErrorCode status = U_ZERO_ERROR; cal = Calendar::createInstance("ja_JP_TRADITIONAL", status); CHECK(status, UnicodeString("Creating ja_JP_TRADITIONAL calendar")); Calendar *cal2 = cal->clone(); delete cal; cal = NULL; // Test simple parse/format with adopt UDate aDate = 999932400000.0; SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yy G"), Locale("en_US@calendar=japanese"), status); SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status); CHECK(status, "creating date format instance"); if(!fmt) { errln("Coudln't create en_US instance"); } else { UnicodeString str; fmt2->format(aDate, str); logln(UnicodeString() + "Test Date: " + str); str.remove(); fmt->format(aDate, str); logln(UnicodeString() + "as Japanese Calendar: " + str); UnicodeString expected("September 8, 13 Heisei"); if(str != expected) { errln("Expected " + expected + " but got " + str); } UDate otherDate = fmt->parse(expected, status); if(otherDate != aDate) { UnicodeString str3; ParsePosition pp; fmt->parse(expected, *cal2, pp); fmt->format(otherDate, str3); errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " + " = " + otherDate + ", " + str3 + " = " + CalendarTest::calToStr(*cal2) ); } else { logln("Parsed OK: " + expected); } delete fmt; } // Test parse with incomplete information fmt = new SimpleDateFormat(UnicodeString("G y"), Locale("en_US@calendar=japanese"), status); /* The test data below should points to 1868-09-08T00:00:00 in America/Los_Angeles. * The time calculated by original test code uses -7:00 UTC offset, because it assumes * DST is observed (because of a timezone bug, DST is observed for early 20th century * day to infinite past time). The bug was fixed and DST is no longer used for time before * 1900 for any zones. However, ICU timezone transition data is represented by 32-bit integer * (sec) and cannot represent transitions before 1901 defined in Olson tzdata. For example, * based on Olson definition, offset -7:52:58 should be used for Nov 18, 1883 or older dates. * If ICU properly capture entire Olson zone definition, the start time of "Meiji 1" is * -3197117222000. -Yoshito */ /* TODO: When ICU support the Olson LMT offset for America/Los_Angeles, we need to update * the reference data. */ //aDate = -3197120400000.; aDate = -3197116800000.; CHECK(status, "creating date format instance"); if(!fmt) { errln("Coudln't create en_US instance"); } else { UnicodeString str; fmt2->format(aDate, str); logln(UnicodeString() + "Test Date: " + str); str.remove(); fmt->format(aDate, str); logln(UnicodeString() + "as Japanese Calendar: " + str); UnicodeString expected("Meiji 1"); if(str != expected) { errln("Expected " + expected + " but got " + str); } UDate otherDate = fmt->parse(expected, status); if(otherDate != aDate) { UnicodeString str3; ParsePosition pp; fmt->parse(expected, *cal2, pp); fmt->format(otherDate, str3); errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " + " = " + otherDate + ", " + str3 + " = " + CalendarTest::calToStr(*cal2) ); } else { logln("Parsed OK: " + expected); } delete fmt; } delete cal2; delete fmt2; CHECK(status, "Error occured"); // Now, try in Japanese { UnicodeString expect = CharsToUnicodeString("\\u5e73\\u621013\\u5e749\\u67088\\u65e5\\u571f\\u66dc\\u65e5"); UDate expectDate = 999932400000.0; // Testing a recent date Locale loc("ja_JP@calendar=japanese"); status = U_ZERO_ERROR; simpleTest(loc, expect, expectDate, status); } { UnicodeString expect = CharsToUnicodeString("\\u5e73\\u621013\\u5e749\\u67088\\u65e5\\u571f\\u66dc\\u65e5"); UDate expectDate = 999932400000.0; // Testing a recent date Locale loc("ja_JP_TRADITIONAL"); // legacy status = U_ZERO_ERROR; simpleTest(loc, expect, expectDate, status); } { UnicodeString expect = CharsToUnicodeString("\\u5b89\\u6c385\\u5e747\\u67084\\u65e5\\u6728\\u66dc\\u65e5"); //UDate expectDate = -6106035600000.0; UDate expectDate = -6106032000000.0; // 1776-07-04T00:00:00Z-0800 Locale loc("ja_JP@calendar=japanese"); status = U_ZERO_ERROR; simpleTest(loc, expect, expectDate, status); } { // Jitterbug 1869 - this is an ambiguous era. (Showa 64 = Jan 6 1989, but Showa could be 2 other eras) ) UnicodeString expect = CharsToUnicodeString("\\u662d\\u548c64\\u5e741\\u67086\\u65e5\\u91d1\\u66dc\\u65e5"); UDate expectDate = 600076800000.0; Locale loc("ja_JP@calendar=japanese"); status = U_ZERO_ERROR; simpleTest(loc, expect, expectDate, status); } { // This Feb 29th falls on a leap year by gregorian year, but not by Japanese year. UnicodeString expect = CharsToUnicodeString("\\u5EB7\\u6B632\\u5e742\\u670829\\u65e5\\u65e5\\u66dc\\u65e5"); // Add -1:00 to the following for historical TZ - aliu //UDate expectDate = -16214403600000.0; // courtesy of date format round trip test UDate expectDate = -16214400000000.0; // 1456-03-09T00:00:00Z-0800 Locale loc("ja_JP@calendar=japanese"); status = U_ZERO_ERROR; simpleTest(loc, expect, expectDate, status); } }