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. } }
void Init(double timeStart, double timeTo) { // invalid time if (timeStart > timeTo || timeStart < 0) { fprintf(stderr, "Invalid time range set\n"); exit(-1); } Time_t = timeStart; Time_tStart = timeStart; calendar.add(Event(timeTo, HIGH_PRIORITY, NULL)); }
void RelativeDateFormat::parse( const UnicodeString& text, Calendar& cal, ParsePosition& pos) const { // Can the fDateFormat parse it? if(fDateFormat != NULL) { ParsePosition aPos(pos); fDateFormat->parse(text,cal,aPos); if((aPos.getIndex() != pos.getIndex()) && (aPos.getErrorIndex()==-1)) { pos=aPos; // copy the sub parse return; // parsed subfmt OK } } // Linear search the relative strings for(int n=0; n<fDatesLen; n++) { if(fDates[n].string != NULL && (0==text.compare(pos.getIndex(), fDates[n].len, fDates[n].string))) { UErrorCode status = U_ZERO_ERROR; // 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 fields pos.setErrorIndex(pos.getIndex()+fDates[n].len); } else { pos.setIndex(pos.getIndex()+fDates[n].len); } return; } } // parse failed }
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 DataDrivenFormatTest::testConvertDate(TestData *testData, const DataMap * /* settings */, UBool fmt) { UnicodeString kPATTERN("PATTERN="); // TODO: static UnicodeString kMILLIS("MILLIS="); // TODO: static UnicodeString kRELATIVE_MILLIS("RELATIVE_MILLIS="); // TODO: static UnicodeString kRELATIVE_ADD("RELATIVE_ADD:"); // TODO: static UErrorCode status = U_ZERO_ERROR; SimpleDateFormat basicFmt(UnicodeString("EEE MMM dd yyyy / YYYY'-W'ww-ee"), status); if (U_FAILURE(status)) { dataerrln("FAIL: Couldn't create basic SimpleDateFormat: %s", u_errorName(status)); return; } const DataMap *currentCase= NULL; // Start the processing int n = 0; while (testData->nextCase(currentCase, status)) { char calLoc[256] = ""; DateTimeStyleSet styleSet; UnicodeString pattern; UBool usePattern = FALSE; (void)usePattern; // Suppress unused warning. CalendarFieldsSet fromSet; UDate fromDate = 0; UBool useDate = FALSE; UDate now = Calendar::getNow(); ++n; char theCase[200]; sprintf(theCase, "case %d:", n); UnicodeString caseString(theCase, ""); // load params UnicodeString locale = currentCase->getString("locale", status); if (U_FAILURE(status)) { errln("case %d: No 'locale' line.", n); continue; } UnicodeString zone = currentCase->getString("zone", status); if (U_FAILURE(status)) { errln("case %d: No 'zone' line.", n); continue; } UnicodeString spec = currentCase->getString("spec", status); if(U_FAILURE(status)) { errln("case %d: No 'spec' line.", n); continue; } UnicodeString date = currentCase->getString("date", status); if(U_FAILURE(status)) { errln("case %d: No 'date' line.", n); continue; } UnicodeString expectStr= currentCase->getString("str", status); if(U_FAILURE(status)) { errln("case %d: No 'str' line.", n); continue; } DateFormat *format = NULL; // Process: 'locale' locale.extract(0, locale.length(), calLoc, (const char*)0); // default codepage. Invariant codepage doesn't have '@'! Locale loc(calLoc); if(spec.startsWith(kPATTERN)) { pattern = UnicodeString(spec,kPATTERN.length()); usePattern = TRUE; format = new SimpleDateFormat(pattern, loc, status); if(U_FAILURE(status)) { errln("case %d: could not create SimpleDateFormat from pattern: %s", n, u_errorName(status)); continue; } } else { if(styleSet.parseFrom(spec, status)<0 || U_FAILURE(status)) { errln("case %d: could not parse spec as style fields: %s", n, u_errorName(status)); continue; } format = DateFormat::createDateTimeInstance((DateFormat::EStyle)styleSet.getDateStyle(), (DateFormat::EStyle)styleSet.getTimeStyle(), loc); if(format == NULL ) { errln("case %d: could not create SimpleDateFormat from styles.", n); continue; } } Calendar *cal = Calendar::createInstance(loc, status); if(U_FAILURE(status)) { errln("case %d: could not create calendar from %s", n, calLoc); } if (zone.length() > 0) { TimeZone * tz = TimeZone::createTimeZone(zone); cal->setTimeZone(*tz); format->setTimeZone(*tz); delete tz; } // parse 'date' if(date.startsWith(kMILLIS)) { UnicodeString millis = UnicodeString(date, kMILLIS.length()); useDate = TRUE; fromDate = udbg_stod(millis); } else if(date.startsWith(kRELATIVE_MILLIS)) { UnicodeString millis = UnicodeString(date, kRELATIVE_MILLIS.length()); useDate = TRUE; fromDate = udbg_stod(millis) + now; } else if(date.startsWith(kRELATIVE_ADD)) { UnicodeString add = UnicodeString(date, kRELATIVE_ADD.length()); // "add" is a string indicating which fields to add if(fromSet.parseFrom(add, status)<0 || U_FAILURE(status)) { errln("case %d: could not parse date as RELATIVE_ADD calendar fields: %s", n, u_errorName(status)); continue; } useDate=TRUE; cal->clear(); cal->setTime(now, status); for (int q=0; q<UCAL_FIELD_COUNT; q++) { if (fromSet.isSet((UCalendarDateFields)q)) { //int32_t oldv = cal->get((UCalendarDateFields)q, status); if (q == UCAL_DATE) { cal->add((UCalendarDateFields)q, fromSet.get((UCalendarDateFields)q), status); } else { cal->set((UCalendarDateFields)q, fromSet.get((UCalendarDateFields)q)); } //int32_t newv = cal->get((UCalendarDateFields)q, status); } } fromDate = cal->getTime(status); if(U_FAILURE(status)) { errln("case %d: could not apply date as RELATIVE_ADD calendar fields: %s", n, u_errorName(status)); continue; } } else if(fromSet.parseFrom(date, status)<0 || U_FAILURE(status)) { errln("case %d: could not parse date as calendar fields: %s", n, u_errorName(status)); continue; } // now, do it. if (fmt) { FieldPosition pos; // logln((UnicodeString)"#"+n+" "+locale+"/"+from+" >>> "+toCalLoc+"/" // +to); cal->clear(); UnicodeString output; output.remove(); if(useDate) { // cal->setTime(fromDate, status); // if(U_FAILURE(status)) { // errln("case %d: could not set time on calendar: %s", n, u_errorName(status)); // continue; // } format->format(fromDate, output, pos, status); } else { fromSet.setOnCalendar(cal, status); if(U_FAILURE(status)) { errln("case %d: could not set fields on calendar: %s", n, u_errorName(status)); continue; } format->format(*cal, output, pos); } // check erro result from 'format' if(U_FAILURE(status)) { errln("case %d: could not format(): %s", n, u_errorName(status)); // TODO: use 'pos' } // if(pos.getBeginIndex()==0 && pos.getEndIndex()==0) { // TODO: more precise error? // errln("WARNING: case %d: format's pos returned (0,0) - error ??", n); // } if(output == expectStr) { logln(caseString+": format: SUCCESS! "+UnicodeString("expect=output=")+output); } else { UnicodeString result; UnicodeString result2; errln(caseString+": format: output!=expectStr, got " + *udbg_escape(output, &result) + " expected " + *udbg_escape(expectStr, &result2)); } } else { cal->clear(); ParsePosition pos; format->parse(expectStr,*cal,pos); if(useDate) { UDate gotDate = cal->getTime(status); if(U_FAILURE(status)) { errln(caseString+": parse: could not get time on calendar: "+UnicodeString(u_errorName(status))); continue; } if(gotDate == fromDate) { logln(caseString+": parse: SUCCESS! "+UnicodeString("gotDate=parseDate=")+expectStr); } else { UnicodeString expectDateStr, gotDateStr; basicFmt.format(fromDate,expectDateStr); basicFmt.format(gotDate,gotDateStr); errln(caseString+": parse: FAIL. parsed '"+expectStr+"' and got "+gotDateStr+", expected " + expectDateStr); } } else { // Calendar *cal2 = cal->clone(); // cal2->clear(); // fromSet.setOnCalendar(cal2, status); if(U_FAILURE(status)) { errln("case %d: parse: could not set fields on calendar: %s", n, u_errorName(status)); continue; } CalendarFieldsSet diffSet; // diffSet.clear(); if (!fromSet.matches(cal, diffSet, status)) { UnicodeString diffs = diffSet.diffFrom(fromSet, status); errln((UnicodeString)"FAIL: "+caseString +", Differences: '"+ diffs +"', status: "+ u_errorName(status)); } else if (U_FAILURE(status)) { errln("FAIL: "+caseString+" parse SET SOURCE calendar Failed to match: " +u_errorName(status)); } else { logln("PASS: "******" parse."); } } } delete cal; delete format; } // delete basicFmt; }
/** Date-time artithmetic * * @param time * @param value * @param units * @param tz * @param locale * * @return POSIXst * * @version 0.5-1 (Marek Gagolewski, 2014-12-30) * @version 0.5-1 (Marek Gagolewski, 2015-03-06) tz arg added */ SEXP stri_datetime_add(SEXP time, SEXP value, SEXP units, SEXP tz, SEXP locale) { PROTECT(time = stri_prepare_arg_POSIXct(time, "time")); PROTECT(value = stri_prepare_arg_integer(value, "value")); if (!isNull(tz)) PROTECT(tz = stri_prepare_arg_string_1(tz, "tz")); else PROTECT(tz); /* needed to set tzone attrib */ R_len_t vectorize_length = stri__recycling_rule(true, 2, LENGTH(time), LENGTH(value)); const char* units_val = stri__prepare_arg_string_1_notNA(units, "units"); const char* units_opts[] = {"years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", NULL}; int units_cur = stri__match_arg(units_val, units_opts); const char* locale_val = stri__prepare_arg_locale(locale, "locale", true); TimeZone* tz_val = stri__prepare_arg_timezone(tz, "tz", true/*allowdefault*/); Calendar* cal = NULL; STRI__ERROR_HANDLER_BEGIN(3) StriContainerDouble time_cont(time, vectorize_length); StriContainerInteger value_cont(value, vectorize_length); UCalendarDateFields units_field; switch (units_cur) { case 0: units_field = UCAL_YEAR; break; case 1: units_field = UCAL_MONTH; break; case 2: units_field = UCAL_WEEK_OF_YEAR; break; case 3: units_field = UCAL_DAY_OF_MONTH; break; case 4: units_field = UCAL_HOUR_OF_DAY; break; case 5: units_field = UCAL_MINUTE; break; case 6: units_field = UCAL_SECOND; break; case 7: units_field = UCAL_MILLISECOND; break; default: throw StriException(MSG__INCORRECT_MATCH_OPTION, "units"); } 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; STRI__PROTECT(ret = Rf_allocVector(REALSXP, vectorize_length)); double* ret_val = REAL(ret); for (R_len_t i=0; i<vectorize_length; ++i) { if (time_cont.isNA(i) || value_cont.isNA(i)) { ret_val[i] = NA_REAL; continue; } status = U_ZERO_ERROR; cal->setTime((UDate)(time_cont.get(i)*1000.0), status); STRI__CHECKICUSTATUS_THROW(status, {/* do nothing special on err */}) status = U_ZERO_ERROR; cal->add(units_field, value_cont.get(i), status); STRI__CHECKICUSTATUS_THROW(status, {/* do nothing special on err */}) status = U_ZERO_ERROR; ret_val[i] = ((double)cal->getTime(status))/1000.0; STRI__CHECKICUSTATUS_THROW(status, {/* do nothing special on err */}) } if (!isNull(tz)) Rf_setAttrib(ret, Rf_ScalarString(Rf_mkChar("tzone")), tz); stri__set_class_POSIXct(ret); if (tz_val) { delete tz_val; tz_val = NULL; } if (cal) { delete cal; cal = NULL; } STRI__UNPROTECT_ALL return ret; STRI__ERROR_HANDLER_END({ if (tz_val) { delete tz_val; tz_val = NULL; } if (cal) { delete cal; cal = NULL; } }) }
std::string GlobalizationNDK::getDateNames(const std::string& args) { ENamesType type = kNamesWide; ENamesItem item = kNamesMonths; if (!args.empty()) { Json::Reader reader; Json::Value root; bool parse = reader.parse(args, root); if (!parse) { slog2f(0, ID_G11N, SLOG2_ERROR, "GlobalizationNDK::getDateNames: invalid json data: %s", args.c_str()); return errorInJson(PARSING_ERROR, "Parameters not valid json format!"); } Json::Value options = root["options"]; std::string error; if (!handleNamesOptions(options, type, item, error)) return errorInJson(PARSING_ERROR, error); } int count; const char* pattern; DateFormat::EStyle dstyle; // Check ICU SimpleDateFormat document for patterns for months and days. // http://www.icu-project.org/apiref/icu4c/classicu_1_1SimpleDateFormat.html if (item == kNamesMonths) { count = 12; if (type == kNamesWide) { dstyle = DateFormat::kLong; pattern = "MMMM"; } else { dstyle = DateFormat::kShort; pattern = "MMM"; } } else { count = 7; if (type == kNamesWide) { dstyle = DateFormat::kLong; pattern = "eeee"; } else { dstyle = DateFormat::kShort; pattern = "eee"; } } UErrorCode status = U_ZERO_ERROR; const Locale& loc = Locale::getDefault(); DateFormat* df = DateFormat::createDateInstance(dstyle, loc); if (!df) { slog2f(0, ID_G11N, SLOG2_ERROR, "GlobalizationNDK::getDateNames: unable to create DateFormat instance!"); return errorInJson(UNKNOWN_ERROR, "Unable to create DateFormat instance!"); } std::auto_ptr<DateFormat> deleter(df); if (df->getDynamicClassID() != SimpleDateFormat::getStaticClassID()) { slog2f(0, ID_G11N, SLOG2_ERROR, "GlobalizationNDK::getDateNames: DateFormat instance not SimpleDateFormat!"); return errorInJson(UNKNOWN_ERROR, "DateFormat instance not SimpleDateFormat!"); } SimpleDateFormat* sdf = (SimpleDateFormat*) df; sdf->applyLocalizedPattern(UnicodeString(pattern, -1), status); Calendar* cal = Calendar::createInstance(status); if (!cal) { slog2f(0, ID_G11N, SLOG2_ERROR, "GlobalizationNDK::getDateNames: unable to create Calendar instance: %x.", status); return errorInJson(UNKNOWN_ERROR, "Unable to create Calendar instance!"); } std::auto_ptr<Calendar> caldeleter(cal); UCalendarDaysOfWeek ud = cal->getFirstDayOfWeek(status); if (status != U_ZERO_ERROR && status != U_ERROR_WARNING_START) { slog2f(0, ID_G11N, SLOG2_ERROR, "GlobalizationNDK::getDateNames: failed to getFirstDayOfWeek: %d!", status); return errorInJson(PARSING_ERROR, "Failed to getFirstDayOfWeek!"); } if (ud == UCAL_SUNDAY) cal->set(2014, 0, 5); else cal->set(2014, 0, 6); std::list<std::string> utf8Names; for (int i = 0; i < count; ++i) { UnicodeString ucs; sdf->format(cal->getTime(status), ucs); if (item == kNamesMonths) cal->add(UCAL_MONTH, 1, status); else cal->add(UCAL_DAY_OF_MONTH, 1, status); if (ucs.isEmpty()) continue; std::string utf8; ucs.toUTF8String(utf8); utf8Names.push_back(utf8); } if (!utf8Names.size()) { slog2f(0, ID_G11N, SLOG2_ERROR, "GlobalizationNDK::getDateNames: unable to get symbols: item: %d, type: %d.", item, type); return errorInJson(UNKNOWN_ERROR, "Unable to get symbols!"); } return resultInJson(utf8Names); }