From eddf3c7f4c4423ad8cca20c9d8a879ae951484a3 Mon Sep 17 00:00:00 2001 From: Peter Edberg Date: Fri, 4 Mar 2016 05:54:01 +0000 Subject: [PATCH] ICU-12072 C, Updates per review comments X-SVN-Rev: 38481 --- icu4c/source/i18n/reldatefmt.cpp | 34 +++++----- .../test/cintltst/crelativedateformattest.c | 64 ++++++++++++------- 2 files changed, 58 insertions(+), 40 deletions(-) diff --git a/icu4c/source/i18n/reldatefmt.cpp b/icu4c/source/i18n/reldatefmt.cpp index 6975d2315d7..b7cd167816f 100644 --- a/icu4c/source/i18n/reldatefmt.cpp +++ b/icu4c/source/i18n/reldatefmt.cpp @@ -905,7 +905,7 @@ UnicodeString& RelativeDateTimeFormatter::formatNumeric( case UDAT_REL_UNIT_MINUTE: relunit = UDAT_RELATIVE_MINUTES; break; case UDAT_REL_UNIT_SECOND: relunit = UDAT_RELATIVE_SECONDS; break; default: // a unit that the above method does not handle - status = U_MISSING_RESOURCE_ERROR; + status = U_UNSUPPORTED_ERROR; return appendTo; } UDateDirection direction = UDAT_DIRECTION_NEXT; @@ -951,14 +951,18 @@ UnicodeString& RelativeDateTimeFormatter::format( // rewrite this to use it directly, and rewrite the old format method to call this // new one; that is covered by http://bugs.icu-project.org/trac/ticket/12171. UDateDirection direction = UDAT_DIRECTION_COUNT; - int32_t intoffset = (offset < 0)? (int32_t)(offset-0.5) : (int32_t)(offset+0.5); - switch (intoffset) { - case -2: direction = UDAT_DIRECTION_LAST_2; break; - case -1: direction = UDAT_DIRECTION_LAST; break; - case 0: direction = UDAT_DIRECTION_THIS; break; - case 1: direction = UDAT_DIRECTION_NEXT; break; - case 2: direction = UDAT_DIRECTION_NEXT_2; break; - default: break; + if (offset > -2.1 && offset < 2.1) { + // Allow a 1% epsilon, so offsets in -1.01..-0.99 map to LAST + double offsetx100 = offset * 100.0; + int32_t intoffset = (offsetx100 < 0)? (int32_t)(offsetx100-0.5) : (int32_t)(offsetx100+0.5); + switch (intoffset) { + case -200/*-2*/: direction = UDAT_DIRECTION_LAST_2; break; + case -100/*-1*/: direction = UDAT_DIRECTION_LAST; break; + case 0/* 0*/: direction = UDAT_DIRECTION_THIS; break; + case 100/* 1*/: direction = UDAT_DIRECTION_NEXT; break; + case 200/* 2*/: direction = UDAT_DIRECTION_NEXT_2; break; + default: break; + } } UDateAbsoluteUnit absunit = UDAT_ABSOLUTE_UNIT_COUNT; switch (unit) { @@ -966,7 +970,6 @@ UnicodeString& RelativeDateTimeFormatter::format( case UDAT_REL_UNIT_MONTH: absunit = UDAT_ABSOLUTE_MONTH; break; case UDAT_REL_UNIT_WEEK: absunit = UDAT_ABSOLUTE_WEEK; break; case UDAT_REL_UNIT_DAY: absunit = UDAT_ABSOLUTE_DAY; break; - case UDAT_REL_UNIT_MINUTE: case UDAT_REL_UNIT_SECOND: if (direction == UDAT_DIRECTION_THIS) { absunit = UDAT_ABSOLUTE_NOW; @@ -1086,7 +1089,7 @@ ureldatefmt_open( const char* locale, } LocalPointer formatter(new RelativeDateTimeFormatter(Locale(locale), (NumberFormat*)nfToAdopt, width, - capitalizationContext, *status)); + capitalizationContext, *status), *status); if (U_FAILURE(*status)) { return NULL; } @@ -1169,19 +1172,14 @@ ureldatefmt_combineDateAndTime( const URelativeDateTimeFormatter* reldatefmt, return 0; } if (result == NULL ? resultCapacity != 0 : resultCapacity < 0 || - relativeDateString == NULL || relativeDateStringLen < 1 || - timeString == NULL || timeStringLen < -1) { + (relativeDateString == NULL ? relativeDateStringLen != 0 : relativeDateStringLen < -1) || + (timeString == NULL ? timeStringLen != 0 : timeStringLen < -1)) { *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; } UnicodeString relDateStr((UBool)(relativeDateStringLen == -1), relativeDateString, relativeDateStringLen); UnicodeString timeStr((UBool)(timeStringLen == -1), timeString, timeStringLen); UnicodeString res; - if (result != NULL) { - // NULL destination for pure preflighting: empty dummy string - // otherwise, alias the destination buffer (copied from udat_format) - res.setTo(result, 0, resultCapacity); - } ((RelativeDateTimeFormatter*)reldatefmt)->combineDateAndTime(relDateStr, timeStr, res, *status); if (U_FAILURE(*status)) { return 0; diff --git a/icu4c/source/test/cintltst/crelativedateformattest.c b/icu4c/source/test/cintltst/crelativedateformattest.c index 4f3dac57429..93ce3d2debe 100644 --- a/icu4c/source/test/cintltst/crelativedateformattest.c +++ b/icu4c/source/test/cintltst/crelativedateformattest.c @@ -28,19 +28,20 @@ void addRelativeDateFormatTest(TestNode** root) TESTCASE(TestCombineDateTime); } -static const double offsets[] = { -5.0, -2.2, -1.0, -0.7, 0.0, 0.7, 1.0, 2.2, 5.0 }; +static const double offsets[] = { -5.0, -2.2, -2.0, -1.0, -0.7, 0.0, 0.7, 1.0, 2.0, 5.0 }; enum { kNumOffsets = UPRV_LENGTHOF(offsets) }; static const char* en_decDef_long_midSent_week[kNumOffsets*2] = { /* text numeric */ "5 weeks ago", "5 weeks ago", /* -5 */ "2.2 weeks ago", "2.2 weeks ago", /* -2.2 */ + "2 weeks ago", "2 weeks ago", /* -2 */ "last week", "1 week ago", /* -1 */ - "last week", "0.7 weeks ago", /* -0.7 */ + "0.7 weeks ago", "0.7 weeks ago", /* -0.7 */ "this week", "in 0 weeks", /* 0 */ - "next week", "in 0.7 weeks", /* 0.7 */ + "in 0.7 weeks", "in 0.7 weeks", /* 0.7 */ "next week", "in 1 week", /* 1 */ - "in 2.2 weeks", "in 2.2 weeks", /* 2.2 */ + "in 2 weeks", "in 2 weeks", /* 2 */ "in 5 weeks", "in 5 weeks" /* 5 */ }; @@ -48,12 +49,13 @@ static const char* en_dec0_long_midSent_week[kNumOffsets*2] = { /* text numeric */ "5 weeks ago", "5 weeks ago", /* -5 */ "2 weeks ago", "2 weeks ago", /* -2.2 */ + "2 weeks ago", "2 weeks ago", /* -2 */ "last week", "1 week ago", /* -1 */ - "last week", "0 weeks ago", /* -0.7 */ + "0 weeks ago", "0 weeks ago", /* -0.7 */ "this week", "in 0 weeks", /* 0 */ - "next week", "in 0 weeks", /* 0.7 */ + "in 0 weeks", "in 0 weeks", /* 0.7 */ "next week", "in 1 week", /* 1 */ - "in 2 weeks", "in 2 weeks", /* 2.2 */ + "in 2 weeks", "in 2 weeks", /* 2 */ "in 5 weeks", "in 5 weeks" /* 5 */ }; @@ -61,12 +63,13 @@ static const char* en_decDef_short_midSent_week[kNumOffsets*2] = { /* text numeric */ "5 wk. ago", "5 wk. ago", /* -5 */ "2.2 wk. ago", "2.2 wk. ago", /* -2.2 */ + "2 wk. ago", "2 wk. ago", /* -2 */ "last wk.", "1 wk. ago", /* -1 */ - "last wk.", "0.7 wk. ago", /* -0.7 */ + "0.7 wk. ago", "0.7 wk. ago", /* -0.7 */ "this wk.", "in 0 wk.", /* 0 */ - "next wk.", "in 0.7 wk.", /* 0.7 */ + "in 0.7 wk.", "in 0.7 wk.", /* 0.7 */ "next wk.", "in 1 wk.", /* 1 */ - "in 2.2 wk.", "in 2.2 wk.", /* 2.2 */ + "in 2 wk.", "in 2 wk.", /* 2 */ "in 5 wk.", "in 5 wk." /* 5 */ }; @@ -74,12 +77,13 @@ static const char* en_decDef_long_midSent_min[kNumOffsets*2] = { /* text numeric */ "5 minutes ago", "5 minutes ago", /* -5 */ "2.2 minutes ago", "2.2 minutes ago", /* -2.2 */ + "2 minutes ago", "2 minutes ago", /* -2 */ "1 minute ago", "1 minute ago", /* -1 */ "0.7 minutes ago", "0.7 minutes ago", /* -0.7 */ - "now", "in 0 minutes", /* 0 */ + "in 0 minutes", "in 0 minutes", /* 0 */ "in 0.7 minutes", "in 0.7 minutes", /* 0.7 */ "in 1 minute", "in 1 minute", /* 1 */ - "in 2.2 minutes", "in 2.2 minutes", /* 2.2 */ + "in 2 minutes", "in 2 minutes", /* 2 */ "in 5 minutes", "in 5 minutes" /* 5 */ }; @@ -87,25 +91,27 @@ static const char* en_dec0_long_midSent_tues[kNumOffsets*2] = { /* text numeric */ ""/*no data */, ""/*no data */, /* -5 */ ""/*no data */, ""/*no data */, /* -2.2 */ + ""/*no data */, ""/*no data */, /* -2 */ "last Tuesday", ""/*no data */, /* -1 */ - "last Tuesday", ""/*no data */, /* -0.7 */ + ""/*no data */, ""/*no data */, /* -0.7 */ "this Tuesday", ""/*no data */, /* 0 */ - "next Tuesday", ""/*no data */, /* 0.7 */ + ""/*no data */, ""/*no data */, /* 0.7 */ "next Tuesday", ""/*no data */, /* 1 */ - ""/*no data */, ""/*no data */, /* 2.2 */ + ""/*no data */, ""/*no data */, /* 2 */ ""/*no data */, ""/*no data */, /* 5 */ }; static const char* fr_decDef_long_midSent_day[kNumOffsets*2] = { /* text numeric */ "il y a 5 jours", "il y a 5 jours", /* -5 */ - "avant-hier", "il y a 2,2 jours", /* -2.2 */ + "il y a 2,2 jours", "il y a 2,2 jours", /* -2.2 */ + "avant-hier", "il y a 2 jours", /* -2 */ "hier", "il y a 1 jour", /* -1 */ - "hier", "il y a 0,7 jour", /* -0.7 */ + "il y a 0,7 jour", "il y a 0,7 jour", /* -0.7 */ "aujourd\\u2019hui", "dans 0 jour", /* 0 */ - "demain", "dans 0,7 jour", /* 0.7 */ + "dans 0,7 jour", "dans 0,7 jour", /* 0.7 */ "demain", "dans 1 jour", /* 1 */ - "apr\\u00E8s-demain", "dans 2,2 jours", /* 2.2 */ + "apr\\u00E8s-demain", "dans 2 jours", /* 2 */ "dans 5 jours", "dans 5 jours" /* 5 */ }; @@ -162,8 +168,8 @@ static void TestRelDateFmt() for (iOffset = 0; iOffset < kNumOffsets; iOffset++) { UChar ubufget[kUBufMax]; int32_t ulenget; - - if (itemPtr->unit >= UDAT_REL_UNIT_SUNDAY && (offsets[iOffset] < -1.0 || offsets[iOffset] > 1.0)) { + + if (itemPtr->unit >= UDAT_REL_UNIT_SUNDAY && (offsets[iOffset] != -1.0 || offsets[iOffset] != 0.0 || offsets[iOffset] != 1.0)) { continue; /* we do not currently have data for this */ } @@ -207,7 +213,7 @@ static void TestRelDateFmt() } } } - + ureldatefmt_close(reldatefmt); } } @@ -261,6 +267,20 @@ static void TestCombineDateTime() itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, itemPtr->expectedResult, bbufget ); } } + // preflight test + status = U_ZERO_ERROR; + ulenget = ureldatefmt_combineDateAndTime(reldatefmt, ubufreldate, ulenreldate, ubuftime, ulentime, NULL, 0, &status); + if ( status != U_BUFFER_OVERFLOW_ERROR) { + log_err("FAIL: ureldatefmt_combineDateAndTime() preflight for locale %s, width %d, capContext %d: expected U_BUFFER_OVERFLOW_ERROR, got %s\n", + itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, myErrorName(status) ); + } else { + UChar ubufexp[kUBufMax]; + int32_t ulenexp = u_unescape(itemPtr->expectedResult, ubufexp, kUBufMax); + if (ulenget != ulenexp) { + log_err("ERROR: ureldatefmt_combineDateAndTime() preflight for locale %s, width %d, capContext %d;\n expected len %d, get len %d\n", + itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, ulenexp, ulenget ); + } + } ureldatefmt_close(reldatefmt); }