Imported Upstream version 58.1
[platform/upstream/icu.git] / source / test / cintltst / crelativedateformattest.c
1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4  * Copyright (c) 2016, International Business Machines Corporation
5  * and others. All Rights Reserved.
6  ********************************************************************/
7 /* C API TEST FOR DATE INTERVAL FORMAT */
8
9 #include "unicode/utypes.h"
10
11 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION
12
13 #include "unicode/ureldatefmt.h"
14 #include "unicode/unum.h"
15 #include "unicode/udisplaycontext.h"
16 #include "unicode/ustring.h"
17 #include "cintltst.h"
18 #include "cmemory.h"
19
20 static void TestRelDateFmt(void);
21 static void TestCombineDateTime(void);
22
23 void addRelativeDateFormatTest(TestNode** root);
24
25 #define TESTCASE(x) addTest(root, &x, "tsformat/crelativedateformattest/" #x)
26
27 void addRelativeDateFormatTest(TestNode** root)
28 {
29     TESTCASE(TestRelDateFmt);
30     TESTCASE(TestCombineDateTime);
31 }
32
33 static const double offsets[] = { -5.0, -2.2, -2.0, -1.0, -0.7, 0.0, 0.7, 1.0, 2.0, 5.0 };
34 enum { kNumOffsets = UPRV_LENGTHOF(offsets) };
35
36 static const char* en_decDef_long_midSent_week[kNumOffsets*2] = {
37 /*  text                    numeric */
38     "5 weeks ago",          "5 weeks ago",        /* -5   */
39     "2.2 weeks ago",        "2.2 weeks ago",      /* -2.2 */
40     "2 weeks ago",          "2 weeks ago",        /* -2   */
41     "last week",            "1 week ago",         /* -1   */
42     "0.7 weeks ago",        "0.7 weeks ago",      /* -0.7 */
43     "this week",            "in 0 weeks",         /*  0   */
44     "in 0.7 weeks",         "in 0.7 weeks",       /*  0.7 */
45     "next week",            "in 1 week",          /*  1   */
46     "in 2 weeks",           "in 2 weeks",         /*  2   */
47     "in 5 weeks",           "in 5 weeks"          /*  5   */
48 };
49
50 static const char* en_dec0_long_midSent_week[kNumOffsets*2] = {
51 /*  text                    numeric */
52     "5 weeks ago",          "5 weeks ago",        /* -5   */
53     "2 weeks ago",          "2 weeks ago",        /* -2.2 */
54     "2 weeks ago",          "2 weeks ago",        /* -2  */
55     "last week",            "1 week ago",         /* -1   */
56     "0 weeks ago",          "0 weeks ago",        /* -0.7 */
57     "this week",            "in 0 weeks",         /*  0   */
58     "in 0 weeks",           "in 0 weeks",         /*  0.7 */
59     "next week",            "in 1 week",          /*  1   */
60     "in 2 weeks",           "in 2 weeks",         /*  2   */
61     "in 5 weeks",           "in 5 weeks"          /*  5   */
62 };
63
64 static const char* en_decDef_short_midSent_week[kNumOffsets*2] = {
65 /*  text                    numeric */
66     "5 wk. ago",            "5 wk. ago",          /* -5   */
67     "2.2 wk. ago",          "2.2 wk. ago",        /* -2.2 */
68     "2 wk. ago",            "2 wk. ago",          /* -2   */
69     "last wk.",             "1 wk. ago",          /* -1   */
70     "0.7 wk. ago",          "0.7 wk. ago",        /* -0.7 */
71     "this wk.",             "in 0 wk.",           /*  0   */
72     "in 0.7 wk.",           "in 0.7 wk.",         /*  0.7 */
73     "next wk.",             "in 1 wk.",           /*  1   */
74     "in 2 wk.",             "in 2 wk.",           /*  2   */
75     "in 5 wk.",             "in 5 wk."            /*  5   */
76 };
77
78 static const char* en_decDef_long_midSent_min[kNumOffsets*2] = {
79 /*  text                    numeric */
80     "5 minutes ago",        "5 minutes ago",      /* -5   */
81     "2.2 minutes ago",      "2.2 minutes ago",    /* -2.2 */
82     "2 minutes ago",        "2 minutes ago",      /* -2   */
83     "1 minute ago",         "1 minute ago",       /* -1   */
84     "0.7 minutes ago",      "0.7 minutes ago",    /* -0.7 */
85     "in 0 minutes",         "in 0 minutes",       /*  0   */
86     "in 0.7 minutes",       "in 0.7 minutes",     /*  0.7 */
87     "in 1 minute",          "in 1 minute",        /*  1   */
88     "in 2 minutes",         "in 2 minutes",       /*  2   */
89     "in 5 minutes",         "in 5 minutes"        /*  5   */
90 };
91
92 static const char* en_dec0_long_midSent_tues[kNumOffsets*2] = {
93 /*  text                    numeric */
94     ""/*no data */,         ""/*no data */,       /* -5   */
95     ""/*no data */,         ""/*no data */,       /* -2.2 */
96     ""/*no data */,         ""/*no data */,       /* -2   */
97     "last Tuesday",         ""/*no data */,       /* -1   */
98     ""/*no data */,         ""/*no data */,       /* -0.7 */
99     "this Tuesday",         ""/*no data */,       /*  0   */
100     ""/*no data */,         ""/*no data */,       /*  0.7 */
101     "next Tuesday",         ""/*no data */,       /*  1   */
102     ""/*no data */,         ""/*no data */,       /*  2   */
103     ""/*no data */,         ""/*no data */,       /*  5   */
104 };
105
106 static const char* fr_decDef_long_midSent_day[kNumOffsets*2] = {
107 /*  text                    numeric */
108     "il y a 5 jours",       "il y a 5 jours",     /* -5   */
109     "il y a 2,2 jours",     "il y a 2,2 jours",   /* -2.2 */
110     "avant-hier",           "il y a 2 jours",     /* -2   */
111     "hier",                 "il y a 1 jour",      /* -1   */
112     "il y a 0,7 jour",      "il y a 0,7 jour",    /* -0.7 */
113     "aujourd\\u2019hui",    "dans 0 jour",        /*  0   */
114     "dans 0,7 jour",        "dans 0,7 jour",      /*  0.7 */
115     "demain",               "dans 1 jour",        /*  1   */
116     "apr\\u00E8s-demain",   "dans 2 jours",       /*  2   */
117     "dans 5 jours",         "dans 5 jours"        /*  5   */
118 };
119
120
121 typedef struct {
122     const char*                         locale;
123     int32_t                             decPlaces; /* fixed decimal places; -1 to use default num formatter */
124     UDateRelativeDateTimeFormatterStyle width;
125     UDisplayContext                     capContext;
126     URelativeDateTimeUnit               unit;
127     const char **                       expectedResults; /* for the various offsets */
128 } RelDateTimeFormatTestItem;
129
130 static const RelDateTimeFormatTestItem fmtTestItems[] = {
131     { "en", -1, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK,    en_decDef_long_midSent_week  },
132     { "en",  0, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK,    en_dec0_long_midSent_week    },
133     { "en", -1, UDAT_STYLE_SHORT, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK,    en_decDef_short_midSent_week },
134     { "en", -1, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_MINUTE,  en_decDef_long_midSent_min   },
135     { "en", -1, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_TUESDAY, en_dec0_long_midSent_tues    },
136     { "fr", -1, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_DAY,     fr_decDef_long_midSent_day   },
137     { NULL,  0, (UDateRelativeDateTimeFormatterStyle)0, (UDisplayContext)0, (URelativeDateTimeUnit)0, NULL } /* terminator */
138 };
139
140 enum { kUBufMax = 64, kBBufMax = 256 };
141
142 static void TestRelDateFmt()
143 {
144     const RelDateTimeFormatTestItem *itemPtr;
145     log_verbose("\nTesting ureldatefmt_open(), ureldatefmt_format(), ureldatefmt_formatNumeric() with various parameters\n");
146     for (itemPtr = fmtTestItems; itemPtr->locale != NULL; itemPtr++) {
147         URelativeDateTimeFormatter *reldatefmt = NULL;
148         UNumberFormat* nfToAdopt = NULL;
149         UErrorCode status = U_ZERO_ERROR;
150         int32_t iOffset;
151
152         if (itemPtr->decPlaces >= 0) {
153             nfToAdopt = unum_open(UNUM_DECIMAL, NULL, 0, itemPtr->locale, NULL, &status);
154             if ( U_FAILURE(status) ) {
155                 log_data_err("FAIL: unum_open(UNUM_DECIMAL, ...) for locale %s: %s\n", itemPtr->locale, myErrorName(status));
156                 continue;
157             }
158                     unum_setAttribute(nfToAdopt, UNUM_MIN_FRACTION_DIGITS, itemPtr->decPlaces);
159                     unum_setAttribute(nfToAdopt, UNUM_MAX_FRACTION_DIGITS, itemPtr->decPlaces);
160                     unum_setAttribute(nfToAdopt, UNUM_ROUNDING_MODE, UNUM_ROUND_DOWN);
161         }
162         reldatefmt = ureldatefmt_open(itemPtr->locale, nfToAdopt, itemPtr->width, itemPtr->capContext, &status);
163         if ( U_FAILURE(status) ) {
164             log_data_err("FAIL: ureldatefmt_open() for locale %s, decPlaces %d, width %d, capContext %d: %s\n",
165                     itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
166                     myErrorName(status) );
167             continue;
168         }
169
170         for (iOffset = 0; iOffset < kNumOffsets; iOffset++) {
171             UChar ubufget[kUBufMax];
172             int32_t ulenget;
173
174             if (itemPtr->unit >= UDAT_REL_UNIT_SUNDAY && offsets[iOffset] != -1.0 && offsets[iOffset] != 0.0 && offsets[iOffset] != 1.0) {
175                 continue; /* we do not currently have data for this */
176             }
177
178             status = U_ZERO_ERROR;
179             ulenget = ureldatefmt_format(reldatefmt, offsets[iOffset], itemPtr->unit, ubufget, kUBufMax, &status);
180             if ( U_FAILURE(status) ) {
181                 log_err("FAIL: ureldatefmt_format() for locale %s, decPlaces %d, width %d, capContext %d, offset %.2f, unit %d: %s\n",
182                     itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
183                     offsets[iOffset], (int)itemPtr->unit, myErrorName(status) );
184             } else {
185                 UChar ubufexp[kUBufMax];
186                 int32_t ulenexp = u_unescape(itemPtr->expectedResults[iOffset*2], ubufexp, kUBufMax);
187                 if (ulenget != ulenexp || u_strncmp(ubufget, ubufexp, ulenexp) != 0) {
188                     char  bbufget[kBBufMax];
189                     u_austrncpy(bbufget, ubufget, kUBufMax);
190                     log_err("ERROR: ureldatefmt_format() for locale %s, decPlaces %d, width %d, capContext %d, offset %.2f, unit %d;\n      expected %s\n      get      %s\n",
191                         itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
192                         offsets[iOffset], (int)itemPtr->unit, itemPtr->expectedResults[iOffset*2], bbufget );
193                 }
194             }
195
196             if (itemPtr->unit >= UDAT_REL_UNIT_SUNDAY) {
197                 continue; /* we do not currently have numeric-style data for this */
198             }
199
200             status = U_ZERO_ERROR;
201             ulenget = ureldatefmt_formatNumeric(reldatefmt, offsets[iOffset], itemPtr->unit, ubufget, kUBufMax, &status);
202             if ( U_FAILURE(status) ) {
203                 log_err("FAIL: ureldatefmt_formatNumeric() for locale %s, decPlaces %d, width %d, capContext %d, offset %.2f, unit %d: %s\n",
204                     itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
205                     offsets[iOffset], (int)itemPtr->unit, myErrorName(status) );
206             } else {
207                 UChar ubufexp[kUBufMax];
208                 int32_t ulenexp = u_unescape(itemPtr->expectedResults[iOffset*2 + 1], ubufexp, kUBufMax);
209                 if (ulenget != ulenexp || u_strncmp(ubufget, ubufexp, ulenexp) != 0) {
210                     char  bbufget[kBBufMax];
211                     u_austrncpy(bbufget, ubufget, kUBufMax);
212                     log_err("ERROR: ureldatefmt_formatNumeric() for locale %s, decPlaces %d, width %d, capContext %d, offset %.2f, unit %d;\n      expected %s\n      get      %s\n",
213                         itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
214                         offsets[iOffset], (int)itemPtr->unit, itemPtr->expectedResults[iOffset*2 + 1], bbufget );
215                 }
216             }
217         }
218
219         ureldatefmt_close(reldatefmt);
220     }
221 }
222
223 typedef struct {
224     const char*                         locale;
225     UDateRelativeDateTimeFormatterStyle width;
226     UDisplayContext                     capContext;
227     const char *                        relativeDateString;
228     const char *                        timeString;
229     const char *                        expectedResult;
230 } CombineDateTimeTestItem;
231
232 static const CombineDateTimeTestItem combTestItems[] = {
233     { "en",  UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, "yesterday",  "3:45 PM",  "yesterday, 3:45 PM" },
234     { NULL,  (UDateRelativeDateTimeFormatterStyle)0, (UDisplayContext)0, NULL, NULL, NULL } /* terminator */
235 };
236
237 static void TestCombineDateTime()
238 {
239     const CombineDateTimeTestItem *itemPtr;
240     log_verbose("\nTesting ureldatefmt_combineDateAndTime() with various parameters\n");
241     for (itemPtr = combTestItems; itemPtr->locale != NULL; itemPtr++) {
242         URelativeDateTimeFormatter *reldatefmt = NULL;
243         UErrorCode status = U_ZERO_ERROR;
244         UChar ubufreldate[kUBufMax];
245         UChar ubuftime[kUBufMax];
246         UChar ubufget[kUBufMax];
247         int32_t ulenreldate, ulentime, ulenget;
248
249         reldatefmt = ureldatefmt_open(itemPtr->locale, NULL, itemPtr->width, itemPtr->capContext, &status);
250         if ( U_FAILURE(status) ) {
251             log_data_err("FAIL: ureldatefmt_open() for locale %s, width %d, capContext %d: %s\n",
252                     itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, myErrorName(status) );
253             continue;
254         }
255
256         ulenreldate = u_unescape(itemPtr->relativeDateString, ubufreldate, kUBufMax);
257         ulentime    = u_unescape(itemPtr->timeString,         ubuftime,    kUBufMax);
258         ulenget     = ureldatefmt_combineDateAndTime(reldatefmt, ubufreldate, ulenreldate, ubuftime, ulentime, ubufget, kUBufMax, &status);
259         if ( U_FAILURE(status) ) {
260             log_err("FAIL: ureldatefmt_combineDateAndTime() for locale %s, width %d, capContext %d: %s\n",
261                 itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, myErrorName(status) );
262         } else {
263             UChar ubufexp[kUBufMax];
264             int32_t ulenexp = u_unescape(itemPtr->expectedResult, ubufexp, kUBufMax);
265             if (ulenget != ulenexp || u_strncmp(ubufget, ubufexp, ulenexp) != 0) {
266                 char  bbufget[kBBufMax];
267                 u_austrncpy(bbufget, ubufget, kUBufMax);
268                 log_err("ERROR: ureldatefmt_combineDateAndTime() for locale %s, width %d, capContext %d;\n      expected %s\n      get      %s\n",
269                     itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, itemPtr->expectedResult, bbufget );
270             }
271         }
272         // preflight test
273         status = U_ZERO_ERROR;
274         ulenget = ureldatefmt_combineDateAndTime(reldatefmt, ubufreldate, ulenreldate, ubuftime, ulentime, NULL, 0, &status);
275         if ( status != U_BUFFER_OVERFLOW_ERROR) {
276             log_err("FAIL: ureldatefmt_combineDateAndTime() preflight for locale %s, width %d, capContext %d: expected U_BUFFER_OVERFLOW_ERROR, got %s\n",
277                 itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, myErrorName(status) );
278         } else {
279             UChar ubufexp[kUBufMax];
280             int32_t ulenexp = u_unescape(itemPtr->expectedResult, ubufexp, kUBufMax);
281             if (ulenget != ulenexp) {
282                 log_err("ERROR: ureldatefmt_combineDateAndTime() preflight for locale %s, width %d, capContext %d;\n      expected len %d, get len %d\n",
283                     itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, ulenexp, ulenget );
284             }
285         }
286
287         ureldatefmt_close(reldatefmt);
288     }
289 }
290
291 #endif /* #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION */