1#undef G_DISABLE_ASSERT
2#undef G_LOG_DOMAIN
3
4/* We are testing some deprecated APIs here */
5#ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
6#define GLIB_DISABLE_DEPRECATION_WARNINGS
7#endif
8
9#include "config.h"
10
11#include "glib.h"
12
13#include <stdio.h>
14#include <string.h>
15#include <stdlib.h>
16#include <locale.h>
17#include <time.h>
18
19#ifdef G_OS_WIN32
20#define WIN32_LEAN_AND_MEAN
21#include <windows.h>
22/* mingw defines it while msvc doesn't */
23#ifndef SUBLANG_LITHUANIAN_LITHUANIA
24#define SUBLANG_LITHUANIAN_LITHUANIA 0x01
25#endif
26#endif
27
28static void
29test_basic (void)
30{
31 g_assert_cmpint (sizeof (GDate), <, 9);
32 g_assert (!g_date_valid_month (G_DATE_BAD_MONTH));
33 g_assert (!g_date_valid_month (13));
34 g_assert (!g_date_valid_day (G_DATE_BAD_DAY));
35 g_assert (!g_date_valid_day (32));
36 g_assert (!g_date_valid_year (G_DATE_BAD_YEAR));
37 g_assert (!g_date_valid_julian (G_DATE_BAD_JULIAN));
38 g_assert (!g_date_valid_weekday (G_DATE_BAD_WEEKDAY));
39 g_assert (g_date_is_leap_year (2000));
40 g_assert (!g_date_is_leap_year (1999));
41 g_assert (g_date_is_leap_year (1996));
42 g_assert (g_date_is_leap_year (1600));
43 g_assert (!g_date_is_leap_year (2100));
44 g_assert (!g_date_is_leap_year (1800));
45}
46
47static void
48test_empty_constructor (void)
49{
50 GDate *d;
51
52 d = g_date_new ();
53 g_assert (!g_date_valid (d));
54 g_date_free (date: d);
55}
56
57static void
58test_dmy_constructor (void)
59{
60 GDate *d;
61 guint32 j;
62
63 d = g_date_new_dmy (day: 1, month: 1, year: 1);
64 g_assert (g_date_valid (d));
65 j = g_date_get_julian (date: d);
66 g_assert_cmpint (j, ==, 1);
67 g_assert_cmpint (g_date_get_month (d), ==, G_DATE_JANUARY);
68 g_assert_cmpint (g_date_get_day (d), ==, 1);
69 g_assert_cmpint (g_date_get_year (d), ==, 1);
70 g_date_free (date: d);
71}
72
73static void
74test_julian_constructor (void)
75{
76 GDate *d1;
77 GDate *d2;
78
79 d1 = g_date_new_julian (julian_day: 4000);
80 d2 = g_date_new_julian (julian_day: 5000);
81 g_assert_cmpint (g_date_get_julian (d1), ==, 4000);
82 g_assert_cmpint (g_date_days_between (d1, d2), ==, 1000);
83 g_assert_cmpint (g_date_get_year (d1), ==, 11);
84 g_assert_cmpint (g_date_get_day (d2), ==, 9);
85 g_date_free (date: d1);
86 g_date_free (date: d2);
87}
88
89static void
90test_dates (void)
91{
92 GDate *d;
93 GTimeVal tv;
94 time_t now;
95
96 d = g_date_new ();
97
98 /* today */
99 now = time (NULL);
100 g_assert_cmpint (now, !=, (time_t) -1);
101 g_date_set_time (date: d, time_: now);
102 g_assert (g_date_valid (d));
103
104 /* Unix epoch */
105 g_date_set_time (date: d, time_: 1);
106 g_assert (g_date_valid (d));
107
108 tv.tv_sec = 0;
109 tv.tv_usec = 0;
110 g_date_set_time_val (date: d, timeval: &tv);
111 g_assert (g_date_valid (d));
112
113 /* Julian day 1 */
114 g_date_set_julian (date: d, julian_date: 1);
115 g_assert (g_date_valid (d));
116
117 g_date_set_year (date: d, year: 3);
118 g_date_set_day (date: d, day: 3);
119 g_date_set_month (date: d, month: 3);
120 g_assert (g_date_valid (d));
121 g_assert_cmpint (g_date_get_year (d), ==, 3);
122 g_assert_cmpint (g_date_get_month (d), ==, 3);
123 g_assert_cmpint (g_date_get_day (d), ==, 3);
124 g_assert (!g_date_is_first_of_month (d));
125 g_assert (!g_date_is_last_of_month (d));
126 g_date_set_day (date: d, day: 1);
127 g_assert (g_date_is_first_of_month (d));
128 g_date_subtract_days (date: d, n_days: 1);
129 g_assert (g_date_is_last_of_month (d));
130
131 g_date_free (date: d);
132}
133
134static void
135test_parse (void)
136{
137 GDate *d;
138 gchar buf[101];
139
140 d = g_date_new ();
141
142 g_date_set_dmy (date: d, day: 10, month: 1, y: 2000);
143 g_date_strftime (s: buf, slen: 100, format: "%x", date: d);
144
145 g_date_set_parse (date: d, str: buf);
146 g_assert (g_date_valid (d));
147 g_assert_cmpint (g_date_get_month (d), ==, 1);
148 g_assert_cmpint (g_date_get_day (d), ==, 10);
149 g_assert_cmpint (g_date_get_year (d), ==, 2000);
150
151 g_date_set_parse (date: d, str: "2001 10 1");
152 g_assert (g_date_valid (d));
153 g_assert_cmpint (g_date_get_month (d), ==, 10);
154 g_assert_cmpint (g_date_get_day (d), ==, 1);
155 g_assert_cmpint (g_date_get_year (d), ==, 2001);
156
157 g_date_set_parse (date: d, str: "2001 10");
158 g_assert (!g_date_valid (d));
159
160 g_date_set_parse (date: d, str: "2001 10 1 1");
161 g_assert (!g_date_valid (d));
162
163 g_date_set_parse (date: d, str: "March 1999");
164 g_assert (g_date_valid (d));
165 g_assert_cmpint (g_date_get_month (d), ==, 3);
166 g_assert_cmpint (g_date_get_day (d), ==, 1);
167 g_assert_cmpint (g_date_get_year (d), ==, 1999);
168
169 g_date_set_parse (date: d, str: "10 Sep 1087");
170 g_assert (g_date_valid (d));
171 g_assert_cmpint (g_date_get_month (d), ==, 9);
172 g_assert_cmpint (g_date_get_day (d), ==, 10);
173 g_assert_cmpint (g_date_get_year (d), ==, 1087);
174
175 g_date_set_parse (date: d, str: "19990301");
176 g_assert (g_date_valid (d));
177 g_assert_cmpint (g_date_get_month (d), ==, 3);
178 g_assert_cmpint (g_date_get_day (d), ==, 1);
179 g_assert_cmpint (g_date_get_year (d), ==, 1999);
180
181 g_date_set_parse (date: d, str: "20011320");
182 g_assert (!g_date_valid (d));
183
184 g_date_free (date: d);
185}
186
187static void
188test_parse_invalid (void)
189{
190 const gchar * const strs[] =
191 {
192 /* Incomplete UTF-8 sequence */
193 "\xfd",
194 /* Ridiculously long input */
195 "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
196 "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
197 "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
198 };
199 gsize i;
200
201 for (i = 0; i < G_N_ELEMENTS (strs); i++)
202 {
203 GDate *d = g_date_new ();
204
205 g_test_message (format: "Test %" G_GSIZE_FORMAT, i);
206 g_date_set_parse (date: d, str: strs[i]);
207
208 g_assert_false (g_date_valid (d));
209
210 g_date_free (date: d);
211 }
212}
213
214static void
215test_parse_locale_change (void)
216{
217 /* Checks that g_date_set_parse correctly changes locale specific data as
218 * necessary. In this particular case year adjustment, as Thai calendar is
219 * 543 years ahead of the Gregorian calendar. */
220
221 GDate date;
222
223 if (setlocale (LC_ALL, locale: "th_TH") == NULL)
224 {
225 g_test_skip (msg: "locale th_TH not available");
226 return;
227 }
228
229 g_date_set_parse (date: &date, str: "04/07/2519");
230
231 setlocale (LC_ALL, locale: "C");
232 g_date_set_parse (date: &date, str: "07/04/76");
233 g_assert_cmpint (g_date_get_day (&date), ==, 4);
234 g_assert_cmpint (g_date_get_month (&date), ==, 7);
235 g_assert_cmpint (g_date_get_year (&date), ==, 1976);
236
237 setlocale (LC_ALL, locale: "");
238}
239
240static void
241test_month_substring (void)
242{
243 GDate date;
244
245 g_test_bug (bug_uri_snippet: "793550");
246
247 if (setlocale (LC_ALL, locale: "pl_PL") == NULL)
248 {
249 g_test_skip (msg: "pl_PL locale not available");
250 return;
251 }
252
253 /* In Polish language September is "wrzesień" and August is "sierpień"
254 * abbreviated as "sie". The former used to be confused with the latter
255 * because "sie" is a substring of "wrzesień" and was matched first. */
256
257 g_date_set_parse (date: &date, str: "wrzesień 2018");
258 g_assert_true (g_date_valid (&date));
259 g_assert_cmpint (g_date_get_month (&date), ==, G_DATE_SEPTEMBER);
260
261 g_date_set_parse (date: &date, str: "sie 2018");
262 g_assert_true (g_date_valid (&date));
263 g_assert_cmpint (g_date_get_month (&date), ==, G_DATE_AUGUST);
264
265 g_date_set_parse (date: &date, str: "sierpień 2018");
266 g_assert_true (g_date_valid (&date));
267 g_assert_cmpint (g_date_get_month (&date), ==, G_DATE_AUGUST);
268
269 setlocale (LC_ALL, locale: "");
270}
271
272
273static void
274test_month_names (void)
275{
276#if defined(HAVE_LANGINFO_ABALTMON) || defined(G_OS_WIN32)
277 GDate *gdate;
278 gchar buf[101];
279 gchar *oldlocale;
280#ifdef G_OS_WIN32
281 LCID old_lcid;
282#endif
283#endif /* defined(HAVE_LANGINFO_ABALTMON) || defined(G_OS_WIN32) */
284
285 g_test_bug (bug_uri_snippet: "749206");
286
287 /* If running uninstalled (G_TEST_BUILDDIR is set), skip this test, since we
288 * need the translations to be installed. We can’t mess around with
289 * bindtextdomain() here, as the compiled .gmo files in po/ are not in the
290 * right installed directory hierarchy to be successfully loaded by gettext. */
291 if (g_getenv (variable: "G_TEST_BUILDDIR") != NULL)
292 {
293 g_test_skip (msg: "Skipping due to running uninstalled. "
294 "This test can only be run when the translations are installed.");
295 return;
296 }
297
298 /* This test can only work (on non-Windows platforms) if libc supports
299 * the %OB (etc.) format placeholders. If it doesn’t, strftime() (and hence
300 * g_date_strftime()) will return the placeholder unsubstituted.
301 * g_date_strftime() explicitly documents that it doesn’t provide any more
302 * format placeholders than the system strftime(), so we should skip the test
303 * in that case. If people need %OB support, they should depend on a suitable
304 * version of libc, or use g_date_time_format(). Note: a test for a support
305 * of _NL_ABALTMON_* is not strictly the same as checking for %OB support.
306 * Some platforms (BSD, OS X) support %OB while _NL_ABALTMON_* and %Ob
307 * are supported only by glibc 2.27 and newer. But we don’t care about BSD
308 * here, the aim of this test is to make sure that our custom implementation
309 * for Windows works the same as glibc 2.27 native implementation. */
310#if !defined(HAVE_LANGINFO_ABALTMON) && !defined(G_OS_WIN32)
311 g_test_skip ("libc doesn’t support all alternative month names");
312#else
313
314#define TEST_DATE(d,m,y,f,o) G_STMT_START { \
315 gchar *o_casefold, *buf_casefold; \
316 g_date_set_dmy (gdate, d, m, y); \
317 g_date_strftime (buf, 100, f, gdate); \
318 buf_casefold = g_utf8_casefold (buf, -1); \
319 o_casefold = g_utf8_casefold ((o), -1); \
320 g_assert_cmpstr (buf_casefold, ==, o_casefold); \
321 g_free (buf_casefold); \
322 g_free (o_casefold); \
323 g_date_set_parse (gdate, buf); \
324 g_assert (g_date_valid (gdate)); \
325 g_assert_cmpint (g_date_get_day (gdate), ==, d); \
326 g_assert_cmpint (g_date_get_month (gdate), ==, m); \
327 g_assert_cmpint (g_date_get_year (gdate), ==, y); \
328} G_STMT_END
329
330 oldlocale = g_strdup (str: setlocale (LC_ALL, NULL));
331#ifdef G_OS_WIN32
332 old_lcid = GetThreadLocale ();
333#endif
334
335 gdate = g_date_new ();
336
337 /* Note: Windows implementation of g_date_strftime() does not support
338 * "-" format modifier (e.g., "%-d", "%-e") so we will not use it.
339 */
340
341 /* Make sure that nothing has been changed in western European languages. */
342 setlocale (LC_ALL, locale: "en_GB.utf-8");
343#ifdef G_OS_WIN32
344 SetThreadLocale (MAKELCID (MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_UK), SORT_DEFAULT));
345#endif
346 if (strstr (haystack: setlocale (LC_ALL, NULL), needle: "en_GB") != NULL)
347 {
348 TEST_DATE (1, 1, 2018, "%B %d, %Y", "January 01, 2018");
349 TEST_DATE (1, 2, 2018, "%OB %Y", "February 2018");
350 TEST_DATE (1, 3, 2018, "%e %b %Y", " 1 Mar 2018");
351 TEST_DATE (1, 4, 2018, "%Ob %Y", "Apr 2018");
352 TEST_DATE (1, 5, 2018, "%d %h %Y", "01 May 2018");
353 TEST_DATE (1, 6, 2018, "%Oh %Y", "Jun 2018");
354 }
355 else
356 g_test_skip (msg: "locale en_GB not available, skipping English month names test");
357
358 setlocale (LC_ALL, locale: "de_DE.utf-8");
359#ifdef G_OS_WIN32
360 SetThreadLocale (MAKELCID (MAKELANGID (LANG_GERMAN, SUBLANG_GERMAN), SORT_DEFAULT));
361#endif
362 if (strstr (haystack: setlocale (LC_ALL, NULL), needle: "de_DE") != NULL)
363 {
364 TEST_DATE (16, 7, 2018, "%d. %B %Y", "16. Juli 2018");
365 TEST_DATE ( 1, 8, 2018, "%OB %Y", "August 2018");
366 TEST_DATE (18, 9, 2018, "%e. %b %Y", "18. Sep 2018");
367 TEST_DATE ( 1, 10, 2018, "%Ob %Y", "Okt 2018");
368 TEST_DATE (20, 11, 2018, "%d. %h %Y", "20. Nov 2018");
369 TEST_DATE ( 1, 12, 2018, "%Oh %Y", "Dez 2018");
370 }
371 else
372 g_test_skip (msg: "locale de_DE not available, skipping German month names test");
373
374
375 setlocale (LC_ALL, locale: "es_ES.utf-8");
376#ifdef G_OS_WIN32
377 SetThreadLocale (MAKELCID (MAKELANGID (LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT));
378#endif
379 if (strstr (haystack: setlocale (LC_ALL, NULL), needle: "es_ES") != NULL)
380 {
381 TEST_DATE ( 9, 1, 2018, "%d de %B de %Y", "09 de enero de 2018");
382 TEST_DATE ( 1, 2, 2018, "%OB de %Y", "febrero de 2018");
383 TEST_DATE (10, 3, 2018, "%e de %b de %Y", "10 de mar de 2018");
384 TEST_DATE ( 1, 4, 2018, "%Ob de %Y", "abr de 2018");
385 TEST_DATE (11, 5, 2018, "%d de %h de %Y", "11 de may de 2018");
386 TEST_DATE ( 1, 6, 2018, "%Oh de %Y", "jun de 2018");
387 }
388 else
389 g_test_skip (msg: "locale es_ES not available, skipping Spanish month names test");
390
391 setlocale (LC_ALL, locale: "fr_FR.utf-8");
392#ifdef G_OS_WIN32
393 SetThreadLocale (MAKELCID (MAKELANGID (LANG_FRENCH, SUBLANG_FRENCH), SORT_DEFAULT));
394#endif
395 if (strstr (haystack: setlocale (LC_ALL, NULL), needle: "fr_FR") != NULL)
396 {
397 TEST_DATE (31, 7, 2018, "%d %B %Y", "31 juillet 2018");
398 TEST_DATE ( 1, 8, 2018, "%OB %Y", "août 2018");
399 TEST_DATE (30, 9, 2018, "%e %b %Y", "30 sept. 2018");
400 TEST_DATE ( 1, 10, 2018, "%Ob %Y", "oct. 2018");
401 TEST_DATE (29, 11, 2018, "%d %h %Y", "29 nov. 2018");
402 TEST_DATE ( 1, 12, 2018, "%Oh %Y", "déc. 2018");
403 }
404 else
405 g_test_skip (msg: "locale fr_FR not available, skipping French month names test");
406
407 /* Make sure that there are visible changes in some European languages. */
408 setlocale (LC_ALL, locale: "el_GR.utf-8");
409#ifdef G_OS_WIN32
410 SetThreadLocale (MAKELCID (MAKELANGID (LANG_GREEK, SUBLANG_GREEK_GREECE), SORT_DEFAULT));
411#endif
412 if (strstr (haystack: setlocale (LC_ALL, NULL), needle: "el_GR") != NULL)
413 {
414 TEST_DATE ( 2, 1, 2018, "%d %B %Y", "02 Ιανουαρίου 2018");
415 TEST_DATE ( 4, 2, 2018, "%e %B %Y", " 4 Φεβρουαρίου 2018");
416 TEST_DATE (15, 3, 2018, "%d %B %Y", "15 Μαρτίου 2018");
417 TEST_DATE ( 1, 4, 2018, "%OB %Y", "Απρίλιος 2018");
418 TEST_DATE ( 1, 5, 2018, "%OB %Y", "Μάιος 2018");
419 TEST_DATE ( 1, 6, 2018, "%OB %Y", "Ιούνιος 2018");
420 TEST_DATE (16, 7, 2018, "%e %b %Y", "16 Ιουλ 2018");
421 TEST_DATE ( 1, 8, 2018, "%Ob %Y", "Αύγ 2018");
422 }
423 else
424 g_test_skip (msg: "locale el_GR not available, skipping Greek month names test");
425
426 setlocale (LC_ALL, locale: "hr_HR.utf-8");
427#ifdef G_OS_WIN32
428 SetThreadLocale (MAKELCID (MAKELANGID (LANG_CROATIAN, SUBLANG_CROATIAN_CROATIA), SORT_DEFAULT));
429#endif
430 if (strstr (haystack: setlocale (LC_ALL, NULL), needle: "hr_HR") != NULL)
431 {
432 TEST_DATE ( 8, 5, 2018, "%d. %B %Y", "08. svibnja 2018");
433 TEST_DATE ( 9, 6, 2018, "%e. %B %Y", " 9. lipnja 2018");
434 TEST_DATE (10, 7, 2018, "%d. %B %Y", "10. srpnja 2018");
435 TEST_DATE ( 1, 8, 2018, "%OB %Y", "Kolovoz 2018");
436 TEST_DATE ( 1, 9, 2018, "%OB %Y", "Rujan 2018");
437 TEST_DATE ( 1, 10, 2018, "%OB %Y", "Listopad 2018");
438 TEST_DATE (11, 11, 2018, "%e. %b %Y", "11. Stu 2018");
439 TEST_DATE ( 1, 12, 2018, "%Ob %Y", "Pro 2018");
440 }
441 else
442 g_test_skip (msg: "locale hr_HR not available, skipping Croatian month names test");
443
444 setlocale (LC_ALL, locale: "lt_LT.utf-8");
445#ifdef G_OS_WIN32
446 SetThreadLocale (MAKELCID (MAKELANGID (LANG_LITHUANIAN, SUBLANG_LITHUANIAN_LITHUANIA), SORT_DEFAULT));
447#endif
448 if (strstr (haystack: setlocale (LC_ALL, NULL), needle: "lt_LT") != NULL)
449 {
450 TEST_DATE ( 1, 1, 2018, "%Y m. %B %d d.", "2018 m. sausio 01 d.");
451 TEST_DATE ( 2, 2, 2018, "%Y m. %B %e d.", "2018 m. vasario 2 d.");
452 TEST_DATE ( 3, 3, 2018, "%Y m. %B %d d.", "2018 m. kovo 03 d.");
453 TEST_DATE ( 1, 4, 2018, "%Y m. %OB", "2018 m. balandis");
454 TEST_DATE ( 1, 5, 2018, "%Y m. %OB", "2018 m. gegužė");
455 TEST_DATE ( 1, 6, 2018, "%Y m. %OB", "2018 m. birželis");
456 TEST_DATE (17, 7, 2018, "%Y m. %b %e d.", "2018 m. liep. 17 d.");
457 TEST_DATE ( 1, 8, 2018, "%Y m. %Ob", "2018 m. rugp.");
458 }
459 else
460 g_test_skip (msg: "locale lt_LT not available, skipping Lithuanian month names test");
461
462 setlocale (LC_ALL, locale: "pl_PL.utf-8");
463#ifdef G_OS_WIN32
464 SetThreadLocale (MAKELCID (MAKELANGID (LANG_POLISH, SUBLANG_POLISH_POLAND), SORT_DEFAULT));
465#endif
466 if (strstr (haystack: setlocale (LC_ALL, NULL), needle: "pl_PL") != NULL)
467 {
468 TEST_DATE ( 3, 5, 2018, "%d %B %Y", "03 maja 2018");
469 TEST_DATE ( 4, 6, 2018, "%e %B %Y", " 4 czerwca 2018");
470 TEST_DATE (20, 7, 2018, "%d %B %Y", "20 lipca 2018");
471 TEST_DATE ( 1, 8, 2018, "%OB %Y", "sierpień 2018");
472 TEST_DATE ( 1, 9, 2018, "%OB %Y", "wrzesień 2018");
473 TEST_DATE ( 1, 10, 2018, "%OB %Y", "październik 2018");
474 TEST_DATE (25, 11, 2018, "%e %b %Y", "25 lis 2018");
475 TEST_DATE ( 1, 12, 2018, "%Ob %Y", "gru 2018");
476 }
477 else
478 g_test_skip (msg: "locale pl_PL not available, skipping Polish month names test");
479
480 setlocale (LC_ALL, locale: "ru_RU.utf-8");
481#ifdef G_OS_WIN32
482 SetThreadLocale (MAKELCID (MAKELANGID (LANG_RUSSIAN, SUBLANG_RUSSIAN_RUSSIA), SORT_DEFAULT));
483#endif
484 if (strstr (haystack: setlocale (LC_ALL, NULL), needle: "ru_RU") != NULL)
485 {
486 TEST_DATE ( 3, 1, 2018, "%d %B %Y", "03 января 2018");
487 TEST_DATE ( 4, 2, 2018, "%e %B %Y", " 4 февраля 2018");
488 TEST_DATE (23, 3, 2018, "%d %B %Y", "23 марта 2018");
489 TEST_DATE ( 1, 4, 2018, "%OB %Y", "Апрель 2018");
490 TEST_DATE ( 1, 5, 2018, "%OB %Y", "Май 2018");
491 TEST_DATE ( 1, 6, 2018, "%OB %Y", "Июнь 2018");
492 TEST_DATE (24, 7, 2018, "%e %b %Y", "24 июл 2018");
493 TEST_DATE ( 1, 8, 2018, "%Ob %Y", "авг 2018");
494 /* This difference is very important in Russian: */
495 TEST_DATE (19, 5, 2018, "%e %b %Y", "19 мая 2018");
496 TEST_DATE (20, 5, 2018, "%Ob, %d-е, %Y", "май, 20-е, 2018");
497 }
498 else
499 g_test_skip (msg: "locale ru_RU not available, skipping Russian month names test");
500
501 g_date_free (date: gdate);
502
503 setlocale (LC_ALL, locale: oldlocale);
504#ifdef G_OS_WIN32
505 SetThreadLocale (old_lcid);
506#endif
507 g_free (mem: oldlocale);
508#endif /* defined(HAVE_LANGINFO_ABALTMON) || defined(G_OS_WIN32) */
509}
510
511static void
512test_year (gconstpointer t)
513{
514 GDateYear y = GPOINTER_TO_INT (t);
515 GDateMonth m;
516 GDateDay day;
517 guint32 j;
518 GDate *d;
519 gint i;
520 GDate tmp;
521
522 guint32 first_day_of_year = G_DATE_BAD_JULIAN;
523 guint16 days_in_year = g_date_is_leap_year (year: y) ? 366 : 365;
524 guint sunday_week_of_year = 0;
525 guint sunday_weeks_in_year = g_date_get_sunday_weeks_in_year (year: y);
526 guint monday_week_of_year = 0;
527 guint monday_weeks_in_year = g_date_get_monday_weeks_in_year (year: y);
528 guint iso8601_week_of_year = 0;
529
530 g_assert (g_date_valid_year (y));
531 /* Years ought to have roundabout 52 weeks */
532 g_assert (sunday_weeks_in_year == 52 || sunday_weeks_in_year == 53);
533 g_assert (monday_weeks_in_year == 52 || monday_weeks_in_year == 53);
534
535 m = 1;
536 while (m < 13)
537 {
538 guint8 dim = g_date_get_days_in_month (month: m, year: y);
539 GDate days[31];
540
541 g_date_clear (date: days, n_dates: 31);
542
543 g_assert (dim > 0 && dim < 32);
544 g_assert (g_date_valid_month (m));
545
546 day = 1;
547 while (day <= dim)
548 {
549 g_assert (g_date_valid_dmy (day, m, y));
550
551 d = &days[day - 1];
552 //g_assert (!g_date_valid (d));
553
554 g_date_set_dmy (date: d, day, month: m, y);
555
556 g_assert (g_date_valid (d));
557
558 if (m == G_DATE_JANUARY && day == 1)
559 first_day_of_year = g_date_get_julian (date: d);
560
561 g_assert (first_day_of_year != G_DATE_BAD_JULIAN);
562
563 g_assert_cmpint (g_date_get_month (d), ==, m);
564 g_assert_cmpint (g_date_get_year (d), ==, y);
565 g_assert_cmpint (g_date_get_day (d), ==, day);
566
567 g_assert (g_date_get_julian (d) + 1 - first_day_of_year ==
568 g_date_get_day_of_year (d));
569
570 if (m == G_DATE_DECEMBER && day == 31)
571 g_assert_cmpint (g_date_get_day_of_year (d), ==, days_in_year);
572
573 g_assert_cmpint (g_date_get_day_of_year (d), <=, days_in_year);
574 g_assert_cmpint (g_date_get_monday_week_of_year (d), <=, monday_weeks_in_year);
575 g_assert_cmpint (g_date_get_monday_week_of_year (d), >=, monday_week_of_year);
576
577 if (g_date_get_weekday(date: d) == G_DATE_MONDAY)
578 {
579 g_assert_cmpint (g_date_get_monday_week_of_year (d) - monday_week_of_year, ==, 1);
580 if ((m == G_DATE_JANUARY && day <= 4) ||
581 (m == G_DATE_DECEMBER && day >= 29))
582 g_assert_cmpint (g_date_get_iso8601_week_of_year (d), ==, 1);
583 else
584 g_assert_cmpint (g_date_get_iso8601_week_of_year (d) - iso8601_week_of_year, ==, 1);
585 }
586 else
587 {
588 g_assert_cmpint (g_date_get_monday_week_of_year(d) - monday_week_of_year, ==, 0);
589 if (!(day == 1 && m == G_DATE_JANUARY))
590 g_assert_cmpint (g_date_get_iso8601_week_of_year(d) - iso8601_week_of_year, ==, 0);
591 }
592
593 monday_week_of_year = g_date_get_monday_week_of_year (date: d);
594 iso8601_week_of_year = g_date_get_iso8601_week_of_year (date: d);
595
596 g_assert_cmpint (g_date_get_sunday_week_of_year (d), <=, sunday_weeks_in_year);
597 g_assert_cmpint (g_date_get_sunday_week_of_year (d), >=, sunday_week_of_year);
598 if (g_date_get_weekday(date: d) == G_DATE_SUNDAY)
599 g_assert_cmpint (g_date_get_sunday_week_of_year (d) - sunday_week_of_year, ==, 1);
600 else
601 g_assert_cmpint (g_date_get_sunday_week_of_year (d) - sunday_week_of_year, ==, 0);
602
603 sunday_week_of_year = g_date_get_sunday_week_of_year (date: d);
604
605 g_assert_cmpint (g_date_compare (d, d), ==, 0);
606
607 i = 1;
608 while (i < 402) /* Need to get 400 year increments in */
609 {
610 tmp = *d;
611 g_date_add_days (date: d, n_days: i);
612 g_assert_cmpint (g_date_compare (d, &tmp), >, 0);
613 g_date_subtract_days (date: d, n_days: i);
614 g_assert_cmpint (g_date_get_day (d), ==, day);
615 g_assert_cmpint (g_date_get_month (d), ==, m);
616 g_assert_cmpint (g_date_get_year (d), ==, y);
617
618 tmp = *d;
619 g_date_add_months (date: d, n_months: i);
620 g_assert_cmpint (g_date_compare (d, &tmp), >, 0);
621 g_date_subtract_months (date: d, n_months: i);
622 g_assert_cmpint (g_date_get_month (d), ==, m);
623 g_assert_cmpint (g_date_get_year (d), ==, y);
624
625 if (day < 29)
626 g_assert_cmpint (g_date_get_day (d), ==, day);
627 else
628 g_date_set_day (date: d, day);
629
630 tmp = *d;
631 g_date_add_years (date: d, n_years: i);
632 g_assert_cmpint (g_date_compare (d, &tmp), >, 0);
633 g_date_subtract_years (date: d, n_years: i);
634 g_assert_cmpint (g_date_get_month (d), ==, m);
635 g_assert_cmpint (g_date_get_year (d), ==, y);
636
637 if (m != 2 && day != 29)
638 g_assert_cmpint (g_date_get_day (d), ==, day);
639 else
640 g_date_set_day (date: d, day); /* reset */
641
642 i += 10;
643 }
644
645 j = g_date_get_julian (date: d);
646
647 ++day;
648 }
649 ++m;
650 }
651
652 /* at this point, d is the last day of year y */
653 g_date_set_dmy (date: &tmp, day: 1, month: 1, y: y + 1);
654 g_assert_cmpint (j + 1, ==, g_date_get_julian (&tmp));
655
656 g_date_add_days (date: &tmp, n_days: 1);
657 g_assert_cmpint (j + 2, ==, g_date_get_julian (&tmp));
658}
659
660static void
661test_clamp (void)
662{
663 GDate d1, d2, d, o;
664
665 g_date_set_dmy (date: &d1, day: 1, month: 1, y: 1970);
666 g_date_set_dmy (date: &d2, day: 1, month: 1, y: 1980);
667 g_date_set_dmy (date: &d, day: 1, month: 1, y: 1);
668
669 o = d;
670 g_date_clamp (date: &o, NULL, NULL);
671 g_assert (g_date_compare (&o, &d) == 0);
672
673 g_date_clamp (date: &o, min_date: &d1, max_date: &d2);
674 g_assert (g_date_compare (&o, &d1) == 0);
675
676 g_date_set_dmy (date: &o, day: 1, month: 1, y: 2000);
677
678 g_date_clamp (date: &o, min_date: &d1, max_date: &d2);
679 g_assert (g_date_compare (&o, &d2) == 0);
680}
681
682static void
683test_order (void)
684{
685 GDate d1, d2;
686
687 g_date_set_dmy (date: &d1, day: 1, month: 1, y: 1970);
688 g_date_set_dmy (date: &d2, day: 1, month: 1, y: 1980);
689
690 g_assert (g_date_compare (&d1, &d2) == -1);
691 g_date_order (date1: &d2, date2: &d1);
692 g_assert (g_date_compare (&d1, &d2) == 1);
693}
694
695static void
696test_copy (void)
697{
698 GDate *d;
699 GDate *c;
700
701 d = g_date_new ();
702 g_assert_false (g_date_valid (d));
703
704 c = g_date_copy (date: d);
705 g_assert_nonnull (c);
706 g_assert_false (g_date_valid (c));
707 g_date_free (date: c);
708
709 g_date_set_day (date: d, day: 10);
710
711 c = g_date_copy (date: d);
712 g_date_set_month (date: c, month: 1);
713 g_date_set_year (date: c, year: 2015);
714 g_assert_true (g_date_valid (c));
715 g_assert_cmpuint (g_date_get_day (c), ==, 10);
716 g_date_free (date: c);
717
718 g_date_free (date: d);
719}
720
721/* Check the results of g_date_valid_dmy() for various inputs. */
722static void
723test_valid_dmy (void)
724{
725 const struct
726 {
727 GDateDay day;
728 GDateMonth month;
729 GDateYear year;
730 gboolean expected_valid;
731 }
732 vectors[] =
733 {
734 /* Lower bounds */
735 { 0, 0, 0, FALSE },
736 { 1, 1, 1, TRUE },
737 { 1, 1, 0, FALSE },
738 /* Leap year month lengths */
739 { 30, 2, 2000, FALSE },
740 { 29, 2, 2000, TRUE },
741 { 29, 2, 2001, FALSE },
742 /* Maximum year */
743 { 1, 1, G_MAXUINT16, TRUE },
744 };
745 gsize i;
746
747 for (i = 0; i < G_N_ELEMENTS (vectors); i++)
748 {
749 gboolean valid;
750 g_test_message (format: "Vector %" G_GSIZE_FORMAT ": %04u-%02u-%02u, %s",
751 i, vectors[i].year, vectors[i].month, vectors[i].day,
752 vectors[i].expected_valid ? "valid" : "invalid");
753
754 valid = g_date_valid_dmy (day: vectors[i].day, month: vectors[i].month, year: vectors[i].year);
755
756 if (vectors[i].expected_valid)
757 g_assert_true (valid);
758 else
759 g_assert_false (valid);
760 }
761}
762
763int
764main (int argc, char** argv)
765{
766 gchar *path;
767 gsize i;
768
769 /* Try to get all the leap year cases. */
770 int check_years[] = {
771 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
772 11, 12, 13, 14, 98, 99, 100, 101, 102, 103, 397,
773 398, 399, 400, 401, 402, 403, 404, 405, 406,
774 1598, 1599, 1600, 1601, 1602, 1650, 1651,
775 1897, 1898, 1899, 1900, 1901, 1902, 1903,
776 1961, 1962, 1963, 1964, 1965, 1967,
777 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976,
778 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985,
779 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
780 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
781 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012,
782 3000, 3001, 3002, 3998, 3999, 4000, 4001, 4002, 4003
783 };
784
785 g_setenv (variable: "LC_ALL", value: "en_US.utf-8", TRUE);
786 setlocale (LC_ALL, locale: "");
787#ifdef G_OS_WIN32
788 SetThreadLocale (MAKELCID (MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT));
789#endif
790
791 g_test_init (argc: &argc, argv: &argv, NULL);
792 g_test_bug_base (uri_pattern: "http://bugzilla.gnome.org/");
793
794 g_test_add_func (testpath: "/date/basic", test_func: test_basic);
795 g_test_add_func (testpath: "/date/empty", test_func: test_empty_constructor);
796 g_test_add_func (testpath: "/date/dmy", test_func: test_dmy_constructor);
797 g_test_add_func (testpath: "/date/julian", test_func: test_julian_constructor);
798 g_test_add_func (testpath: "/date/dates", test_func: test_dates);
799 g_test_add_func (testpath: "/date/parse", test_func: test_parse);
800 g_test_add_func (testpath: "/date/parse/invalid", test_func: test_parse_invalid);
801 g_test_add_func (testpath: "/date/parse_locale_change", test_func: test_parse_locale_change);
802 g_test_add_func (testpath: "/date/month_substring", test_func: test_month_substring);
803 g_test_add_func (testpath: "/date/month_names", test_func: test_month_names);
804 g_test_add_func (testpath: "/date/clamp", test_func: test_clamp);
805 g_test_add_func (testpath: "/date/order", test_func: test_order);
806 for (i = 0; i < G_N_ELEMENTS (check_years); i++)
807 {
808 path = g_strdup_printf (format: "/date/year/%d", check_years[i]);
809 g_test_add_data_func (testpath: path, GINT_TO_POINTER(check_years[i]), test_func: test_year);
810 g_free (mem: path);
811 }
812 g_test_add_func (testpath: "/date/copy", test_func: test_copy);
813 g_test_add_func (testpath: "/date/valid-dmy", test_func: test_valid_dmy);
814
815 return g_test_run ();
816}
817

source code of gtk/subprojects/glib/glib/tests/date.c