• Home
  • 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 <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