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