• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 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 
addRelativeDateFormatTest(TestNode ** root)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.0, 0.7, 1.0, 2.0, 5.0 };
34 enum { kNumOffsets = UPRV_LENGTHOF(offsets) };
35 
36 static const char* en_decDef_long_midSent_sec[kNumOffsets*2] = {
37 /*  text                    numeric */
38     "5 seconds ago",        "5 seconds ago",      /* -5   */
39     "2.2 seconds ago",      "2.2 seconds ago",    /* -2.2 */
40     "2 seconds ago",        "2 seconds ago",      /* -2   */
41     "1 second ago",         "1 second ago",       /* -1   */
42     "0.7 seconds ago",      "0.7 seconds ago",    /* -0.7 */
43     "now",                  "0 seconds ago",      /*  -0  */
44     "now",                  "in 0 seconds",       /*  0   */
45     "in 0.7 seconds",       "in 0.7 seconds",     /*  0.7 */
46     "in 1 second",          "in 1 second",        /*  1   */
47     "in 2 seconds",         "in 2 seconds",       /*  2   */
48     "in 5 seconds",         "in 5 seconds"        /*  5   */
49 };
50 
51 static const char* en_decDef_long_midSent_week[kNumOffsets*2] = {
52 /*  text                    numeric */
53     "5 weeks ago",          "5 weeks ago",        /* -5   */
54     "2.2 weeks ago",        "2.2 weeks ago",      /* -2.2 */
55     "2 weeks ago",          "2 weeks ago",        /* -2   */
56     "last week",            "1 week ago",         /* -1   */
57     "0.7 weeks ago",        "0.7 weeks ago",      /* -0.7 */
58     "this week",            "0 weeks ago",        /*  -0  */
59     "this week",            "in 0 weeks",         /*  0   */
60     "in 0.7 weeks",         "in 0.7 weeks",       /*  0.7 */
61     "next week",            "in 1 week",          /*  1   */
62     "in 2 weeks",           "in 2 weeks",         /*  2   */
63     "in 5 weeks",           "in 5 weeks"          /*  5   */
64 };
65 
66 static const char* en_dec0_long_midSent_week[kNumOffsets*2] = {
67 /*  text                    numeric */
68     "5 weeks ago",          "5 weeks ago",        /* -5   */
69     "2 weeks ago",          "2 weeks ago",        /* -2.2 */
70     "2 weeks ago",          "2 weeks ago",        /* -2  */
71     "last week",            "1 week ago",         /* -1   */
72     "0 weeks ago",          "0 weeks ago",        /* -0.7 */
73     "this week",            "0 weeks ago",        /* -0  */
74     "this week",            "in 0 weeks",         /*  0   */
75     "in 0 weeks",           "in 0 weeks",         /*  0.7 */
76     "next week",            "in 1 week",          /*  1   */
77     "in 2 weeks",           "in 2 weeks",         /*  2   */
78     "in 5 weeks",           "in 5 weeks"          /*  5   */
79 };
80 
81 static const char* en_decDef_short_midSent_week[kNumOffsets*2] = {
82 /*  text                    numeric */
83     "5 wk. ago",            "5 wk. ago",          /* -5   */
84     "2.2 wk. ago",          "2.2 wk. ago",        /* -2.2 */
85     "2 wk. ago",            "2 wk. ago",          /* -2   */
86     "last wk.",             "1 wk. ago",          /* -1   */
87     "0.7 wk. ago",          "0.7 wk. ago",        /* -0.7 */
88     "this wk.",             "0 wk. ago",          /* -0   */
89     "this wk.",             "in 0 wk.",           /*  0   */
90     "in 0.7 wk.",           "in 0.7 wk.",         /*  0.7 */
91     "next wk.",             "in 1 wk.",           /*  1   */
92     "in 2 wk.",             "in 2 wk.",           /*  2   */
93     "in 5 wk.",             "in 5 wk."            /*  5   */
94 };
95 
96 static const char* en_decDef_long_midSent_min[kNumOffsets*2] = {
97 /*  text                    numeric */
98     "5 minutes ago",        "5 minutes ago",      /* -5   */
99     "2.2 minutes ago",      "2.2 minutes ago",    /* -2.2 */
100     "2 minutes ago",        "2 minutes ago",      /* -2   */
101     "1 minute ago",         "1 minute ago",       /* -1   */
102     "0.7 minutes ago",      "0.7 minutes ago",    /* -0.7 */
103     "0 minutes ago",        "0 minutes ago",      /* -0   */
104     "in 0 minutes",         "in 0 minutes",       /*  0   */
105     "in 0.7 minutes",       "in 0.7 minutes",     /*  0.7 */
106     "in 1 minute",          "in 1 minute",        /*  1   */
107     "in 2 minutes",         "in 2 minutes",       /*  2   */
108     "in 5 minutes",         "in 5 minutes"        /*  5   */
109 };
110 
111 static const char* en_dec0_long_midSent_tues[kNumOffsets*2] = {
112 /*  text                    numeric */
113     "5 Tuesdays ago",       "5 Tuesdays ago",     /* -5   */
114     ""/*no data */,         ""/*no data */,       /* -2.2 */
115     "2 Tuesdays ago",       "2 Tuesdays ago",     /* -2   */
116     "last Tuesday",         "1 Tuesday ago",      /* -1   */
117     ""/*no data */,         ""/*no data */,       /* -0.7 */
118     "this Tuesday",         "0 Tuesdays ago",     /* -0   */
119     "this Tuesday",         "in 0 Tuesdays",      /*  0   */
120     ""/*no data */,         ""/*no data */,       /*  0.7 */
121     "next Tuesday",         "in 1 Tuesday",       /*  1   */
122     "in 2 Tuesdays",        "in 2 Tuesdays",      /*  2   */
123     "in 5 Tuesdays",        "in 5 Tuesdays",      /*  5   */
124 };
125 
126 static const char* fr_decDef_long_midSent_day[kNumOffsets*2] = {
127 /*  text                    numeric */
128     "il y a 5 jours",       "il y a 5 jours",     /* -5   */
129     "il y a 2,2 jours",     "il y a 2,2 jours",   /* -2.2 */
130     "avant-hier",           "il y a 2 jours",     /* -2   */
131     "hier",                 "il y a 1 jour",      /* -1   */
132     "il y a 0,7 jour",      "il y a 0,7 jour",    /* -0.7 */
133     "aujourd\\u2019hui",    "il y a 0 jour",      /* -0   */
134     "aujourd\\u2019hui",    "dans 0 jour",        /*  0   */
135     "dans 0,7 jour",        "dans 0,7 jour",      /*  0.7 */
136     "demain",               "dans 1 jour",        /*  1   */
137     "apr\\u00E8s-demain",   "dans 2 jours",       /*  2   */
138     "dans 5 jours",         "dans 5 jours"        /*  5   */
139 };
140 
141 
142 typedef struct {
143     const char*                         locale;
144     int32_t                             decPlaces; /* fixed decimal places; -1 to use default num formatter */
145     UDateRelativeDateTimeFormatterStyle width;
146     UDisplayContext                     capContext;
147     URelativeDateTimeUnit               unit;
148     const char **                       expectedResults; /* for the various offsets */
149 } RelDateTimeFormatTestItem;
150 
151 static const RelDateTimeFormatTestItem fmtTestItems[] = {
152     { "en", -1, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_SECOND,  en_decDef_long_midSent_sec  },
153     { "en", -1, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK,    en_decDef_long_midSent_week  },
154     { "en",  0, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK,    en_dec0_long_midSent_week    },
155     { "en", -1, UDAT_STYLE_SHORT, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK,    en_decDef_short_midSent_week },
156     { "en", -1, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_MINUTE,  en_decDef_long_midSent_min   },
157     { "en", -1, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_TUESDAY, en_dec0_long_midSent_tues    },
158     { "fr", -1, UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_DAY,     fr_decDef_long_midSent_day   },
159     { NULL,  0, (UDateRelativeDateTimeFormatterStyle)0, (UDisplayContext)0, (URelativeDateTimeUnit)0, NULL } /* terminator */
160 };
161 
162 enum { kUBufMax = 64, kBBufMax = 256 };
163 
TestRelDateFmt()164 static void TestRelDateFmt()
165 {
166     const RelDateTimeFormatTestItem *itemPtr;
167     log_verbose("\nTesting ureldatefmt_open(), ureldatefmt_format(), ureldatefmt_formatNumeric() with various parameters\n");
168     for (itemPtr = fmtTestItems; itemPtr->locale != NULL; itemPtr++) {
169         URelativeDateTimeFormatter *reldatefmt = NULL;
170         UNumberFormat* nfToAdopt = NULL;
171         UErrorCode status = U_ZERO_ERROR;
172         int32_t iOffset;
173 
174         if (itemPtr->decPlaces >= 0) {
175             nfToAdopt = unum_open(UNUM_DECIMAL, NULL, 0, itemPtr->locale, NULL, &status);
176             if ( U_FAILURE(status) ) {
177                 log_data_err("FAIL: unum_open(UNUM_DECIMAL, ...) for locale %s: %s\n", itemPtr->locale, myErrorName(status));
178                 continue;
179             }
180 		    unum_setAttribute(nfToAdopt, UNUM_MIN_FRACTION_DIGITS, itemPtr->decPlaces);
181 		    unum_setAttribute(nfToAdopt, UNUM_MAX_FRACTION_DIGITS, itemPtr->decPlaces);
182 		    unum_setAttribute(nfToAdopt, UNUM_ROUNDING_MODE, UNUM_ROUND_DOWN);
183         }
184         reldatefmt = ureldatefmt_open(itemPtr->locale, nfToAdopt, itemPtr->width, itemPtr->capContext, &status);
185         if ( U_FAILURE(status) ) {
186             log_data_err("FAIL: ureldatefmt_open() for locale %s, decPlaces %d, width %d, capContext %d: %s\n",
187                     itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
188                     myErrorName(status) );
189             continue;
190         }
191 
192         for (iOffset = 0; iOffset < kNumOffsets; iOffset++) {
193             UChar ubufget[kUBufMax];
194             int32_t ulenget;
195 
196             if (itemPtr->unit >= UDAT_REL_UNIT_SUNDAY && offsets[iOffset] != -1.0 && offsets[iOffset] != 0.0 && offsets[iOffset] != 1.0) {
197                 continue; /* we do not currently have data for this */
198             }
199 
200             status = U_ZERO_ERROR;
201             ulenget = ureldatefmt_format(reldatefmt, offsets[iOffset], itemPtr->unit, ubufget, kUBufMax, &status);
202             if ( U_FAILURE(status) ) {
203                 log_err("FAIL: ureldatefmt_format() 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], 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_format() 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], bbufget );
215                 }
216             }
217 
218             if (itemPtr->unit >= UDAT_REL_UNIT_SUNDAY) {
219                 continue; /* we do not currently have numeric-style data for this */
220             }
221 
222             status = U_ZERO_ERROR;
223             ulenget = ureldatefmt_formatNumeric(reldatefmt, offsets[iOffset], itemPtr->unit, ubufget, kUBufMax, &status);
224             if ( U_FAILURE(status) ) {
225                 log_err("FAIL: ureldatefmt_formatNumeric() for locale %s, decPlaces %d, width %d, capContext %d, offset %.2f, unit %d: %s\n",
226                     itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
227                     offsets[iOffset], (int)itemPtr->unit, myErrorName(status) );
228             } else {
229                 UChar ubufexp[kUBufMax];
230                 int32_t ulenexp = u_unescape(itemPtr->expectedResults[iOffset*2 + 1], ubufexp, kUBufMax);
231                 if (ulenget != ulenexp || u_strncmp(ubufget, ubufexp, ulenexp) != 0) {
232                     char  bbufget[kBBufMax];
233                     u_austrncpy(bbufget, ubufget, kUBufMax);
234                     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",
235                         itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
236                         offsets[iOffset], (int)itemPtr->unit, itemPtr->expectedResults[iOffset*2 + 1], bbufget );
237                 }
238             }
239         }
240 
241         ureldatefmt_close(reldatefmt);
242     }
243 }
244 
245 typedef struct {
246     const char*                         locale;
247     UDateRelativeDateTimeFormatterStyle width;
248     UDisplayContext                     capContext;
249     const char *                        relativeDateString;
250     const char *                        timeString;
251     const char *                        expectedResult;
252 } CombineDateTimeTestItem;
253 
254 static const CombineDateTimeTestItem combTestItems[] = {
255     { "en",  UDAT_STYLE_LONG,  UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, "yesterday",  "3:45 PM",  "yesterday, 3:45 PM" },
256     { NULL,  (UDateRelativeDateTimeFormatterStyle)0, (UDisplayContext)0, NULL, NULL, NULL } /* terminator */
257 };
258 
TestCombineDateTime()259 static void TestCombineDateTime()
260 {
261     const CombineDateTimeTestItem *itemPtr;
262     log_verbose("\nTesting ureldatefmt_combineDateAndTime() with various parameters\n");
263     for (itemPtr = combTestItems; itemPtr->locale != NULL; itemPtr++) {
264         URelativeDateTimeFormatter *reldatefmt = NULL;
265         UErrorCode status = U_ZERO_ERROR;
266         UChar ubufreldate[kUBufMax];
267         UChar ubuftime[kUBufMax];
268         UChar ubufget[kUBufMax];
269         int32_t ulenreldate, ulentime, ulenget;
270 
271         reldatefmt = ureldatefmt_open(itemPtr->locale, NULL, itemPtr->width, itemPtr->capContext, &status);
272         if ( U_FAILURE(status) ) {
273             log_data_err("FAIL: ureldatefmt_open() for locale %s, width %d, capContext %d: %s\n",
274                     itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, myErrorName(status) );
275             continue;
276         }
277 
278         ulenreldate = u_unescape(itemPtr->relativeDateString, ubufreldate, kUBufMax);
279         ulentime    = u_unescape(itemPtr->timeString,         ubuftime,    kUBufMax);
280         ulenget     = ureldatefmt_combineDateAndTime(reldatefmt, ubufreldate, ulenreldate, ubuftime, ulentime, ubufget, kUBufMax, &status);
281         if ( U_FAILURE(status) ) {
282             log_err("FAIL: ureldatefmt_combineDateAndTime() for locale %s, width %d, capContext %d: %s\n",
283                 itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, myErrorName(status) );
284         } else {
285             UChar ubufexp[kUBufMax];
286             int32_t ulenexp = u_unescape(itemPtr->expectedResult, ubufexp, kUBufMax);
287             if (ulenget != ulenexp || u_strncmp(ubufget, ubufexp, ulenexp) != 0) {
288                 char  bbufget[kBBufMax];
289                 u_austrncpy(bbufget, ubufget, kUBufMax);
290                 log_err("ERROR: ureldatefmt_combineDateAndTime() for locale %s, width %d, capContext %d;\n      expected %s\n      get      %s\n",
291                     itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, itemPtr->expectedResult, bbufget );
292             }
293         }
294         // preflight test
295         status = U_ZERO_ERROR;
296         ulenget = ureldatefmt_combineDateAndTime(reldatefmt, ubufreldate, ulenreldate, ubuftime, ulentime, NULL, 0, &status);
297         if ( status != U_BUFFER_OVERFLOW_ERROR) {
298             log_err("FAIL: ureldatefmt_combineDateAndTime() preflight for locale %s, width %d, capContext %d: expected U_BUFFER_OVERFLOW_ERROR, got %s\n",
299                 itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, myErrorName(status) );
300         } else {
301             UChar ubufexp[kUBufMax];
302             int32_t ulenexp = u_unescape(itemPtr->expectedResult, ubufexp, kUBufMax);
303             if (ulenget != ulenexp) {
304                 log_err("ERROR: ureldatefmt_combineDateAndTime() preflight for locale %s, width %d, capContext %d;\n      expected len %d, get len %d\n",
305                     itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, ulenexp, ulenget );
306             }
307         }
308 
309         ureldatefmt_close(reldatefmt);
310     }
311 }
312 
313 #endif /* #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION */
314