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 <stdbool.h>
14
15 #include "unicode/ureldatefmt.h"
16 #include "unicode/unum.h"
17 #include "unicode/udisplaycontext.h"
18 #include "unicode/ustring.h"
19 #include "cintltst.h"
20 #include "cmemory.h"
21 #include "cformtst.h"
22
23 static void TestRelDateFmt(void);
24 static void TestNumericField(void);
25 static void TestCombineDateTime(void);
26 static void TestFields(void);
27
28 void addRelativeDateFormatTest(TestNode** root);
29
30 #define TESTCASE(x) addTest(root, &x, "tsformat/crelativedateformattest/" #x)
31
addRelativeDateFormatTest(TestNode ** root)32 void addRelativeDateFormatTest(TestNode** root)
33 {
34 TESTCASE(TestRelDateFmt);
35 TESTCASE(TestNumericField);
36 TESTCASE(TestCombineDateTime);
37 TESTCASE(TestFields);
38 }
39
40 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 };
41 enum { kNumOffsets = UPRV_LENGTHOF(offsets) };
42
43 typedef struct {
44 int32_t field;
45 int32_t beginPos;
46 int32_t endPos;
47 } FieldsDat;
48
49 static const char* en_decDef_long_midSent_sec[kNumOffsets*2] = {
50 /* text numeric */
51 "5 seconds ago", "5 seconds ago", /* -5 */
52 "2.2 seconds ago", "2.2 seconds ago", /* -2.2 */
53 "2 seconds ago", "2 seconds ago", /* -2 */
54 "1 second ago", "1 second ago", /* -1 */
55 "0.7 seconds ago", "0.7 seconds ago", /* -0.7 */
56 "now", "0 seconds ago", /* -0 */
57 "now", "in 0 seconds", /* 0 */
58 "in 0.7 seconds", "in 0.7 seconds", /* 0.7 */
59 "in 1 second", "in 1 second", /* 1 */
60 "in 2 seconds", "in 2 seconds", /* 2 */
61 "in 5 seconds", "in 5 seconds" /* 5 */
62 };
63
64 static const FieldsDat en_attrDef_long_midSent_sec[kNumOffsets*2] = {
65 /* text numeric text numeric */
66 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "5 seconds ago", "5 seconds ago", -5 */
67 {UDAT_REL_NUMERIC_FIELD, 0, 3}, {UDAT_REL_NUMERIC_FIELD, 0, 3}, /* "2.2 seconds ago", "2.2 seconds ago", -2.2 */
68 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "2 seconds ago", "2 seconds ago", -2 */
69 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "1 second ago", "1 second ago", -1 */
70 {UDAT_REL_NUMERIC_FIELD, 0, 3}, {UDAT_REL_NUMERIC_FIELD, 0, 3}, /* "0.7 seconds ago", "0.7 seconds ago", -0.7 */
71 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "now", "0 seconds ago", -0 */
72 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "now", "in 0 seconds", 0 */
73 {UDAT_REL_NUMERIC_FIELD, 3, 6}, {UDAT_REL_NUMERIC_FIELD, 3, 6}, /* "in 0.7 seconds", "in 0.7 seconds", 0.7 */
74 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 1 second", "in 1 second", 1 */
75 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 2 seconds", "in 2 seconds", 2 */
76 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 5 seconds", "in 5 seconds" 5 */
77 };
78
79 static const char* en_decDef_long_midSent_week[kNumOffsets*2] = {
80 /* text numeric */
81 "5 weeks ago", "5 weeks ago", /* -5 */
82 "2.2 weeks ago", "2.2 weeks ago", /* -2.2 */
83 "2 weeks ago", "2 weeks ago", /* -2 */
84 "last week", "1 week ago", /* -1 */
85 "0.7 weeks ago", "0.7 weeks ago", /* -0.7 */
86 "this week", "0 weeks ago", /* -0 */
87 "this week", "in 0 weeks", /* 0 */
88 "in 0.7 weeks", "in 0.7 weeks", /* 0.7 */
89 "next week", "in 1 week", /* 1 */
90 "in 2 weeks", "in 2 weeks", /* 2 */
91 "in 5 weeks", "in 5 weeks" /* 5 */
92 };
93
94 static const FieldsDat en_attrDef_long_midSent_week[kNumOffsets*2] = {
95 /* text numeric text numeric */
96 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "5 weeks ago", "5 weeks ago", -5 */
97 {UDAT_REL_NUMERIC_FIELD, 0, 3}, {UDAT_REL_NUMERIC_FIELD, 0, 3}, /* "2.2 weeks ago", "2.2 weeks ago", -2.2 */
98 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "2 weeks ago", "2 weeks ago", -2 */
99 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "last week", "1 week ago", -1 */
100 {UDAT_REL_NUMERIC_FIELD, 0, 3}, {UDAT_REL_NUMERIC_FIELD, 0, 3}, /* "0.7 weeks ago", "0.7 weeks ago", -0.7 */
101 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "this week", "0 weeks ago", -0 */
102 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "this week", "in 0 weeks", 0 */
103 {UDAT_REL_NUMERIC_FIELD, 3, 6}, {UDAT_REL_NUMERIC_FIELD, 3, 6}, /* "in 0.7 weeks", "in 0.7 weeks", 0.7 */
104 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "next week", "in 1 week", 1 */
105 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 2 weeks", "in 2 weeks", 2 */
106 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 5 weeks", "in 5 weeks" 5 */
107 };
108
109 static const char* en_dec0_long_midSent_week[kNumOffsets*2] = {
110 /* text numeric */
111 "5 weeks ago", "5 weeks ago", /* -5 */
112 "2 weeks ago", "2 weeks ago", /* -2.2 */
113 "2 weeks ago", "2 weeks ago", /* -2 */
114 "last week", "1 week ago", /* -1 */
115 "0 weeks ago", "0 weeks ago", /* -0.7 */
116 "this week", "0 weeks ago", /* -0 */
117 "this week", "in 0 weeks", /* 0 */
118 "in 0 weeks", "in 0 weeks", /* 0.7 */
119 "next week", "in 1 week", /* 1 */
120 "in 2 weeks", "in 2 weeks", /* 2 */
121 "in 5 weeks", "in 5 weeks" /* 5 */
122 };
123
124 static const FieldsDat en_attr0_long_midSent_week[kNumOffsets*2] = {
125 /* text numeric text numeric */
126 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "5 weeks ago", "5 weeks ago", -5 */
127 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "2 weeks ago", "2 weeks ago", -2.2 */
128 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "2 weeks ago", "2 weeks ago", -2 */
129 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "last week", "1 week ago", -1 */
130 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "0 weeks ago", "0 weeks ago", -0.7 */
131 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "this week", "0 weeks ago", -0 */
132 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "this week", "in 0 weeks", 0 */
133 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 0 weeks", "in 0 weeks", 0.7 */
134 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "next week", "in 1 week", 1 */
135 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 2 weeks", "in 2 weeks", 2 */
136 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 5 weeks", "in 5 weeks" 5 */
137 };
138
139 static const char* en_decDef_short_midSent_week[kNumOffsets*2] = {
140 /* text numeric */
141 "5 wk. ago", "5 wk. ago", /* -5 */
142 "2.2 wk. ago", "2.2 wk. ago", /* -2.2 */
143 "2 wk. ago", "2 wk. ago", /* -2 */
144 "last wk.", "1 wk. ago", /* -1 */
145 "0.7 wk. ago", "0.7 wk. ago", /* -0.7 */
146 "this wk.", "0 wk. ago", /* -0 */
147 "this wk.", "in 0 wk.", /* 0 */
148 "in 0.7 wk.", "in 0.7 wk.", /* 0.7 */
149 "next wk.", "in 1 wk.", /* 1 */
150 "in 2 wk.", "in 2 wk.", /* 2 */
151 "in 5 wk.", "in 5 wk." /* 5 */
152 };
153
154 static const FieldsDat en_attrDef_short_midSent_week[kNumOffsets*2] = {
155 /* text numeric text numeric */
156 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "5 wk. ago", "5 wk. ago", -5 */
157 {UDAT_REL_NUMERIC_FIELD, 0, 3}, {UDAT_REL_NUMERIC_FIELD, 0, 3}, /* "2.2 wk. ago", "2.2 wk. ago", -2.2 */
158 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "2 wk. ago", "2 wk. ago", -2 */
159 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "last wk.", "1 wk. ago", -1 */
160 {UDAT_REL_NUMERIC_FIELD, 0, 3}, {UDAT_REL_NUMERIC_FIELD, 0, 3}, /* "0.7 wk. ago", "0.7 wk. ago", -0.7 */
161 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "this wk.", "0 wk. ago", -0 */
162 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "this wk.", "in 0 wk.", 0 */
163 {UDAT_REL_NUMERIC_FIELD, 3, 6}, {UDAT_REL_NUMERIC_FIELD, 3, 6}, /* "in 0.7 wk.", "in 0.7 wk.", 0.7 */
164 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "next wk.", "in 1 wk.", 1 */
165 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 2 wk.", "in 2 wk.", 2 */
166 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 5 wk.", "in 5 wk." 5 */
167 };
168
169 static const char* en_decDef_long_midSent_min[kNumOffsets*2] = {
170 /* text numeric */
171 "5 minutes ago", "5 minutes ago", /* -5 */
172 "2.2 minutes ago", "2.2 minutes ago", /* -2.2 */
173 "2 minutes ago", "2 minutes ago", /* -2 */
174 "1 minute ago", "1 minute ago", /* -1 */
175 "0.7 minutes ago", "0.7 minutes ago", /* -0.7 */
176 "this minute", "0 minutes ago", /* -0 */
177 "this minute", "in 0 minutes", /* 0 */
178 "in 0.7 minutes", "in 0.7 minutes", /* 0.7 */
179 "in 1 minute", "in 1 minute", /* 1 */
180 "in 2 minutes", "in 2 minutes", /* 2 */
181 "in 5 minutes", "in 5 minutes" /* 5 */
182 };
183
184 static const FieldsDat en_attrDef_long_midSent_min[kNumOffsets*2] = {
185 /* text numeric text numeric */
186 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "5 minutes ago", "5 minutes ago", -5 */
187 {UDAT_REL_NUMERIC_FIELD, 0, 3}, {UDAT_REL_NUMERIC_FIELD, 0, 3}, /* "2.2 minutes ago", "2.2 minutes ago", -2.2 */
188 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "2 minutes ago", "2 minutes ago", -2 */
189 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "1 minute ago", "1 minute ago", -1 */
190 {UDAT_REL_NUMERIC_FIELD, 0, 3}, {UDAT_REL_NUMERIC_FIELD, 0, 3}, /* "0.7 minutes ago", "0.7 minutes ago", -0.7 */
191 {-1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "this minute", "0 minutes ago", -0 */
192 {-1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "this minute", "in 0 minutes", 0 */
193 {UDAT_REL_NUMERIC_FIELD, 3, 6}, {UDAT_REL_NUMERIC_FIELD, 3, 6}, /* "in 0.7 minutes", "in 0.7 minutes", 0.7 */
194 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 1 minute", "in 1 minute", 1 */
195 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 2 minutes", "in 2 minutes", 2 */
196 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 5 minutes", "in 5 minutes" 5 */
197 };
198
199 static const char* en_dec0_long_midSent_tues[kNumOffsets*2] = {
200 /* text numeric */
201 "5 Tuesdays ago", "5 Tuesdays ago", /* -5 */
202 ""/*no data */, ""/*no data */, /* -2.2 */
203 "2 Tuesdays ago", "2 Tuesdays ago", /* -2 */
204 "last Tuesday", "1 Tuesday ago", /* -1 */
205 ""/*no data */, ""/*no data */, /* -0.7 */
206 "this Tuesday", "0 Tuesdays ago", /* -0 */
207 "this Tuesday", "in 0 Tuesdays", /* 0 */
208 ""/*no data */, ""/*no data */, /* 0.7 */
209 "next Tuesday", "in 1 Tuesday", /* 1 */
210 "in 2 Tuesdays", "in 2 Tuesdays", /* 2 */
211 "in 5 Tuesdays", "in 5 Tuesdays", /* 5 */
212 };
213
214 static const FieldsDat en_attr0_long_midSent_tues[kNumOffsets*2] = {
215 /* text numeric text numeric */
216 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "5 Tuesdays ago", "5 Tuesdays ago", -5 */
217 { -1, -1, -1}, { -1, -1, -1}, /* "" , "" , -2.2 */
218 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "2 Tuesdays ago", "2 Tuesdays ago", -2 */
219 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "last Tuesday", "1 Tuesday ago", -1 */
220 { -1, -1, -1}, { -1, -1, -1}, /* "" , "" , -0.7 */
221 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "this Tuesday", "0 Tuesdays ago", -0 */
222 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "this Tuesday", "in 0 Tuesdays", 0 */
223 { -1, -1, -1}, { -1, -1, -1}, /* "" , "" , 0.7 */
224 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "next Tuesday", "in 1 Tuesday", 1 */
225 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 2 Tuesdays", "in 2 Tuesdays", 2 */
226 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 5 Tuesdays", "in 5 Tuesdays", 5 */
227 };
228
229 static const char* fr_decDef_long_midSent_day[kNumOffsets*2] = {
230 /* text numeric */
231 "il y a 5 jours", "il y a 5 jours", /* -5 */
232 "il y a 2,2 jours", "il y a 2,2 jours", /* -2.2 */
233 "avant-hier", "il y a 2 jours", /* -2 */
234 "hier", "il y a 1 jour", /* -1 */
235 "il y a 0,7 jour", "il y a 0,7 jour", /* -0.7 */
236 "aujourd\\u2019hui", "il y a 0 jour", /* -0 */
237 "aujourd\\u2019hui", "dans 0 jour", /* 0 */
238 "dans 0,7 jour", "dans 0,7 jour", /* 0.7 */
239 "demain", "dans 1 jour", /* 1 */
240 "apr\\u00E8s-demain", "dans 2 jours", /* 2 */
241 "dans 5 jours", "dans 5 jours" /* 5 */
242 };
243
244 static const FieldsDat fr_attrDef_long_midSent_day[kNumOffsets*2] = {
245 /* text numeric text numeric */
246 {UDAT_REL_NUMERIC_FIELD, 7, 8}, {UDAT_REL_NUMERIC_FIELD, 7, 8}, /* "il y a 5 jours", "il y a 5 jours", -5 */
247 {UDAT_REL_NUMERIC_FIELD, 7, 10}, {UDAT_REL_NUMERIC_FIELD, 7, 10}, /* "il y a 2,2 jours", "il y a 2,2 jours", -2.2 */
248 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 7, 8}, /* "avant-hier", "il y a 2 jours", -2 */
249 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 7, 8}, /* "hier", "il y a 1 jour", -1 */
250 {UDAT_REL_NUMERIC_FIELD, 7, 10}, {UDAT_REL_NUMERIC_FIELD, 7, 10}, /* "il y a 0,7 jour", "il y a 0,7 jour", -0.7 */
251 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 7, 8}, /* "aujourd\\u2019hui", "il y a 0 jour", -0 */
252 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 5, 6}, /* "aujourd\\u2019hui", "dans 0 jour", 0 */
253 {UDAT_REL_NUMERIC_FIELD, 5, 8}, {UDAT_REL_NUMERIC_FIELD, 5, 8}, /* "dans 0,7 jour", "dans 0,7 jour", 0.7 */
254 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 5, 6}, /* "demain", "dans 1 jour", 1 */
255 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 5, 6}, /* "apr\\u00E8s-demain", "dans 2 jours", 2 */
256 {UDAT_REL_NUMERIC_FIELD, 5, 6}, {UDAT_REL_NUMERIC_FIELD, 5, 6}, /* "dans 5 jours", "dans 5 jours" 5 */
257 };
258
259 static const char* ak_decDef_long_stdAlon_sec[kNumOffsets*2] = { // falls back to root
260 /* text numeric */
261 "-5 s", "-5 s", /* -5 */
262 "-2.2 s", "-2.2 s", /* -2.2 */
263 "-2 s", "-2 s", /* -2 */
264 "-1 s", "-1 s", /* -1 */
265 "-0.7 s", "-0.7 s", /* -0.7 */
266 "now", "-0 s", /* -0 */
267 "now", "+0 s", /* 0 */
268 "+0.7 s", "+0.7 s", /* 0.7 */
269 "+1 s", "+1 s", /* 1 */
270 "+2 s", "+2 s", /* 2 */
271 "+5 s", "+5 s", /* 5 */
272 };
273
274 static const FieldsDat ak_attrDef_long_stdAlon_sec[kNumOffsets*2] = {
275 {UDAT_REL_NUMERIC_FIELD, 1, 2}, {UDAT_REL_NUMERIC_FIELD, 1, 2},
276 {UDAT_REL_NUMERIC_FIELD, 1, 4}, {UDAT_REL_NUMERIC_FIELD, 1, 4},
277 {UDAT_REL_NUMERIC_FIELD, 1, 2}, {UDAT_REL_NUMERIC_FIELD, 1, 2},
278 {UDAT_REL_NUMERIC_FIELD, 1, 2}, {UDAT_REL_NUMERIC_FIELD, 1, 2},
279 {UDAT_REL_NUMERIC_FIELD, 1, 4}, {UDAT_REL_NUMERIC_FIELD, 1, 4},
280 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 1, 2},
281 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 1, 2},
282 {UDAT_REL_NUMERIC_FIELD, 1, 4}, {UDAT_REL_NUMERIC_FIELD, 1, 4},
283 {UDAT_REL_NUMERIC_FIELD, 1, 2}, {UDAT_REL_NUMERIC_FIELD, 1, 2},
284 {UDAT_REL_NUMERIC_FIELD, 1, 2}, {UDAT_REL_NUMERIC_FIELD, 1, 2},
285 {UDAT_REL_NUMERIC_FIELD, 1, 2}, {UDAT_REL_NUMERIC_FIELD, 1, 2},
286 };
287
288 static const char* enIN_decDef_short_midSent_weds[kNumOffsets*2] = {
289 /* text numeric */
290 "5 Wed. ago", "5 Wed. ago", /* -5 */
291 "2.2 Wed. ago", "2.2 Wed. ago", /* -2.2 */
292 "2 Wed. ago", "2 Wed. ago", /* -2 */
293 "last Wed", "1 Wed. ago", /* -1 */
294 "0.7 Wed. ago", "0.7 Wed. ago", /* -0.7 */
295 "this Wed", "0 Wed. ago", /* -0 */
296 "this Wed", "in 0 Wed.", /* 0 */
297 "in 0.7 Wed.", "in 0.7 Wed.", /* 0.7 */
298 "next Wed", "in 1 Wed", /* 1 */ // in 1 Wed. missing in logical group
299 "in 2 Wed.", "in 2 Wed.", /* 2 */
300 "in 5 Wed.", "in 5 Wed." /* 5 */
301 };
302
303 static const FieldsDat enIN_attrDef_short_midSent_weds[kNumOffsets*2] = {
304 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1},
305 {UDAT_REL_NUMERIC_FIELD, 0, 3}, {UDAT_REL_NUMERIC_FIELD, 0, 3},
306 {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1},
307 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 0, 1},
308 {UDAT_REL_NUMERIC_FIELD, 0, 3}, {UDAT_REL_NUMERIC_FIELD, 0, 3},
309 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 0, 1},
310 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 3, 4},
311 {UDAT_REL_NUMERIC_FIELD, 3, 6}, {UDAT_REL_NUMERIC_FIELD, 3, 6},
312 { -1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 3, 4},
313 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4},
314 {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4},
315 };
316
317 typedef struct {
318 const char* locale;
319 int32_t decPlaces; /* fixed decimal places; -1 to use default num formatter */
320 UDateRelativeDateTimeFormatterStyle width;
321 UDisplayContext capContext;
322 URelativeDateTimeUnit unit;
323 const char ** expectedResults; /* for the various offsets */
324 const FieldsDat* expectedAttributes;
325 } RelDateTimeFormatTestItem;
326
327 static const RelDateTimeFormatTestItem fmtTestItems[] = {
328 { "en", -1, UDAT_STYLE_LONG, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_SECOND,
329 en_decDef_long_midSent_sec, en_attrDef_long_midSent_sec },
330 { "en", -1, UDAT_STYLE_LONG, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK,
331 en_decDef_long_midSent_week, en_attrDef_long_midSent_week},
332 { "en", 0, UDAT_STYLE_LONG, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK,
333 en_dec0_long_midSent_week, en_attr0_long_midSent_week},
334 { "en", -1, UDAT_STYLE_SHORT, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEEK,
335 en_decDef_short_midSent_week, en_attrDef_short_midSent_week},
336 { "en", -1, UDAT_STYLE_LONG, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_MINUTE,
337 en_decDef_long_midSent_min, en_attrDef_long_midSent_min},
338 { "en", -1, UDAT_STYLE_LONG, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_TUESDAY,
339 en_dec0_long_midSent_tues, en_attr0_long_midSent_tues},
340 { "fr", -1, UDAT_STYLE_LONG, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_DAY,
341 fr_decDef_long_midSent_day, fr_attrDef_long_midSent_day},
342 { "ak", -1, UDAT_STYLE_LONG, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, UDAT_REL_UNIT_SECOND,
343 ak_decDef_long_stdAlon_sec, ak_attrDef_long_stdAlon_sec},
344 { "en_IN", -1, UDAT_STYLE_SHORT, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UDAT_REL_UNIT_WEDNESDAY,
345 enIN_decDef_short_midSent_weds, enIN_attrDef_short_midSent_weds},
346 { NULL, 0, (UDateRelativeDateTimeFormatterStyle)0, (UDisplayContext)0, (URelativeDateTimeUnit)0, NULL, NULL } /* terminator */
347 };
348
349 enum { kUBufMax = 64, kBBufMax = 256 };
350
TestRelDateFmt()351 static void TestRelDateFmt()
352 {
353 const RelDateTimeFormatTestItem *itemPtr;
354 log_verbose("\nTesting ureldatefmt_open(), ureldatefmt_format(), ureldatefmt_formatNumeric() with various parameters\n");
355 for (itemPtr = fmtTestItems; itemPtr->locale != NULL; itemPtr++) {
356 URelativeDateTimeFormatter *reldatefmt = NULL;
357 UNumberFormat* nfToAdopt = NULL;
358 UErrorCode status = U_ZERO_ERROR;
359 int32_t iOffset;
360
361 if (itemPtr->decPlaces >= 0) {
362 nfToAdopt = unum_open(UNUM_DECIMAL, NULL, 0, itemPtr->locale, NULL, &status);
363 if ( U_FAILURE(status) ) {
364 log_data_err("FAIL: unum_open(UNUM_DECIMAL, ...) for locale %s: %s\n", itemPtr->locale, myErrorName(status));
365 continue;
366 }
367 unum_setAttribute(nfToAdopt, UNUM_MIN_FRACTION_DIGITS, itemPtr->decPlaces);
368 unum_setAttribute(nfToAdopt, UNUM_MAX_FRACTION_DIGITS, itemPtr->decPlaces);
369 unum_setAttribute(nfToAdopt, UNUM_ROUNDING_MODE, UNUM_ROUND_DOWN);
370 }
371 reldatefmt = ureldatefmt_open(itemPtr->locale, nfToAdopt, itemPtr->width, itemPtr->capContext, &status);
372 if ( U_FAILURE(status) ) {
373 log_data_err("FAIL: ureldatefmt_open() for locale %s, decPlaces %d, width %d, capContext %d: %s\n",
374 itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
375 myErrorName(status) );
376 continue;
377 }
378
379 for (iOffset = 0; iOffset < kNumOffsets; iOffset++) {
380 UChar ubufget[kUBufMax];
381 int32_t ulenget;
382
383 if (itemPtr->unit >= UDAT_REL_UNIT_SUNDAY && offsets[iOffset] != -1.0 && offsets[iOffset] != 0.0 && offsets[iOffset] != 1.0) {
384 continue; /* we do not currently have data for this */
385 }
386
387 status = U_ZERO_ERROR;
388 ulenget = ureldatefmt_format(reldatefmt, offsets[iOffset], itemPtr->unit, ubufget, kUBufMax, &status);
389 if ( U_FAILURE(status) ) {
390 log_err("FAIL: ureldatefmt_format() for locale %s, decPlaces %d, width %d, capContext %d, offset %.2f, unit %d: %s\n",
391 itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
392 offsets[iOffset], (int)itemPtr->unit, myErrorName(status) );
393 } else {
394 UChar ubufexp[kUBufMax];
395 int32_t ulenexp = u_unescape(itemPtr->expectedResults[iOffset*2], ubufexp, kUBufMax);
396 if (ulenget != ulenexp || u_strncmp(ubufget, ubufexp, ulenexp) != 0) {
397 char bbufget[kBBufMax];
398 u_austrncpy(bbufget, ubufget, kUBufMax);
399 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",
400 itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
401 offsets[iOffset], (int)itemPtr->unit, itemPtr->expectedResults[iOffset*2], bbufget );
402 }
403 }
404
405 if (itemPtr->unit >= UDAT_REL_UNIT_SUNDAY) {
406 continue; /* we do not currently have numeric-style data for this */
407 }
408
409 status = U_ZERO_ERROR;
410 ulenget = ureldatefmt_formatNumeric(reldatefmt, offsets[iOffset], itemPtr->unit, ubufget, kUBufMax, &status);
411 if ( U_FAILURE(status) ) {
412 log_err("FAIL: ureldatefmt_formatNumeric() for locale %s, decPlaces %d, width %d, capContext %d, offset %.2f, unit %d: %s\n",
413 itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
414 offsets[iOffset], (int)itemPtr->unit, myErrorName(status) );
415 } else {
416 UChar ubufexp[kUBufMax];
417 int32_t ulenexp = u_unescape(itemPtr->expectedResults[iOffset*2 + 1], ubufexp, kUBufMax);
418 if (ulenget != ulenexp || u_strncmp(ubufget, ubufexp, ulenexp) != 0) {
419 char bbufget[kBBufMax];
420 u_austrncpy(bbufget, ubufget, kUBufMax);
421 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",
422 itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
423 offsets[iOffset], (int)itemPtr->unit, itemPtr->expectedResults[iOffset*2 + 1], bbufget );
424 }
425 }
426 }
427
428 ureldatefmt_close(reldatefmt);
429 }
430 }
431
TestNumericField()432 static void TestNumericField()
433 {
434 const RelDateTimeFormatTestItem *itemPtr;
435 log_verbose("\nTesting ureldatefmt_open(), ureldatefmt_formatForFields(), ureldatefmt_formatNumericForFields() with various parameters\n");
436 for (itemPtr = fmtTestItems; itemPtr->locale != NULL; itemPtr++) {
437 URelativeDateTimeFormatter *reldatefmt = NULL;
438 UNumberFormat* nfToAdopt = NULL;
439 UErrorCode status = U_ZERO_ERROR;
440 int32_t iOffset;
441
442 if (itemPtr->decPlaces >= 0) {
443 nfToAdopt = unum_open(UNUM_DECIMAL, NULL, 0, itemPtr->locale, NULL, &status);
444 if ( U_FAILURE(status) ) {
445 log_data_err("FAIL: unum_open(UNUM_DECIMAL, ...) for locale %s: %s\n", itemPtr->locale, myErrorName(status));
446 continue;
447 }
448 unum_setAttribute(nfToAdopt, UNUM_MIN_FRACTION_DIGITS, itemPtr->decPlaces);
449 unum_setAttribute(nfToAdopt, UNUM_MAX_FRACTION_DIGITS, itemPtr->decPlaces);
450 unum_setAttribute(nfToAdopt, UNUM_ROUNDING_MODE, UNUM_ROUND_DOWN);
451 }
452 reldatefmt = ureldatefmt_open(itemPtr->locale, nfToAdopt, itemPtr->width, itemPtr->capContext, &status);
453 if ( U_FAILURE(status) ) {
454 log_data_err("FAIL: ureldatefmt_open() for locale %s, decPlaces %d, width %d, capContext %d: %s\n",
455 itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
456 myErrorName(status) );
457 continue;
458 }
459
460 for (iOffset = 0; iOffset < kNumOffsets; iOffset++) {
461 if (itemPtr->unit >= UDAT_REL_UNIT_SUNDAY && offsets[iOffset] != -1.0 && offsets[iOffset] != 0.0 && offsets[iOffset] != 1.0) {
462 continue; /* we do not currently have data for this */
463 }
464
465 /* Depend on the next one to verify the data */
466 status = U_ZERO_ERROR;
467 UFormattedRelativeDateTime* fv = ureldatefmt_openResult(&status);
468 if ( U_FAILURE(status) ) {
469 log_err("ureldatefmt_openResult fails, status %s\n", u_errorName(status));
470 continue;
471 }
472 ureldatefmt_formatToResult(reldatefmt, offsets[iOffset], itemPtr->unit, fv, &status);
473 if ( U_FAILURE(status) ) {
474 log_err("FAIL: ureldatefmt_formatForFields() for locale %s, decPlaces %d, width %d, capContext %d, offset %.2f, unit %d: %s\n",
475 itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
476 offsets[iOffset], (int)itemPtr->unit, myErrorName(status) );
477 } else {
478 UChar ubufexp[kUBufMax];
479 int32_t ulenexp = u_unescape(itemPtr->expectedResults[iOffset*2], ubufexp, kUBufMax);
480 int32_t ulenget;
481 const UChar* ubufget = ufmtval_getString(ureldatefmt_resultAsValue(fv, &status), &ulenget, &status);
482 assertUEquals("String content", ubufexp, ubufget);
483 assertIntEquals("String length", ulenexp, ulenget);
484
485 FieldsDat expectedAttr = itemPtr->expectedAttributes[iOffset*2];
486 UConstrainedFieldPosition* cfpos = ucfpos_open(&status);
487 UBool foundNumeric = false;
488 while (true) {
489 foundNumeric = ufmtval_nextPosition(ureldatefmt_resultAsValue(fv, &status), cfpos, &status);
490 if (!foundNumeric) {
491 break;
492 }
493 if (ucfpos_getCategory(cfpos, &status) == UFIELD_CATEGORY_RELATIVE_DATETIME
494 && ucfpos_getField(cfpos, &status) == UDAT_REL_NUMERIC_FIELD) {
495 break;
496 }
497 }
498 assertSuccess("Looking for numeric", &status);
499 int32_t beginPos, endPos;
500 ucfpos_getIndexes(cfpos, &beginPos, &endPos, &status);
501 if (expectedAttr.field == -1) {
502 if (foundNumeric) {
503 log_err("ureldatefmt_formatForFields as \"%s\"; expect no field, but got %d\n",
504 itemPtr->expectedResults[iOffset*2],
505 ucfpos_getField(cfpos, &status));
506 }
507 } else {
508 if (!foundNumeric ||
509 beginPos != expectedAttr.beginPos ||
510 endPos != expectedAttr.endPos) {
511 log_err("ureldatefmt_formatForFields as \"%s\"; expect field %d range %d-%d, get range %d-%d\n",
512 itemPtr->expectedResults[iOffset*2],
513 expectedAttr.field, expectedAttr.beginPos, expectedAttr.endPos,
514 beginPos, endPos);
515 }
516 }
517 ucfpos_close(cfpos);
518 }
519
520 if (itemPtr->unit >= UDAT_REL_UNIT_SUNDAY) {
521 ureldatefmt_closeResult(fv);
522 continue; /* we do not currently have numeric-style data for this */
523 }
524
525 /* Depend on the next one to verify the data */
526 status = U_ZERO_ERROR;
527 ureldatefmt_formatNumericToResult(reldatefmt, offsets[iOffset], itemPtr->unit, fv, &status);
528 if ( U_FAILURE(status) ) {
529 log_err("FAIL: ureldatefmt_formatNumericForFields() for locale %s, decPlaces %d, width %d, capContext %d, offset %.2f, unit %d: %s\n",
530 itemPtr->locale, itemPtr->decPlaces, (int)itemPtr->width, (int)itemPtr->capContext,
531 offsets[iOffset], (int)itemPtr->unit, myErrorName(status) );
532 } else {
533 UChar ubufexp[kUBufMax];
534 int32_t ulenexp = u_unescape(itemPtr->expectedResults[iOffset*2 + 1], ubufexp, kUBufMax);
535 int32_t ulenget;
536 const UChar* ubufget = ufmtval_getString(ureldatefmt_resultAsValue(fv, &status), &ulenget, &status);
537 assertUEquals("String content", ubufexp, ubufget);
538 assertIntEquals("String length", ulenexp, ulenget);
539
540 FieldsDat expectedAttr = itemPtr->expectedAttributes[iOffset*2 + 1];
541 UConstrainedFieldPosition* cfpos = ucfpos_open(&status);
542 UBool foundNumeric = false;
543 while (true) {
544 foundNumeric = ufmtval_nextPosition(ureldatefmt_resultAsValue(fv, &status), cfpos, &status);
545 if (!foundNumeric) {
546 break;
547 }
548 if (ucfpos_getCategory(cfpos, &status) == UFIELD_CATEGORY_RELATIVE_DATETIME
549 && ucfpos_getField(cfpos, &status) == UDAT_REL_NUMERIC_FIELD) {
550 break;
551 }
552 }
553 assertSuccess("Looking for numeric", &status);
554 int32_t beginPos, endPos;
555 ucfpos_getIndexes(cfpos, &beginPos, &endPos, &status);
556 if (expectedAttr.field == -1) {
557 if (foundNumeric) {
558 log_err("ureldatefmt_formatForFields as \"%s\"; expect no field, but got %d rang %d-%d\n",
559 itemPtr->expectedResults[iOffset*2],
560 ucfpos_getField(cfpos, &status), beginPos, endPos);
561 }
562 } else {
563 if (!foundNumeric ||
564 (beginPos != expectedAttr.beginPos || endPos != expectedAttr.endPos)) {
565 log_err("ureldatefmt_formatForFields as \"%s\"; expect field %d range %d-%d, get field %d range %d-%d\n",
566 itemPtr->expectedResults[iOffset*2 + 1],
567 expectedAttr.field, expectedAttr.beginPos, expectedAttr.endPos,
568 ucfpos_getField(cfpos, &status), beginPos, endPos);
569 }
570 }
571 ucfpos_close(cfpos);
572 }
573 ureldatefmt_closeResult(fv);
574 }
575
576 ureldatefmt_close(reldatefmt);
577 }
578 }
579
580 typedef struct {
581 const char* locale;
582 UDateRelativeDateTimeFormatterStyle width;
583 UDisplayContext capContext;
584 const char * relativeDateString;
585 const char * timeString;
586 const char * expectedResult;
587 } CombineDateTimeTestItem;
588
589 static const CombineDateTimeTestItem combTestItems[] = {
590 { "en", UDAT_STYLE_LONG, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, "yesterday", "3:45 PM", "yesterday, 3:45 PM" },
591 { NULL, (UDateRelativeDateTimeFormatterStyle)0, (UDisplayContext)0, NULL, NULL, NULL } /* terminator */
592 };
593
TestCombineDateTime()594 static void TestCombineDateTime()
595 {
596 const CombineDateTimeTestItem *itemPtr;
597 log_verbose("\nTesting ureldatefmt_combineDateAndTime() with various parameters\n");
598 for (itemPtr = combTestItems; itemPtr->locale != NULL; itemPtr++) {
599 URelativeDateTimeFormatter *reldatefmt = NULL;
600 UErrorCode status = U_ZERO_ERROR;
601 UChar ubufreldate[kUBufMax];
602 UChar ubuftime[kUBufMax];
603 UChar ubufget[kUBufMax];
604 int32_t ulenreldate, ulentime, ulenget;
605
606 reldatefmt = ureldatefmt_open(itemPtr->locale, NULL, itemPtr->width, itemPtr->capContext, &status);
607 if ( U_FAILURE(status) ) {
608 log_data_err("FAIL: ureldatefmt_open() for locale %s, width %d, capContext %d: %s\n",
609 itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, myErrorName(status) );
610 continue;
611 }
612
613 ulenreldate = u_unescape(itemPtr->relativeDateString, ubufreldate, kUBufMax);
614 ulentime = u_unescape(itemPtr->timeString, ubuftime, kUBufMax);
615 ulenget = ureldatefmt_combineDateAndTime(reldatefmt, ubufreldate, ulenreldate, ubuftime, ulentime, ubufget, kUBufMax, &status);
616 if ( U_FAILURE(status) ) {
617 log_err("FAIL: ureldatefmt_combineDateAndTime() for locale %s, width %d, capContext %d: %s\n",
618 itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, myErrorName(status) );
619 } else {
620 UChar ubufexp[kUBufMax];
621 int32_t ulenexp = u_unescape(itemPtr->expectedResult, ubufexp, kUBufMax);
622 if (ulenget != ulenexp || u_strncmp(ubufget, ubufexp, ulenexp) != 0) {
623 char bbufget[kBBufMax];
624 u_austrncpy(bbufget, ubufget, kUBufMax);
625 log_err("ERROR: ureldatefmt_combineDateAndTime() for locale %s, width %d, capContext %d;\n expected %s\n get %s\n",
626 itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, itemPtr->expectedResult, bbufget );
627 }
628 }
629 // preflight test
630 status = U_ZERO_ERROR;
631 ulenget = ureldatefmt_combineDateAndTime(reldatefmt, ubufreldate, ulenreldate, ubuftime, ulentime, NULL, 0, &status);
632 if ( status != U_BUFFER_OVERFLOW_ERROR) {
633 log_err("FAIL: ureldatefmt_combineDateAndTime() preflight for locale %s, width %d, capContext %d: expected U_BUFFER_OVERFLOW_ERROR, got %s\n",
634 itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, myErrorName(status) );
635 } else {
636 UChar ubufexp[kUBufMax];
637 int32_t ulenexp = u_unescape(itemPtr->expectedResult, ubufexp, kUBufMax);
638 if (ulenget != ulenexp) {
639 log_err("ERROR: ureldatefmt_combineDateAndTime() preflight for locale %s, width %d, capContext %d;\n expected len %d, get len %d\n",
640 itemPtr->locale, (int)itemPtr->width, (int)itemPtr->capContext, ulenexp, ulenget );
641 }
642 }
643
644 ureldatefmt_close(reldatefmt);
645 }
646 }
647
TestFields()648 static void TestFields() {
649 UErrorCode ec = U_ZERO_ERROR;
650 URelativeDateTimeFormatter* fmt = ureldatefmt_open(
651 "en-us",
652 NULL,
653 UDAT_STYLE_SHORT,
654 UDISPCTX_CAPITALIZATION_NONE,
655 &ec);
656 assertSuccess("Creating RelDTFmt", &ec);
657 UFormattedRelativeDateTime* frdt = ureldatefmt_openResult(&ec);
658 assertSuccess("Creating FmtVal", &ec);
659
660 ureldatefmt_formatNumericToResult(fmt, -50, UDAT_REL_UNIT_SATURDAY, frdt, &ec);
661 assertSuccess("formatNumeric", &ec);
662 {
663 const UFormattedValue* fv = ureldatefmt_resultAsValue(frdt, &ec);
664 assertSuccess("Should convert without error", &ec);
665 static const UFieldPositionWithCategory expectedFieldPositions[] = {
666 // category, field, begin index, end index
667 {UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD, 0, 2},
668 {UFIELD_CATEGORY_RELATIVE_DATETIME, UDAT_REL_NUMERIC_FIELD, 0, 2},
669 {UFIELD_CATEGORY_RELATIVE_DATETIME, UDAT_REL_LITERAL_FIELD, 3, 11}};
670 checkMixedFormattedValue(
671 "FormattedRelativeDateTime as FormattedValue (numeric)",
672 fv,
673 u"50 Sat. ago",
674 expectedFieldPositions,
675 UPRV_LENGTHOF(expectedFieldPositions));
676 }
677
678 ureldatefmt_formatToResult(fmt, -1, UDAT_REL_UNIT_WEEK, frdt, &ec);
679 assertSuccess("format", &ec);
680 {
681 const UFormattedValue* fv = ureldatefmt_resultAsValue(frdt, &ec);
682 assertSuccess("Should convert without error", &ec);
683 static const UFieldPositionWithCategory expectedFieldPositions[] = {
684 // category, field, begin index, end index
685 {UFIELD_CATEGORY_RELATIVE_DATETIME, UDAT_REL_LITERAL_FIELD, 0, 8}};
686 checkMixedFormattedValue(
687 "FormattedRelativeDateTime as FormattedValue (relative)",
688 fv,
689 u"last wk.",
690 expectedFieldPositions,
691 UPRV_LENGTHOF(expectedFieldPositions));
692 }
693
694 ureldatefmt_closeResult(frdt);
695 ureldatefmt_close(fmt);
696 }
697
698 #endif /* #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION */
699