From 5b3c14c29d2a04a64fcd3d52a6572efd2575b5d0 Mon Sep 17 00:00:00 2001 From: Peter Edberg Date: Thu, 24 May 2018 05:52:01 +0000 Subject: [PATCH] ICU-12936 Make RelativeDateTimeFormatter handle offset of -0 X-SVN-Rev: 41451 --- icu4c/source/i18n/reldatefmt.cpp | 3 +- .../test/cintltst/crelativedateformattest.c | 38 ++++++++++++++---- .../icu/text/RelativeDateTimeFormatter.java | 2 +- .../format/RelativeDateTimeFormatterTest.java | 39 +++++++++++++++---- 4 files changed, 64 insertions(+), 18 deletions(-) diff --git a/icu4c/source/i18n/reldatefmt.cpp b/icu4c/source/i18n/reldatefmt.cpp index 45ac5436aa..aad026cb62 100644 --- a/icu4c/source/i18n/reldatefmt.cpp +++ b/icu4c/source/i18n/reldatefmt.cpp @@ -14,6 +14,7 @@ #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION +#include #include "unicode/dtfmtsym.h" #include "unicode/ucasemap.h" #include "unicode/ureldatefmt.h" @@ -849,7 +850,7 @@ UnicodeString& RelativeDateTimeFormatter::formatNumeric( return appendTo; } UDateDirection direction = UDAT_DIRECTION_NEXT; - if (offset < 0) { + if (std::signbit(offset)) { // needed to handle -0.0 direction = UDAT_DIRECTION_LAST; offset = -offset; } diff --git a/icu4c/source/test/cintltst/crelativedateformattest.c b/icu4c/source/test/cintltst/crelativedateformattest.c index b88d3d85c3..42a3414421 100644 --- a/icu4c/source/test/cintltst/crelativedateformattest.c +++ b/icu4c/source/test/cintltst/crelativedateformattest.c @@ -30,9 +30,24 @@ void addRelativeDateFormatTest(TestNode** root) TESTCASE(TestCombineDateTime); } -static const double offsets[] = { -5.0, -2.2, -2.0, -1.0, -0.7, 0.0, 0.7, 1.0, 2.0, 5.0 }; +static const double offsets[] = { -5.0, -2.2, -2.0, -1.0, -0.7, -0.0, 0.0, 0.7, 1.0, 2.0, 5.0 }; enum { kNumOffsets = UPRV_LENGTHOF(offsets) }; +static const char* en_decDef_long_midSent_sec[kNumOffsets*2] = { +/* text numeric */ + "5 seconds ago", "5 seconds ago", /* -5 */ + "2.2 seconds ago", "2.2 seconds ago", /* -2.2 */ + "2 seconds ago", "2 seconds ago", /* -2 */ + "1 second ago", "1 second ago", /* -1 */ + "0.7 seconds ago", "0.7 seconds ago", /* -0.7 */ + "now", "0 seconds ago", /* -0 */ + "now", "in 0 seconds", /* 0 */ + "in 0.7 seconds", "in 0.7 seconds", /* 0.7 */ + "in 1 second", "in 1 second", /* 1 */ + "in 2 seconds", "in 2 seconds", /* 2 */ + "in 5 seconds", "in 5 seconds" /* 5 */ +}; + static const char* en_decDef_long_midSent_week[kNumOffsets*2] = { /* text numeric */ "5 weeks ago", "5 weeks ago", /* -5 */ @@ -40,6 +55,7 @@ static const char* en_decDef_long_midSent_week[kNumOffsets*2] = { "2 weeks ago", "2 weeks ago", /* -2 */ "last week", "1 week ago", /* -1 */ "0.7 weeks ago", "0.7 weeks ago", /* -0.7 */ + "this week", "0 weeks ago", /* -0 */ "this week", "in 0 weeks", /* 0 */ "in 0.7 weeks", "in 0.7 weeks", /* 0.7 */ "next week", "in 1 week", /* 1 */ @@ -54,6 +70,7 @@ static const char* en_dec0_long_midSent_week[kNumOffsets*2] = { "2 weeks ago", "2 weeks ago", /* -2 */ "last week", "1 week ago", /* -1 */ "0 weeks ago", "0 weeks ago", /* -0.7 */ + "this week", "0 weeks ago", /* -0 */ "this week", "in 0 weeks", /* 0 */ "in 0 weeks", "in 0 weeks", /* 0.7 */ "next week", "in 1 week", /* 1 */ @@ -68,6 +85,7 @@ static const char* en_decDef_short_midSent_week[kNumOffsets*2] = { "2 wk. ago", "2 wk. ago", /* -2 */ "last wk.", "1 wk. ago", /* -1 */ "0.7 wk. ago", "0.7 wk. ago", /* -0.7 */ + "this wk.", "0 wk. ago", /* -0 */ "this wk.", "in 0 wk.", /* 0 */ "in 0.7 wk.", "in 0.7 wk.", /* 0.7 */ "next wk.", "in 1 wk.", /* 1 */ @@ -82,6 +100,7 @@ static const char* en_decDef_long_midSent_min[kNumOffsets*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 */ + "0 minutes ago", "0 minutes ago", /* -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 */ @@ -91,16 +110,17 @@ static const char* en_decDef_long_midSent_min[kNumOffsets*2] = { static const char* en_dec0_long_midSent_tues[kNumOffsets*2] = { /* text numeric */ - ""/*no data */, ""/*no data */, /* -5 */ + "5 Tuesdays ago", "5 Tuesdays ago", /* -5 */ ""/*no data */, ""/*no data */, /* -2.2 */ - ""/*no data */, ""/*no data */, /* -2 */ - "last Tuesday", ""/*no data */, /* -1 */ + "2 Tuesdays ago", "2 Tuesdays ago", /* -2 */ + "last Tuesday", "1 Tuesday ago", /* -1 */ ""/*no data */, ""/*no data */, /* -0.7 */ - "this Tuesday", ""/*no data */, /* 0 */ + "this Tuesday", "0 Tuesdays ago", /* -0 */ + "this Tuesday", "in 0 Tuesdays", /* 0 */ ""/*no data */, ""/*no data */, /* 0.7 */ - "next Tuesday", ""/*no data */, /* 1 */ - ""/*no data */, ""/*no data */, /* 2 */ - ""/*no data */, ""/*no data */, /* 5 */ + "next Tuesday", "in 1 Tuesday", /* 1 */ + "in 2 Tuesdays", "in 2 Tuesdays", /* 2 */ + "in 5 Tuesdays", "in 5 Tuesdays", /* 5 */ }; static const char* fr_decDef_long_midSent_day[kNumOffsets*2] = { @@ -110,6 +130,7 @@ static const char* fr_decDef_long_midSent_day[kNumOffsets*2] = { "avant-hier", "il y a 2 jours", /* -2 */ "hier", "il y a 1 jour", /* -1 */ "il y a 0,7 jour", "il y a 0,7 jour", /* -0.7 */ + "aujourd\\u2019hui", "il y a 0 jour", /* -0 */ "aujourd\\u2019hui", "dans 0 jour", /* 0 */ "dans 0,7 jour", "dans 0,7 jour", /* 0.7 */ "demain", "dans 1 jour", /* 1 */ @@ -128,6 +149,7 @@ typedef struct { } RelDateTimeFormatTestItem; static const RelDateTimeFormatTestItem fmtTestItems[] = { + { "en", -1, UDAT_STYLE_LONG, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_SECOND, en_decDef_long_midSent_sec }, { "en", -1, UDAT_STYLE_LONG, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK, en_decDef_long_midSent_week }, { "en", 0, UDAT_STYLE_LONG, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK, en_dec0_long_midSent_week }, { "en", -1, UDAT_STYLE_SHORT, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK, en_decDef_short_midSent_week }, diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/RelativeDateTimeFormatter.java b/icu4j/main/classes/core/src/com/ibm/icu/text/RelativeDateTimeFormatter.java index bd808b46e3..df61c84981 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/RelativeDateTimeFormatter.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/RelativeDateTimeFormatter.java @@ -552,7 +552,7 @@ public final class RelativeDateTimeFormatter { throw new UnsupportedOperationException("formatNumeric does not currently support RelativeUnit.SUNDAY..SATURDAY"); } Direction direction = Direction.NEXT; - if (offset < 0) { + if (Double.compare(offset,0.0) < 0) { // needed to handle -0.0 direction = Direction.LAST; offset = -offset; } diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/RelativeDateTimeFormatterTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/RelativeDateTimeFormatterTest.java index b9c67e43c7..7abe32a615 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/RelativeDateTimeFormatterTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/RelativeDateTimeFormatterTest.java @@ -642,7 +642,22 @@ public class RelativeDateTimeFormatterTest extends TestFmwk { @Test public void TestRelativeDateTimeUnitFormatters() { - double[] offsets = { -5.0, -2.2, -2.0, -1.0, -0.7, 0.0, 0.7, 1.0, 2.0, 5.0 }; + double[] offsets = { -5.0, -2.2, -2.0, -1.0, -0.7, -0.0, 0.0, 0.7, 1.0, 2.0, 5.0 }; + + String[] en_decDef_long_midSent_sec = { + /* text numeric */ + "5 seconds ago", "5 seconds ago", /* -5 */ + "2.2 seconds ago", "2.2 seconds ago", /* -2.2 */ + "2 seconds ago", "2 seconds ago", /* -2 */ + "1 second ago", "1 second ago", /* -1 */ + "0.7 seconds ago", "0.7 seconds ago", /* -0.7 */ + "now", "0 seconds ago", /* -0 */ + "now", "in 0 seconds", /* 0 */ + "in 0.7 seconds", "in 0.7 seconds", /* 0.7 */ + "in 1 second", "in 1 second", /* 1 */ + "in 2 seconds", "in 2 seconds", /* 2 */ + "in 5 seconds", "in 5 seconds" /* 5 */ + }; String[] en_decDef_long_midSent_week = { /* text numeric */ @@ -651,6 +666,7 @@ public class RelativeDateTimeFormatterTest extends TestFmwk { "2 weeks ago", "2 weeks ago", /* -2 */ "last week", "1 week ago", /* -1 */ "0.7 weeks ago", "0.7 weeks ago", /* -0.7 */ + "this week", "0 weeks ago", /* -0 */ "this week", "in 0 weeks", /* 0 */ "in 0.7 weeks", "in 0.7 weeks", /* 0.7 */ "next week", "in 1 week", /* 1 */ @@ -665,6 +681,7 @@ public class RelativeDateTimeFormatterTest extends TestFmwk { "2 weeks ago", "2 weeks ago", /* -2 */ "last week", "1 week ago", /* -1 */ "0 weeks ago", "0 weeks ago", /* -0.7 */ + "this week", "0 weeks ago", /* -0 */ "this week", "in 0 weeks", /* 0 */ "in 0 weeks", "in 0 weeks", /* 0.7 */ "next week", "in 1 week", /* 1 */ @@ -679,6 +696,7 @@ public class RelativeDateTimeFormatterTest extends TestFmwk { "2 wk. ago", "2 wk. ago", /* -2 */ "last wk.", "1 wk. ago", /* -1 */ "0.7 wk. ago", "0.7 wk. ago", /* -0.7 */ + "this wk.", "0 wk. ago", /* -0 */ "this wk.", "in 0 wk.", /* 0 */ "in 0.7 wk.", "in 0.7 wk.", /* 0.7 */ "next wk.", "in 1 wk.", /* 1 */ @@ -693,6 +711,7 @@ public class RelativeDateTimeFormatterTest extends TestFmwk { "2 minutes ago", "2 minutes ago", /* -2 */ "1 minute ago", "1 minute ago", /* -1 */ "0.7 minutes ago", "0.7 minutes ago", /* -0.7 */ + "0 minutes ago", "0 minutes ago", /* -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 */ @@ -702,16 +721,17 @@ public class RelativeDateTimeFormatterTest extends TestFmwk { String[] en_dec0_long_midSent_tues = { /* text numeric */ - ""/*no data */, ""/*no data */, /* -5 */ + "5 Tuesdays ago", "5 Tuesdays ago", /* -5 */ ""/*no data */, ""/*no data */, /* -2.2 */ - ""/*no data */, ""/*no data */, /* -2 */ - "last Tuesday", ""/*no data */, /* -1 */ + "2 Tuesdays ago", "2 Tuesdays ago", /* -2 */ + "last Tuesday", "1 Tuesday ago", /* -1 */ ""/*no data */, ""/*no data */, /* -0.7 */ - "this Tuesday", ""/*no data */, /* 0 */ + "this Tuesday", "0 Tuesdays ago", /* -0 */ + "this Tuesday", "in 0 Tuesdays", /* 0 */ ""/*no data */, ""/*no data */, /* 0.7 */ - "next Tuesday", ""/*no data */, /* 1 */ - ""/*no data */, ""/*no data */, /* 2 */ - ""/*no data */, ""/*no data */, /* 5 */ + "next Tuesday", "in 1 Tuesday", /* 1 */ + "in 2 Tuesdays", "in 2 Tuesdays", /* 2 */ + "in 5 Tuesdays", "in 5 Tuesdays", /* 5 */ }; String[] fr_decDef_long_midSent_day = { @@ -721,6 +741,7 @@ public class RelativeDateTimeFormatterTest extends TestFmwk { "avant-hier", "il y a 2 jours", /* -2 */ "hier", "il y a 1 jour", /* -1 */ "il y a 0,7 jour", "il y a 0,7 jour", /* -0.7 */ + "aujourd’hui", "il y a 0 jour", /* -0 */ "aujourd’hui", "dans 0 jour", /* 0 */ "dans 0,7 jour", "dans 0,7 jour", /* 0.7 */ "demain", "dans 1 jour", /* 1 */ @@ -746,6 +767,8 @@ public class RelativeDateTimeFormatterTest extends TestFmwk { } }; final TestRelativeDateTimeUnitItem[] items = { + new TestRelativeDateTimeUnitItem("en", -1, Style.LONG, DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, + RelativeDateTimeUnit.SECOND, en_decDef_long_midSent_sec), new TestRelativeDateTimeUnitItem("en", -1, Style.LONG, DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, RelativeDateTimeUnit.WEEK, en_decDef_long_midSent_week), new TestRelativeDateTimeUnitItem("en", 0, Style.LONG, DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,