ICU-6855 Add internal RelativeDateFormat toPattern/applyPattern functions
X-SVN-Rev: 25830
This commit is contained in:
parent
55945d1d63
commit
bf6746fb3b
@ -16,6 +16,7 @@
|
||||
|
||||
#include "reldtfmt.h"
|
||||
#include "unicode/msgfmt.h"
|
||||
#include "unicode/smpdtfmt.h"
|
||||
|
||||
#include "gregoimp.h" // for CalendarData
|
||||
#include "cmemory.h"
|
||||
@ -254,6 +255,67 @@ const UChar *RelativeDateFormat::getStringForDay(int32_t day, int32_t &len, UErr
|
||||
return NULL; // not found.
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
RelativeDateFormat::toPattern(UnicodeString& result, UErrorCode& status) const
|
||||
{
|
||||
if (!U_FAILURE(status)) {
|
||||
result.remove();
|
||||
UnicodeString datePattern, timePattern;
|
||||
this->toPatternDate(datePattern, status);
|
||||
this->toPatternTime(timePattern, status);
|
||||
if ( datePattern.length() > 0 ) {
|
||||
if ( timePattern.length() > 0 && fCombinedFormat) {
|
||||
Formattable timeDatePatterns[] = { timePattern, datePattern };
|
||||
FieldPosition pos;
|
||||
fCombinedFormat->format(timeDatePatterns, 2, result, pos, status);
|
||||
}
|
||||
if ( result.length() == 0 ) {
|
||||
result.setTo(datePattern);
|
||||
}
|
||||
} else {
|
||||
result.setTo(timePattern);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
RelativeDateFormat::toPatternDate(UnicodeString& result, UErrorCode& status) const
|
||||
{
|
||||
if (!U_FAILURE(status)) {
|
||||
result.remove();
|
||||
if ( fDateFormat && fDateFormat->getDynamicClassID()==SimpleDateFormat::getStaticClassID() ) {
|
||||
((SimpleDateFormat*)fDateFormat)->toPattern(result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
RelativeDateFormat::toPatternTime(UnicodeString& result, UErrorCode& status) const
|
||||
{
|
||||
if (!U_FAILURE(status)) {
|
||||
result.remove();
|
||||
if ( fTimeFormat && fTimeFormat->getDynamicClassID()==SimpleDateFormat::getStaticClassID() ) {
|
||||
((SimpleDateFormat*)fTimeFormat)->toPattern(result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
RelativeDateFormat::applyPatterns(const UnicodeString& datePattern, const UnicodeString& timePattern, UErrorCode &status)
|
||||
{
|
||||
if (!U_FAILURE(status)) {
|
||||
if ( fDateFormat && fDateFormat->getDynamicClassID()==SimpleDateFormat::getStaticClassID() ) {
|
||||
((SimpleDateFormat*)fDateFormat)->applyPattern(datePattern);
|
||||
}
|
||||
if ( fTimeFormat && fTimeFormat->getDynamicClassID()==SimpleDateFormat::getStaticClassID() ) {
|
||||
((SimpleDateFormat*)fTimeFormat)->applyPattern(timePattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RelativeDateFormat::loadDates(UErrorCode &status) {
|
||||
CalendarData calData(fLocale, "gregorian", status);
|
||||
|
||||
@ -267,7 +329,7 @@ void RelativeDateFormat::loadDates(UErrorCode &status) {
|
||||
int32_t glueIndex = kDateTime;
|
||||
if (patternsSize >= (DateFormat::kDateTimeOffset + DateFormat::kShort + 1)) {
|
||||
// Get proper date time format
|
||||
switch (fDateStyle) {
|
||||
switch (fDateStyle) {
|
||||
case kFullRelative:
|
||||
case kFull:
|
||||
glueIndex = kDateTimeOffset + kFull;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "unicode/dtfmtsym.h"
|
||||
#include "unicode/ustring.h"
|
||||
#include "cpputils.h"
|
||||
#include "reldtfmt.h"
|
||||
|
||||
U_NAMESPACE_USE
|
||||
|
||||
@ -283,7 +284,6 @@ udat_toPattern( const UDateFormat *fmt,
|
||||
int32_t resultLength,
|
||||
UErrorCode *status)
|
||||
{
|
||||
verifyIsSimpleDateFormat(fmt, status);
|
||||
if(U_FAILURE(*status)) return -1;
|
||||
|
||||
UnicodeString res;
|
||||
@ -293,10 +293,17 @@ udat_toPattern( const UDateFormat *fmt,
|
||||
res.setTo(result, 0, resultLength);
|
||||
}
|
||||
|
||||
if(localized)
|
||||
((SimpleDateFormat*)fmt)->toLocalizedPattern(res, *status);
|
||||
else
|
||||
((SimpleDateFormat*)fmt)->toPattern(res);
|
||||
if ( ((DateFormat*)fmt)->getDynamicClassID()==SimpleDateFormat::getStaticClassID() ) {
|
||||
if(localized)
|
||||
((SimpleDateFormat*)fmt)->toLocalizedPattern(res, *status);
|
||||
else
|
||||
((SimpleDateFormat*)fmt)->toPattern(res);
|
||||
} else if ( !localized && ((DateFormat*)fmt)->getDynamicClassID()==RelativeDateFormat::getStaticClassID() ) {
|
||||
((RelativeDateFormat*)fmt)->toPattern(res, *status);
|
||||
} else {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return res.extract(result, resultLength, *status);
|
||||
}
|
||||
@ -838,4 +845,71 @@ udat_getLocaleByType(const UDateFormat *fmt,
|
||||
}
|
||||
return ((Format*)fmt)->getLocaleID(type, *status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that fmt is a RelativeDateFormat. Invalid error if not.
|
||||
* @param fmt the UDateFormat, definitely a DateFormat, maybe something else
|
||||
* @param status error code, will be set to failure if there is a familure or the fmt is NULL.
|
||||
*/
|
||||
static void verifyIsRelativeDateFormat(const UDateFormat* fmt, UErrorCode *status) {
|
||||
if(!U_FAILURE(*status) &&
|
||||
((DateFormat*)fmt)->getDynamicClassID()!=RelativeDateFormat::getStaticClassID()) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
udat_toPatternRelativeDate(const UDateFormat *fmt,
|
||||
UChar *result,
|
||||
int32_t resultLength,
|
||||
UErrorCode *status)
|
||||
{
|
||||
verifyIsRelativeDateFormat(fmt, status);
|
||||
if(U_FAILURE(*status)) return -1;
|
||||
|
||||
UnicodeString datePattern;
|
||||
if(!(result==NULL && resultLength==0)) {
|
||||
// NULL destination for pure preflighting: empty dummy string
|
||||
// otherwise, alias the destination buffer
|
||||
datePattern.setTo(result, 0, resultLength);
|
||||
}
|
||||
((RelativeDateFormat*)fmt)->toPatternDate(datePattern, *status);
|
||||
return datePattern.extract(result, resultLength, *status);
|
||||
}
|
||||
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
udat_toPatternRelativeTime(const UDateFormat *fmt,
|
||||
UChar *result,
|
||||
int32_t resultLength,
|
||||
UErrorCode *status)
|
||||
{
|
||||
verifyIsRelativeDateFormat(fmt, status);
|
||||
if(U_FAILURE(*status)) return -1;
|
||||
|
||||
UnicodeString timePattern;
|
||||
if(!(result==NULL && resultLength==0)) {
|
||||
// NULL destination for pure preflighting: empty dummy string
|
||||
// otherwise, alias the destination buffer
|
||||
timePattern.setTo(result, 0, resultLength);
|
||||
}
|
||||
((RelativeDateFormat*)fmt)->toPatternTime(timePattern, *status);
|
||||
return timePattern.extract(result, resultLength, *status);
|
||||
}
|
||||
|
||||
U_CAPI void U_EXPORT2
|
||||
udat_applyPatternRelative(UDateFormat *format,
|
||||
const UChar *datePattern,
|
||||
int32_t datePatternLength,
|
||||
const UChar *timePattern,
|
||||
int32_t timePatternLength,
|
||||
UErrorCode *status)
|
||||
{
|
||||
verifyIsRelativeDateFormat(format, status);
|
||||
if(U_FAILURE(*status)) return;
|
||||
const UnicodeString datePat((UBool)(datePatternLength == -1), datePattern, datePatternLength);
|
||||
const UnicodeString timePat((UBool)(timePatternLength == -1), timePattern, timePatternLength);
|
||||
((RelativeDateFormat*)format)->applyPatterns(datePat, timePat, *status);
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
@ -383,7 +383,13 @@ while the calls to udat_format are after midnight or span midnight.
|
||||
static const UDate dayInterval = 24.0*60.0*60.0*1000.0;
|
||||
static const UChar trdfZone[] = { 0x0055, 0x0053, 0x002F, 0x0050, 0x0061, 0x0063, 0x0069, 0x0066, 0x0069, 0x0063, 0 }; /* US/Pacific */
|
||||
static const char trdfLocale[] = "en_US";
|
||||
static const UChar minutesPatn[] = { 0x006D, 0x006D, 0 }; /* "mm" */
|
||||
static const UChar monthLongPatn[] = { 0x004D, 0x004D, 0x004D, 0x004D, 0 }; /* "MMMM" */
|
||||
static const UChar monthMediumPatn[] = { 0x004D, 0x004D, 0x004D, 0 }; /* "MMM" */
|
||||
static const UChar monthShortPatn[] = { 0x004D, 0 }; /* "M" */
|
||||
static const UDateFormatStyle dateStylesList[] = { UDAT_FULL, UDAT_LONG, UDAT_MEDIUM, UDAT_SHORT, UDAT_NONE };
|
||||
static const UChar *monthPatnsList[] = { monthLongPatn, monthLongPatn, monthMediumPatn, monthShortPatn, NULL };
|
||||
static const UChar newTimePatn[] = { 0x0048, 0x0048, 0x002C, 0x006D, 0x006D, 0 }; /* "HH,mm" */
|
||||
static const UChar minutesStr[] = { 0x0034, 0x0039, 0 }; /* "49", minutes string to search for in output */
|
||||
enum { kDateOrTimeOutMax = 96, kDateAndTimeOutMax = 192 };
|
||||
|
||||
@ -391,6 +397,7 @@ static void TestRelativeDateFormat()
|
||||
{
|
||||
UDate today = 0.0;
|
||||
const UDateFormatStyle * stylePtr;
|
||||
const UChar ** monthPtnPtr;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UCalendar * ucal = ucal_open(trdfZone, -1, trdfLocale, UCAL_GREGORIAN, &status);
|
||||
if ( U_SUCCESS(status) ) {
|
||||
@ -407,12 +414,17 @@ static void TestRelativeDateFormat()
|
||||
log_err("Generate UDate for a specified time today fails, error %s\n", myErrorName(status) );
|
||||
return;
|
||||
}
|
||||
for (stylePtr = dateStylesList; *stylePtr != UDAT_NONE; ++stylePtr) {
|
||||
for (stylePtr = dateStylesList, monthPtnPtr = monthPatnsList; *stylePtr != UDAT_NONE; ++stylePtr, ++monthPtnPtr) {
|
||||
UDateFormat* fmtRelDateTime;
|
||||
UDateFormat* fmtRelDate;
|
||||
UDateFormat* fmtTime;
|
||||
int32_t dayOffset, limit;
|
||||
UFieldPosition fp;
|
||||
UChar strDateTime[kDateAndTimeOutMax];
|
||||
UChar strDate[kDateOrTimeOutMax];
|
||||
UChar strTime[kDateOrTimeOutMax];
|
||||
UChar * strPtr;
|
||||
int32_t dtpatLen;
|
||||
|
||||
fmtRelDateTime = udat_open(UDAT_SHORT, *stylePtr | UDAT_RELATIVE, trdfLocale, trdfZone, -1, NULL, 0, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
@ -433,24 +445,56 @@ static void TestRelativeDateFormat()
|
||||
continue;
|
||||
}
|
||||
|
||||
dtpatLen = udat_toPatternRelativeDate(fmtRelDateTime, strDate, kDateAndTimeOutMax, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("udat_toPatternRelativeDate timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
|
||||
status = U_ZERO_ERROR;
|
||||
} else if ( u_strstr(strDate, *monthPtnPtr) == NULL || dtpatLen != u_strlen(strDate) ) {
|
||||
log_err("udat_toPatternRelativeDate timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) date pattern incorrect\n", *stylePtr );
|
||||
}
|
||||
dtpatLen = udat_toPatternRelativeTime(fmtRelDateTime, strTime, kDateAndTimeOutMax, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("udat_toPatternRelativeTime timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
|
||||
status = U_ZERO_ERROR;
|
||||
} else if ( u_strstr(strTime, minutesPatn) == NULL || dtpatLen != u_strlen(strTime) ) {
|
||||
log_err("udat_toPatternRelativeTime timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) time pattern incorrect\n", *stylePtr );
|
||||
}
|
||||
dtpatLen = udat_toPattern(fmtRelDateTime, FALSE, strDateTime, kDateAndTimeOutMax, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
|
||||
status = U_ZERO_ERROR;
|
||||
} else if ( u_strstr(strDateTime, strDate) == NULL || u_strstr(strDateTime, strTime) == NULL || dtpatLen != u_strlen(strDateTime) ) {
|
||||
log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) dateTime pattern incorrect\n", *stylePtr );
|
||||
}
|
||||
udat_applyPatternRelative(fmtRelDateTime, strDate, u_strlen(strDate), newTimePatn, u_strlen(newTimePatn), &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("udat_applyPatternRelative timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
|
||||
status = U_ZERO_ERROR;
|
||||
} else {
|
||||
udat_toPattern(fmtRelDateTime, FALSE, strDateTime, kDateAndTimeOutMax, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
|
||||
status = U_ZERO_ERROR;
|
||||
} else if ( u_strstr(strDateTime, newTimePatn) == NULL ) {
|
||||
log_err("udat_applyPatternRelative timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) didn't update time pattern\n", *stylePtr );
|
||||
}
|
||||
}
|
||||
udat_applyPatternRelative(fmtRelDateTime, strDate, u_strlen(strDate), strTime, u_strlen(strTime), &status); /* restore original */
|
||||
|
||||
fp.field = UDAT_MINUTE_FIELD;
|
||||
for (dayOffset = -2, limit = 2; dayOffset <= limit; ++dayOffset) {
|
||||
UChar strRelDateTime[kDateAndTimeOutMax];
|
||||
UChar strRelDate[kDateOrTimeOutMax];
|
||||
UChar strTime[kDateOrTimeOutMax];
|
||||
UChar * strPtr;
|
||||
UDate dateToUse = today + (float)dayOffset*dayInterval;
|
||||
|
||||
udat_format(fmtRelDateTime, dateToUse, strRelDateTime, kDateAndTimeOutMax, &fp, &status);
|
||||
udat_format(fmtRelDateTime, dateToUse, strDateTime, kDateAndTimeOutMax, &fp, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
|
||||
status = U_ZERO_ERROR;
|
||||
} else {
|
||||
udat_format(fmtRelDate, dateToUse, strRelDate, kDateOrTimeOutMax, NULL, &status);
|
||||
udat_format(fmtRelDate, dateToUse, strDate, kDateOrTimeOutMax, NULL, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("udat_format timeStyle NONE dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
|
||||
status = U_ZERO_ERROR;
|
||||
} else if ( u_strstr(strRelDateTime, strRelDate) == NULL ) {
|
||||
} else if ( u_strstr(strDateTime, strDate) == NULL ) {
|
||||
log_err("relative date string not found in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", *stylePtr );
|
||||
}
|
||||
|
||||
@ -458,13 +502,13 @@ static void TestRelativeDateFormat()
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("udat_format timeStyle SHORT dateStyle NONE fails, error %s\n", myErrorName(status) );
|
||||
status = U_ZERO_ERROR;
|
||||
} else if ( u_strstr(strRelDateTime, strTime) == NULL ) {
|
||||
} else if ( u_strstr(strDateTime, strTime) == NULL ) {
|
||||
log_err("time string not found in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", *stylePtr );
|
||||
}
|
||||
|
||||
strPtr = u_strstr(strRelDateTime, minutesStr);
|
||||
strPtr = u_strstr(strDateTime, minutesStr);
|
||||
if ( strPtr != NULL ) {
|
||||
int32_t beginIndex = strPtr - strRelDateTime;
|
||||
int32_t beginIndex = strPtr - strDateTime;
|
||||
if ( fp.beginIndex != beginIndex ) {
|
||||
log_err("UFieldPosition beginIndex %d, expected %d, in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", fp.beginIndex, beginIndex, *stylePtr );
|
||||
}
|
||||
@ -1120,10 +1164,11 @@ static void TestRelativeCrash(void) {
|
||||
}
|
||||
}
|
||||
{
|
||||
/* Now udat_toPattern works for relative date formatters, unless localized is TRUE */
|
||||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
what = "udat_toPattern";
|
||||
log_verbose("Trying %s on a relative date..\n", what);
|
||||
udat_toPattern(icudf, FALSE,NULL,0, &subStatus);
|
||||
udat_toPattern(icudf, TRUE,NULL,0, &subStatus);
|
||||
if(subStatus == expectStatus) {
|
||||
log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user