xref: /haiku/src/tests/kits/locale/DateFormatTest.cpp (revision ae0a10cad3999b13cbfa47a3d947a5219d2d90f4)
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 
19 DateFormatTest::DateFormatTest()
20 {
21 }
22 
23 
24 DateFormatTest::~DateFormatTest()
25 {
26 }
27 
28 
29 void
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
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
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
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
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 std::ostream& operator<<(std::ostream& stream, const BDate& date)
342 {
343 	stream << date.Year();
344 	stream << '-';
345 	stream << date.Month();
346 	stream << '-';
347 	stream << date.Day();
348 
349 	return stream;
350 }
351 
352 
353 std::ostream& operator<<(std::ostream& stream, const BTime& date)
354 {
355 	stream << date.Hour();
356 	stream << ':';
357 	stream << date.Minute();
358 	stream << ':';
359 	stream << date.Second();
360 
361 	return stream;
362 }
363 
364 
365 void
366 DateFormatTest::TestParseDate()
367 {
368 	BLanguage language("en");
369 	BFormattingConventions formatting("en_US");
370 	BDateFormat format(language, formatting);
371 	BDate date;
372 	status_t result;
373 
374 	struct Test {
375 		const char* input;
376 		BDate output;
377 	};
378 
379 	static const Test tests[] = {
380 		{"01/01/1970", BDate(1970, 1, 1)},
381 		{"05/07/1988", BDate(1988, 5, 7)},
382 		{"07/31/2345", BDate(2345, 7, 31)},
383 		{NULL}
384 	};
385 
386 	for (int i = 0; tests[i].input != NULL; i++) {
387 		NextSubTest();
388 		result = format.Parse(tests[i].input, B_SHORT_DATE_FORMAT, date);
389 
390 		CPPUNIT_ASSERT_EQUAL(tests[i].output, date);
391 		CPPUNIT_ASSERT_EQUAL(B_OK, result);
392 	}
393 }
394 
395 
396 void
397 DateFormatTest::TestParseTime()
398 {
399 	BLanguage language("fr");
400 	BFormattingConventions formatting("fr_FR");
401 	BTimeFormat format(language, formatting);
402 	BTime date;
403 	status_t result;
404 
405 	struct Test {
406 		const char* input;
407 		BTime output;
408 	};
409 
410 	static const Test tests[] = {
411 		{"03:25", BTime(3, 25, 0)},
412 		{"16:18", BTime(16, 18, 0)},
413 		{"23:59", BTime(23, 59, 0)},
414 		{NULL}
415 	};
416 
417 	for (int i = 0; tests[i].input != NULL; i++) {
418 		NextSubTest();
419 		result = format.Parse(tests[i].input, B_SHORT_TIME_FORMAT, date);
420 
421 		CPPUNIT_ASSERT_EQUAL(tests[i].output, date);
422 		CPPUNIT_ASSERT_EQUAL(B_OK, result);
423 	}
424 }
425 
426 
427 /*static*/ void
428 DateFormatTest::AddTests(BTestSuite& parent)
429 {
430 	CppUnit::TestSuite& suite = *new CppUnit::TestSuite("DateFormatTest");
431 
432 	suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
433 		"DateFormatTest::TestCustomFormat", &DateFormatTest::TestCustomFormat));
434 	suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
435 		"DateFormatTest::TestFormat", &DateFormatTest::TestFormat));
436 	suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
437 		"DateFormatTest::TestFormatDate", &DateFormatTest::TestFormatDate));
438 	suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
439 		"DateFormatTest::TestMonthNames", &DateFormatTest::TestMonthNames));
440 	suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
441 		"DateFormatTest::TestDayNames", &DateFormatTest::TestDayNames));
442 	suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
443 		"DateFormatTest::TestParseDate", &DateFormatTest::TestParseDate));
444 	suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
445 		"DateFormatTest::TestParseTime", &DateFormatTest::TestParseTime));
446 
447 	parent.addTest("DateFormatTest", &suite);
448 }
449