/** * An array of URelativeString structs is used to store the resource data loaded out of the bundle.
*/ struct URelativeString {
int32_t offset; /** offset of this item, such as, the relative date **/
int32_t len; /** length of the string **/ const char16_t* string; /** string, or nullptr if not set **/
};
if (timeStyle < UDAT_NONE || timeStyle > UDAT_SHORT) { // don't support other time styles (e.g. relative styles), for now
status = U_ILLEGAL_ARGUMENT_ERROR; return;
}
UDateFormatStyle baseDateStyle = (dateStyle > UDAT_SHORT) ? static_cast<UDateFormatStyle>(dateStyle & ~UDAT_RELATIVE) : dateStyle;
DateFormat * df; // Get fDateTimeFormatter from either date or time style (does not matter, we will override the pattern). // We do need to get separate patterns for the date & time styles. if (baseDateStyle != UDAT_NONE) {
df = createDateInstance(static_cast<EStyle>(baseDateStyle), locale);
fDateTimeFormatter=dynamic_cast<SimpleDateFormat *>(df); if (fDateTimeFormatter == nullptr) {
status = U_UNSUPPORTED_ERROR; return;
}
fDateTimeFormatter->toPattern(fDatePattern); if (timeStyle != UDAT_NONE) {
df = createTimeInstance(static_cast<EStyle>(timeStyle), locale);
SimpleDateFormat *sdf = dynamic_cast<SimpleDateFormat *>(df); if (sdf != nullptr) {
sdf->toPattern(fTimePattern); delete sdf;
}
}
} else { // does not matter whether timeStyle is UDAT_NONE, we need something for fDateTimeFormatter
df = createTimeInstance(static_cast<EStyle>(timeStyle), locale);
fDateTimeFormatter=dynamic_cast<SimpleDateFormat *>(df); if (fDateTimeFormatter == nullptr) {
status = U_UNSUPPORTED_ERROR; delete df; return;
}
fDateTimeFormatter->toPattern(fTimePattern);
}
// Initialize the parent fCalendar, so that parse() works correctly.
initializeCalendar(nullptr, locale, status);
loadDates(status);
}
// calculate the difference, in days, between 'cal' and now. int dayDiff = dayDifference(cal, status);
// look up string
int32_t len = 0; const char16_t *theString = getStringForDay(dayDiff, len, status); if(U_SUCCESS(status) && (theString!=nullptr)) { // found a relative string
relativeDayString.setTo(theString, len);
}
if ( relativeDayString.length() > 0 && !fDatePattern.isEmpty() &&
(fTimePattern.isEmpty() || fCombinedFormat == nullptr || fCombinedHasDateAtStart)) { #if !UCONFIG_NO_BREAK_ITERATION // capitalize relativeDayString according to context for relative, set formatter no context if ( u_islower(relativeDayString.char32At(0)) && fCapitalizationBrkIter!= nullptr &&
( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
(capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && fCapitalizationOfRelativeUnitsForUIListMenu) ||
(capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && fCapitalizationOfRelativeUnitsForStandAlone) ) ) { // titlecase first word of relativeDayString
relativeDayString.toTitle(fCapitalizationBrkIter, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
} #endif
fDateTimeFormatter->setContext(UDISPCTX_CAPITALIZATION_NONE, status);
} else { // set our context for the formatter
fDateTimeFormatter->setContext(capitalizationContext, status);
}
if (fDatePattern.isEmpty()) {
fDateTimeFormatter->applyPattern(fTimePattern);
fDateTimeFormatter->format(cal,appendTo,pos);
} elseif (fTimePattern.isEmpty() || fCombinedFormat == nullptr) { if (relativeDayString.length() > 0) {
appendTo.append(relativeDayString);
} else {
fDateTimeFormatter->applyPattern(fDatePattern);
fDateTimeFormatter->format(cal,appendTo,pos);
}
} else {
UnicodeString datePattern; if (relativeDayString.length() > 0) { // Need to quote the relativeDayString to make it a legal date pattern
relativeDayString.findAndReplace(UNICODE_STRING("'", 1), UNICODE_STRING("''", 2)); // double any existing APOSTROPHE
relativeDayString.insert(0, APOSTROPHE); // add APOSTROPHE at beginning...
relativeDayString.append(APOSTROPHE); // and at end
datePattern.setTo(relativeDayString);
} else {
datePattern.setTo(fDatePattern);
}
UnicodeString combinedPattern;
fCombinedFormat->format(fTimePattern, datePattern, combinedPattern, status);
fDateTimeFormatter->applyPattern(combinedPattern);
fDateTimeFormatter->format(cal,appendTo,pos);
}
return appendTo;
}
UnicodeString&
RelativeDateFormat::format(const Formattable& obj,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode& status) const
{ // this is just here to get around the hiding problem // (the previous format() override would hide the version of // format() on DateFormat that this function correspond to, so we // have to redefine it here) return DateFormat::format(obj, appendTo, pos, status);
}
int32_t startIndex = pos.getIndex(); if (fDatePattern.isEmpty()) { // no date pattern, try parsing as time
fDateTimeFormatter->applyPattern(fTimePattern);
fDateTimeFormatter->parse(text,cal,pos);
} elseif (fTimePattern.isEmpty() || fCombinedFormat == nullptr) { // 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 != nullptr &&
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 != nullptr &&
(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;
}
// 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);
} elseif (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);
}
}
}
UDate
RelativeDateFormat::parse( const UnicodeString& text,
ParsePosition& pos) const { // redefined here because the other parse() function hides this function's // counterpart on DateFormat return DateFormat::parse(text, pos);
}
UDate
RelativeDateFormat::parse(const UnicodeString& text, UErrorCode& status) const
{ // redefined here because the other parse() function hides this function's // counterpart on DateFormat return DateFormat::parse(text, status);
}
// Is it inside the resource bundle's range? int n = day + UDAT_DIRECTION_THIS; if (n >= 0 && n < fDatesLen) { if (fDates[n].offset == day && fDates[n].string != nullptr) {
len = fDates[n].len; return fDates[n].string;
}
} return nullptr; // not found.
}
/** * Sink for getting data from fields/day/relative data. * For loading relative day names, e.g., "yesterday", "today".
*/
struct RelDateFmtDataSink : public ResourceSink {
URelativeString *fDatesPtr;
int32_t fDatesLen;
RelDateFmtDataSink(URelativeString* fDates, int32_t len) : fDatesPtr(fDates), fDatesLen(len) { for (int32_t i = 0; i < fDatesLen; ++i) {
fDatesPtr[i].offset = 0;
fDatesPtr[i].string = nullptr;
fDatesPtr[i].len = -1;
}
}
virtual ~RelDateFmtDataSink();
virtualvoid put(constchar *key, ResourceValue &value,
UBool /*noFallback*/, UErrorCode &errorCode) override {
ResourceTable relDayTable = value.getTable(errorCode);
int32_t n = 0;
int32_t len = 0; for (int32_t i = 0; relDayTable.getKeyAndValue(i, key, value); ++i) { // Find the relative offset.
int32_t offset = atoi(key);
// Put in the proper spot, but don't override existing data.
n = offset + UDAT_DIRECTION_THIS; // Converts to index in UDAT_R if (0 <= n && n < fDatesLen && fDatesPtr[n].string == nullptr) { // Not found and n is an empty slot.
fDatesPtr[n].offset = offset;
fDatesPtr[n].string = value.getString(len, errorCode);
fDatesPtr[n].len = len;
}
}
}
};
// Virtual destructors must be defined out of line.
RelDateFmtDataSink::~RelDateFmtDataSink() {}
// Data loading for relative names, e.g., "yesterday", "today", "tomorrow".
fDatesLen = UDAT_DIRECTION_COUNT; // Maximum defined by data.
fDates = static_cast<URelativeString*>(uprv_malloc(sizeof(fDates[0]) * fDatesLen));
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;
}
U_NAMESPACE_END
#endif/* !UCONFIG_NO_FORMATTING */
Messung V0.5
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.