1 /*
2 * Copyright 2014-2021 Haiku, Inc.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7 #include "DateFormatTest.h"
8
9 #include <DateFormat.h>
10 #include <FormattingConventions.h>
11 #include <Language.h>
12 #include <TimeFormat.h>
13 #include <TimeZone.h>
14
15 #include <cppunit/TestCaller.h>
16 #include <cppunit/TestSuite.h>
17
18
DateFormatTest()19 DateFormatTest::DateFormatTest()
20 {
21 }
22
23
~DateFormatTest()24 DateFormatTest::~DateFormatTest()
25 {
26 }
27
28
29 void
TestCustomFormat()30 DateFormatTest::TestCustomFormat()
31 {
32 struct Test {
33 const char* language;
34 const char* formatting;
35 const char* timeZone;
36 int32 fields;
37
38 BString expected;
39 BString force24;
40 BString force12;
41 };
42
43 BString buffer;
44
45 const Test tests[] = {
46 { "en", "en_US", "GMT+1", B_DATE_ELEMENT_HOUR | B_DATE_ELEMENT_MINUTE,
47 "10:21 PM", "22:21", "10:21 PM" },
48 { "en", "en_US", "GMT+1",
49 B_DATE_ELEMENT_HOUR | B_DATE_ELEMENT_MINUTE | B_DATE_ELEMENT_SECOND,
50 "10:21:18 PM", "22:21:18", "10:21:18 PM" },
51 { "en", "en_US", "GMT+1", B_DATE_ELEMENT_HOUR | B_DATE_ELEMENT_MINUTE
52 | B_DATE_ELEMENT_TIMEZONE,
53 "10:21 PM GMT+1", "22:21 GMT+1", "10:21 PM GMT+1" },
54 { "en", "en_US", "GMT+1", B_DATE_ELEMENT_HOUR | B_DATE_ELEMENT_MINUTE
55 | B_DATE_ELEMENT_SECOND | B_DATE_ELEMENT_TIMEZONE,
56 "10:21:18 PM GMT+1", "22:21:18 GMT+1", "10:21:18 PM GMT+1" },
57 { "fr", "fr_FR", "GMT+1", B_DATE_ELEMENT_HOUR | B_DATE_ELEMENT_MINUTE,
58 "22:21", "22:21", "10:21 PM" },
59 { NULL }
60 };
61
62 for (int i = 0; tests[i].language != NULL; i++)
63 {
64 NextSubTest();
65
66 BLanguage language(tests[i].language);
67 BFormattingConventions formatting(tests[i].formatting);
68 BTimeZone timeZone(tests[i].timeZone);
69 status_t result;
70
71 // Test default for language/formatting
72 {
73 BDateTimeFormat format(language, formatting);
74 format.SetDateTimeFormat(B_SHORT_DATE_FORMAT, B_SHORT_TIME_FORMAT,
75 tests[i].fields);
76
77 result = format.Format(buffer, 12345678, B_SHORT_DATE_FORMAT,
78 B_SHORT_TIME_FORMAT, &timeZone);
79
80 CPPUNIT_ASSERT_EQUAL(B_OK, result);
81 CPPUNIT_ASSERT_EQUAL(tests[i].expected, buffer);
82 }
83
84 // Test forced 24 hours
85 {
86 formatting.SetExplicitUse24HourClock(true);
87 BDateTimeFormat format(language, formatting);
88 format.SetDateTimeFormat(B_SHORT_DATE_FORMAT, B_SHORT_TIME_FORMAT,
89 tests[i].fields);
90 result = format.Format(buffer, 12345678, B_SHORT_DATE_FORMAT,
91 B_SHORT_TIME_FORMAT, &timeZone);
92
93 CPPUNIT_ASSERT_EQUAL(B_OK, result);
94 CPPUNIT_ASSERT_EQUAL(tests[i].force24, buffer);
95 }
96
97 // Test forced 12 hours
98 {
99 formatting.SetExplicitUse24HourClock(false);
100 BDateTimeFormat format(language, formatting);
101 format.SetDateTimeFormat(B_SHORT_DATE_FORMAT, B_SHORT_TIME_FORMAT,
102 tests[i].fields);
103 result = format.Format(buffer, 12345678, B_SHORT_DATE_FORMAT,
104 B_SHORT_TIME_FORMAT, &timeZone);
105
106 CPPUNIT_ASSERT_EQUAL(B_OK, result);
107 CPPUNIT_ASSERT_EQUAL(tests[i].force12, buffer);
108 }
109 }
110 }
111
112
113 void
TestFormat()114 DateFormatTest::TestFormat()
115 {
116 struct Value {
117 const char* language;
118 const char* convention;
119 const char* timeZone;
120 time_t time;
121 const char* shortDate;
122 const char* longDate;
123 const char* shortTime;
124 const char* longTime;
125 const char* shortDateTime;
126 };
127
128 static const Value values[] = {
129 {"en", "en_US", "GMT+1", 12345, "1/1/70", "January 1, 1970",
130 "4:25 AM", "4:25:45 AM", "1/1/70, 4:25 AM"},
131 {"fr", "fr_FR", "GMT+1", 12345, "01/01/1970", "1 janvier 1970",
132 "04:25", "04:25:45", "01/01/1970 04:25"},
133 {"fr", "fr_FR", "GMT+1", 12345678, "23/05/1970", "23 mai 1970",
134 "22:21", "22:21:18", "23/05/1970 22:21"},
135 {NULL}
136 };
137
138 BString output;
139 status_t result;
140
141 for (int i = 0; values[i].language != NULL; i++) {
142 NextSubTest();
143
144 BLanguage language(values[i].language);
145 BFormattingConventions formatting(values[i].convention);
146 BTimeZone timeZone(values[i].timeZone);
147 BDateFormat dateFormat(language, formatting);
148 BTimeFormat timeFormat(language, formatting);
149 BDateTimeFormat dateTimeFormat(language, formatting);
150
151 result = dateFormat.Format(output, values[i].time, B_SHORT_DATE_FORMAT,
152 &timeZone);
153 CPPUNIT_ASSERT_EQUAL(B_OK, result);
154 CPPUNIT_ASSERT_EQUAL(BString(values[i].shortDate), output);
155
156 result = dateFormat.Format(output, values[i].time, B_LONG_DATE_FORMAT,
157 &timeZone);
158 CPPUNIT_ASSERT_EQUAL(B_OK, result);
159 CPPUNIT_ASSERT_EQUAL(BString(values[i].longDate), output);
160
161 result = timeFormat.Format(output, values[i].time, B_SHORT_TIME_FORMAT,
162 &timeZone);
163 CPPUNIT_ASSERT_EQUAL(B_OK, result);
164 CPPUNIT_ASSERT_EQUAL(BString(values[i].shortTime), output);
165
166 result = timeFormat.Format(output, values[i].time, B_MEDIUM_TIME_FORMAT,
167 &timeZone);
168 CPPUNIT_ASSERT_EQUAL(B_OK, result);
169 CPPUNIT_ASSERT_EQUAL(BString(values[i].longTime), output);
170
171 result = dateTimeFormat.Format(output, values[i].time,
172 B_SHORT_DATE_FORMAT, B_SHORT_TIME_FORMAT, &timeZone);
173 CPPUNIT_ASSERT_EQUAL(B_OK, result);
174 CPPUNIT_ASSERT_EQUAL(BString(values[i].shortDateTime), output);
175 }
176 }
177
178
179 void
TestFormatDate()180 DateFormatTest::TestFormatDate()
181 {
182 BLanguage language("en");
183 BFormattingConventions formatting("en_US");
184 BDateFormat format(language, formatting);
185
186 BString output;
187 status_t result;
188
189 BDate date(2014, 9, 29);
190
191 result = format.Format(output, date, B_LONG_DATE_FORMAT);
192 CPPUNIT_ASSERT_EQUAL(B_OK, result);
193 CPPUNIT_ASSERT_EQUAL(BString("September 29, 2014"), output);
194
195 // Test an invalid date - must return B_BAD_DATA
196 date.SetDate(2014, 29, 29);
197 result = format.Format(output, date, B_LONG_DATE_FORMAT);
198 CPPUNIT_ASSERT_EQUAL(B_BAD_DATA, result);
199 }
200
201
202 void
TestMonthNames()203 DateFormatTest::TestMonthNames()
204 {
205 BLanguage language("en");
206 BFormattingConventions formatting("en_US");
207 BDateFormat format(language, formatting);
208
209 BString buffer;
210 status_t result = format.GetMonthName(1, buffer);
211
212 CPPUNIT_ASSERT_EQUAL(BString("January"), buffer);
213 CPPUNIT_ASSERT_EQUAL(B_OK, result);
214
215 buffer.Truncate(0);
216 result = format.GetMonthName(12, buffer);
217
218 CPPUNIT_ASSERT_EQUAL(BString("December"), buffer);
219 CPPUNIT_ASSERT_EQUAL(B_OK, result);
220
221 buffer.Truncate(0);
222 result = format.GetMonthName(1, buffer, B_FULL_DATE_FORMAT);
223
224 CPPUNIT_ASSERT_EQUAL(BString("January"), buffer);
225 CPPUNIT_ASSERT_EQUAL(B_OK, result);
226
227 buffer.Truncate(0);
228 result = format.GetMonthName(12, buffer, B_FULL_DATE_FORMAT);
229
230 CPPUNIT_ASSERT_EQUAL(BString("December"), buffer);
231 CPPUNIT_ASSERT_EQUAL(B_OK, result);
232
233 buffer.Truncate(0);
234 result = format.GetMonthName(1, buffer, B_LONG_DATE_FORMAT);
235
236 CPPUNIT_ASSERT_EQUAL(BString("Jan"), buffer);
237 CPPUNIT_ASSERT_EQUAL(B_OK, result);
238
239 buffer.Truncate(0);
240 result = format.GetMonthName(12, buffer, B_LONG_DATE_FORMAT);
241
242 CPPUNIT_ASSERT_EQUAL(BString("Dec"), buffer);
243 CPPUNIT_ASSERT_EQUAL(B_OK, result);
244
245 buffer.Truncate(0);
246 result = format.GetMonthName(1, buffer, B_MEDIUM_DATE_FORMAT);
247
248 CPPUNIT_ASSERT_EQUAL(BString("Jan"), buffer);
249 CPPUNIT_ASSERT_EQUAL(B_OK, result);
250
251 buffer.Truncate(0);
252 result = format.GetMonthName(12, buffer, B_MEDIUM_DATE_FORMAT);
253
254 CPPUNIT_ASSERT_EQUAL(BString("Dec"), buffer);
255 CPPUNIT_ASSERT_EQUAL(B_OK, result);
256
257 buffer.Truncate(0);
258 result = format.GetMonthName(1, buffer, B_SHORT_DATE_FORMAT);
259
260 CPPUNIT_ASSERT_EQUAL(BString("J"), buffer);
261 CPPUNIT_ASSERT_EQUAL(B_OK, result);
262
263 buffer.Truncate(0);
264 result = format.GetMonthName(12, buffer, B_SHORT_DATE_FORMAT);
265
266 CPPUNIT_ASSERT_EQUAL(BString("D"), buffer);
267 CPPUNIT_ASSERT_EQUAL(B_OK, result);
268
269 }
270
271
272 void
TestDayNames()273 DateFormatTest::TestDayNames()
274 {
275 BLanguage language("en");
276 BFormattingConventions formatting("en_US");
277 BDateFormat format(language, formatting);
278
279 BString buffer;
280 status_t result = format.GetDayName(1, buffer);
281
282 CPPUNIT_ASSERT_EQUAL(BString("Monday"), buffer);
283 CPPUNIT_ASSERT_EQUAL(B_OK, result);
284
285 buffer.Truncate(0);
286 result = format.GetDayName(2, buffer);
287
288 CPPUNIT_ASSERT_EQUAL(BString("Tuesday"), buffer);
289 CPPUNIT_ASSERT_EQUAL(B_OK, result);
290
291 buffer.Truncate(0);
292 result = format.GetDayName(1, buffer, B_FULL_DATE_FORMAT);
293
294 CPPUNIT_ASSERT_EQUAL(BString("Monday"), buffer);
295 CPPUNIT_ASSERT_EQUAL(B_OK, result);
296
297 buffer.Truncate(0);
298 result = format.GetDayName(2, buffer, B_FULL_DATE_FORMAT);
299
300 CPPUNIT_ASSERT_EQUAL(BString("Tuesday"), buffer);
301 CPPUNIT_ASSERT_EQUAL(B_OK, result);
302
303 buffer.Truncate(0);
304 result = format.GetDayName(1, buffer, B_LONG_DATE_FORMAT);
305
306 CPPUNIT_ASSERT_EQUAL(BString("Mon"), buffer);
307 CPPUNIT_ASSERT_EQUAL(B_OK, result);
308
309 buffer.Truncate(0);
310 result = format.GetDayName(2, buffer, B_LONG_DATE_FORMAT);
311
312 CPPUNIT_ASSERT_EQUAL(BString("Tue"), buffer);
313 CPPUNIT_ASSERT_EQUAL(B_OK, result);
314
315 buffer.Truncate(0);
316 result = format.GetDayName(1, buffer, B_MEDIUM_DATE_FORMAT);
317
318 CPPUNIT_ASSERT_EQUAL(BString("Mo"), buffer);
319 CPPUNIT_ASSERT_EQUAL(B_OK, result);
320
321 buffer.Truncate(0);
322 result = format.GetDayName(2, buffer, B_MEDIUM_DATE_FORMAT);
323
324 CPPUNIT_ASSERT_EQUAL(BString("Tu"), buffer);
325 CPPUNIT_ASSERT_EQUAL(B_OK, result);
326
327 buffer.Truncate(0);
328 result = format.GetDayName(1, buffer, B_SHORT_DATE_FORMAT);
329
330 CPPUNIT_ASSERT_EQUAL(BString("M"), buffer);
331 CPPUNIT_ASSERT_EQUAL(B_OK, result);
332
333 buffer.Truncate(0);
334 result = format.GetDayName(2, buffer, B_SHORT_DATE_FORMAT);
335
336 CPPUNIT_ASSERT_EQUAL(BString("T"), buffer);
337 CPPUNIT_ASSERT_EQUAL(B_OK, result);
338 }
339
340
341 namespace BPrivate {
342
343
operator <<(std::ostream & stream,const BDate & date)344 std::ostream& operator<<(std::ostream& stream, const BDate& date)
345 {
346 stream << date.Year();
347 stream << '-';
348 stream << date.Month();
349 stream << '-';
350 stream << date.Day();
351
352 return stream;
353 }
354
355
operator <<(std::ostream & stream,const BTime & date)356 std::ostream& operator<<(std::ostream& stream, const BTime& date)
357 {
358 stream << date.Hour();
359 stream << ':';
360 stream << date.Minute();
361 stream << ':';
362 stream << date.Second();
363
364 return stream;
365 }
366
367
368 } // namespace BPrivate
369
370
371 void
TestParseDate()372 DateFormatTest::TestParseDate()
373 {
374 BLanguage language("en");
375 BFormattingConventions formatting("en_US");
376 BDateFormat format(language, formatting);
377 BDate date;
378 status_t result;
379
380 struct Test {
381 const char* input;
382 BDate output;
383 };
384
385 static const Test tests[] = {
386 {"01/01/1970", BDate(1970, 1, 1)},
387 {"05/07/1988", BDate(1988, 5, 7)},
388 {"07/31/2345", BDate(2345, 7, 31)},
389 {NULL}
390 };
391
392 for (int i = 0; tests[i].input != NULL; i++) {
393 NextSubTest();
394 result = format.Parse(tests[i].input, B_SHORT_DATE_FORMAT, date);
395
396 CPPUNIT_ASSERT_EQUAL(tests[i].output, date);
397 CPPUNIT_ASSERT_EQUAL(B_OK, result);
398 }
399 }
400
401
402 void
TestParseTime()403 DateFormatTest::TestParseTime()
404 {
405 BLanguage language("fr");
406 BFormattingConventions formatting("fr_FR");
407 BTimeFormat format(language, formatting);
408 BTime date;
409 status_t result;
410
411 struct Test {
412 const char* input;
413 BTime output;
414 };
415
416 static const Test tests[] = {
417 {"03:25", BTime(3, 25, 0)},
418 {"16:18", BTime(16, 18, 0)},
419 {"23:59", BTime(23, 59, 0)},
420 {NULL}
421 };
422
423 for (int i = 0; tests[i].input != NULL; i++) {
424 NextSubTest();
425 result = format.Parse(tests[i].input, B_SHORT_TIME_FORMAT, date);
426
427 CPPUNIT_ASSERT_EQUAL(tests[i].output, date);
428 CPPUNIT_ASSERT_EQUAL(B_OK, result);
429 }
430 }
431
432
433 /*static*/ void
AddTests(BTestSuite & parent)434 DateFormatTest::AddTests(BTestSuite& parent)
435 {
436 CppUnit::TestSuite& suite = *new CppUnit::TestSuite("DateFormatTest");
437
438 suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
439 "DateFormatTest::TestCustomFormat", &DateFormatTest::TestCustomFormat));
440 suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
441 "DateFormatTest::TestFormat", &DateFormatTest::TestFormat));
442 suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
443 "DateFormatTest::TestFormatDate", &DateFormatTest::TestFormatDate));
444 suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
445 "DateFormatTest::TestMonthNames", &DateFormatTest::TestMonthNames));
446 suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
447 "DateFormatTest::TestDayNames", &DateFormatTest::TestDayNames));
448 suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
449 "DateFormatTest::TestParseDate", &DateFormatTest::TestParseDate));
450 suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
451 "DateFormatTest::TestParseTime", &DateFormatTest::TestParseTime));
452
453 parent.addTest("DateFormatTest", &suite);
454 }
455