xref: /haiku/src/tests/kits/locale/DateFormatTest.cpp (revision c14bd9b2e7cf490db541587f22514659439aa8e9)
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