glib/tests: fix memory leak
[platform/upstream/glib.git] / glib / tests / gdatetime.c
1 /* gdatetime-tests.c
2  *
3  * Copyright (C) 2009-2010 Christian Hergert <chris@dronelabs.com>
4  *
5  * This is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 #include "config.h"
21
22 #include <string.h>
23 #include <time.h>
24 #include <glib.h>
25 #include <glib/gstdio.h>
26 #include <locale.h>
27
28 #define ASSERT_DATE(dt,y,m,d) G_STMT_START { \
29   g_assert_cmpint ((y), ==, g_date_time_get_year ((dt))); \
30   g_assert_cmpint ((m), ==, g_date_time_get_month ((dt))); \
31   g_assert_cmpint ((d), ==, g_date_time_get_day_of_month ((dt))); \
32 } G_STMT_END
33 #define ASSERT_TIME(dt,H,M,S) G_STMT_START { \
34   g_assert_cmpint ((H), ==, g_date_time_get_hour ((dt))); \
35   g_assert_cmpint ((M), ==, g_date_time_get_minute ((dt))); \
36   g_assert_cmpint ((S), ==, g_date_time_get_second ((dt))); \
37 } G_STMT_END
38
39 static void
40 get_localtime_tm (time_t     time_,
41                   struct tm *retval)
42 {
43 #ifdef HAVE_LOCALTIME_R
44   localtime_r (&time_, retval);
45 #else
46   {
47     struct tm *ptm = localtime (&time_);
48
49     if (ptm == NULL)
50       {
51         /* Happens at least in Microsoft's C library if you pass a
52          * negative time_t. Use 2000-01-01 as default date.
53          */
54 #ifndef G_DISABLE_CHECKS
55         g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, "ptm != NULL");
56 #endif
57
58         retval->tm_mon = 0;
59         retval->tm_mday = 1;
60         retval->tm_year = 100;
61       }
62     else
63       memcpy ((void *) retval, (void *) ptm, sizeof (struct tm));
64   }
65 #endif /* HAVE_LOCALTIME_R */
66 }
67
68 static void
69 test_GDateTime_now (void)
70 {
71   GDateTime *dt;
72   struct tm tm;
73
74   memset (&tm, 0, sizeof (tm));
75   get_localtime_tm (time (NULL), &tm);
76
77   dt = g_date_time_new_now_local ();
78
79   g_assert_cmpint (g_date_time_get_year (dt), ==, 1900 + tm.tm_year);
80   g_assert_cmpint (g_date_time_get_month (dt), ==, 1 + tm.tm_mon);
81   g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, tm.tm_mday);
82   g_assert_cmpint (g_date_time_get_hour (dt), ==, tm.tm_hour);
83   g_assert_cmpint (g_date_time_get_minute (dt), ==, tm.tm_min);
84   /* XXX we need some fuzzyness here */
85   g_assert_cmpint (g_date_time_get_second (dt), >=, tm.tm_sec);
86
87   g_date_time_unref (dt);
88 }
89
90 static void
91 test_GDateTime_new_from_unix (void)
92 {
93   GDateTime *dt;
94   struct tm  tm;
95   time_t     t;
96
97   memset (&tm, 0, sizeof (tm));
98   t = time (NULL);
99   get_localtime_tm (t, &tm);
100
101   dt = g_date_time_new_from_unix_local (t);
102   g_assert_cmpint (g_date_time_get_year (dt), ==, 1900 + tm.tm_year);
103   g_assert_cmpint (g_date_time_get_month (dt), ==, 1 + tm.tm_mon);
104   g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, tm.tm_mday);
105   g_assert_cmpint (g_date_time_get_hour (dt), ==, tm.tm_hour);
106   g_assert_cmpint (g_date_time_get_minute (dt), ==, tm.tm_min);
107   g_assert_cmpint (g_date_time_get_second (dt), ==, tm.tm_sec);
108   g_date_time_unref (dt);
109
110   memset (&tm, 0, sizeof (tm));
111   tm.tm_year = 90;
112   tm.tm_mday = 1;
113   tm.tm_mon = 0;
114   tm.tm_hour = 0;
115   tm.tm_min = 0;
116   tm.tm_sec = 0;
117   t = mktime (&tm);
118
119   dt = g_date_time_new_from_unix_local (t);
120   g_assert_cmpint (g_date_time_get_year (dt), ==, 1990);
121   g_assert_cmpint (g_date_time_get_month (dt), ==, 1);
122   g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, 1);
123   g_assert_cmpint (g_date_time_get_hour (dt), ==, 0);
124   g_assert_cmpint (g_date_time_get_minute (dt), ==, 0);
125   g_assert_cmpint (g_date_time_get_second (dt), ==, 0);
126   g_date_time_unref (dt);
127 }
128
129 static void
130 test_GDateTime_compare (void)
131 {
132   GDateTime *dt1, *dt2;
133   gint       i;
134
135   dt1 = g_date_time_new_utc (2000, 1, 1, 0, 0, 0);
136
137   for (i = 1; i < 2000; i++)
138     {
139       dt2 = g_date_time_new_utc (i, 12, 31, 0, 0, 0);
140       g_assert_cmpint (1, ==, g_date_time_compare (dt1, dt2));
141       g_date_time_unref (dt2);
142     }
143
144   dt2 = g_date_time_new_utc (1999, 12, 31, 23, 59, 59);
145   g_assert_cmpint (1, ==, g_date_time_compare (dt1, dt2));
146   g_date_time_unref (dt2);
147
148   dt2 = g_date_time_new_utc (2000, 1, 1, 0, 0, 1);
149   g_assert_cmpint (-1, ==, g_date_time_compare (dt1, dt2));
150   g_date_time_unref (dt2);
151
152   dt2 = g_date_time_new_utc (2000, 1, 1, 0, 0, 0);
153   g_assert_cmpint (0, ==, g_date_time_compare (dt1, dt2));
154   g_date_time_unref (dt2);
155   g_date_time_unref (dt1);
156 }
157
158 static void
159 test_GDateTime_equal (void)
160 {
161   GDateTime *dt1, *dt2;
162   GTimeZone *tz;
163
164   dt1 = g_date_time_new_local (2009, 10, 19, 0, 0, 0);
165   dt2 = g_date_time_new_local (2009, 10, 19, 0, 0, 0);
166   g_assert (g_date_time_equal (dt1, dt2));
167   g_date_time_unref (dt1);
168   g_date_time_unref (dt2);
169
170   dt1 = g_date_time_new_local (2009, 10, 18, 0, 0, 0);
171   dt2 = g_date_time_new_local (2009, 10, 19, 0, 0, 0);
172   g_assert (!g_date_time_equal (dt1, dt2));
173   g_date_time_unref (dt1);
174   g_date_time_unref (dt2);
175
176   /* UTC-0300 and not in DST */
177   tz = g_time_zone_new ("-03:00");
178   dt1 = g_date_time_new (tz, 2010, 5, 24,  8, 0, 0);
179   g_time_zone_unref (tz);
180   g_assert_cmpint (g_date_time_get_utc_offset (dt1) / G_USEC_PER_SEC, ==, (-3 * 3600));
181   /* UTC */
182   dt2 = g_date_time_new_utc (2010, 5, 24, 11, 0, 0);
183   g_assert_cmpint (g_date_time_get_utc_offset (dt2), ==, 0);
184
185   g_assert (g_date_time_equal (dt1, dt2));
186   g_date_time_unref (dt1);
187
188   /* America/Recife is in UTC-0300 */
189   tz = g_time_zone_new ("America/Recife");
190   dt1 = g_date_time_new (tz, 2010, 5, 24,  8, 0, 0);
191   g_time_zone_unref (tz);
192   g_assert_cmpint (g_date_time_get_utc_offset (dt1) / G_USEC_PER_SEC, ==, (-3 * 3600));
193   g_assert (g_date_time_equal (dt1, dt2));
194   g_date_time_unref (dt1);
195   g_date_time_unref (dt2);
196 }
197
198 static void
199 test_GDateTime_get_day_of_week (void)
200 {
201   GDateTime *dt;
202
203   dt = g_date_time_new_local (2009, 10, 19, 0, 0, 0);
204   g_assert_cmpint (1, ==, g_date_time_get_day_of_week (dt));
205   g_date_time_unref (dt);
206
207   dt = g_date_time_new_local (2000, 10, 1, 0, 0, 0);
208   g_assert_cmpint (7, ==, g_date_time_get_day_of_week (dt));
209   g_date_time_unref (dt);
210 }
211
212 static void
213 test_GDateTime_get_day_of_month (void)
214 {
215   GDateTime *dt;
216
217   dt = g_date_time_new_local (2009, 10, 19, 0, 0, 0);
218   g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, 19);
219   g_date_time_unref (dt);
220
221   dt = g_date_time_new_local (1400, 3, 12, 0, 0, 0);
222   g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, 12);
223   g_date_time_unref (dt);
224
225   dt = g_date_time_new_local (1800, 12, 31, 0, 0, 0);
226   g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, 31);
227   g_date_time_unref (dt);
228
229   dt = g_date_time_new_local (1000, 1, 1, 0, 0, 0);
230   g_assert_cmpint (g_date_time_get_day_of_month (dt), ==, 1);
231   g_date_time_unref (dt);
232 }
233
234 static void
235 test_GDateTime_get_hour (void)
236 {
237   GDateTime *dt;
238
239   dt = g_date_time_new_utc (2009, 10, 19, 15, 13, 11);
240   g_assert_cmpint (15, ==, g_date_time_get_hour (dt));
241   g_date_time_unref (dt);
242
243   dt = g_date_time_new_utc (100, 10, 19, 1, 0, 0);
244   g_assert_cmpint (1, ==, g_date_time_get_hour (dt));
245   g_date_time_unref (dt);
246
247   dt = g_date_time_new_utc (100, 10, 19, 0, 0, 0);
248   g_assert_cmpint (0, ==, g_date_time_get_hour (dt));
249   g_date_time_unref (dt);
250
251   dt = g_date_time_new_utc (100, 10, 1, 23, 59, 59);
252   g_assert_cmpint (23, ==, g_date_time_get_hour (dt));
253   g_date_time_unref (dt);
254 }
255
256 static void
257 test_GDateTime_get_microsecond (void)
258 {
259   GTimeVal   tv;
260   GDateTime *dt;
261
262   g_get_current_time (&tv);
263   dt = g_date_time_new_from_timeval_local (&tv);
264   g_assert_cmpint (tv.tv_usec, ==, g_date_time_get_microsecond (dt));
265   g_date_time_unref (dt);
266 }
267
268 static void
269 test_GDateTime_get_year (void)
270 {
271   GDateTime *dt;
272
273   dt = g_date_time_new_local (2009, 1, 1, 0, 0, 0);
274   g_assert_cmpint (2009, ==, g_date_time_get_year (dt));
275   g_date_time_unref (dt);
276
277   dt = g_date_time_new_local (1, 1, 1, 0, 0, 0);
278   g_assert_cmpint (1, ==, g_date_time_get_year (dt));
279   g_date_time_unref (dt);
280
281   dt = g_date_time_new_local (13, 1, 1, 0, 0, 0);
282   g_assert_cmpint (13, ==, g_date_time_get_year (dt));
283   g_date_time_unref (dt);
284
285   dt = g_date_time_new_local (3000, 1, 1, 0, 0, 0);
286   g_assert_cmpint (3000, ==, g_date_time_get_year (dt));
287   g_date_time_unref (dt);
288 }
289
290 static void
291 test_GDateTime_hash (void)
292 {
293   GHashTable *h;
294
295   h = g_hash_table_new_full (g_date_time_hash, g_date_time_equal,
296                              (GDestroyNotify)g_date_time_unref,
297                              NULL);
298   g_hash_table_insert (h, g_date_time_new_now_local (), NULL);
299   g_hash_table_remove_all (h);
300   g_hash_table_destroy (h);
301 }
302
303 static void
304 test_GDateTime_new_from_timeval (void)
305 {
306   GDateTime *dt;
307   GTimeVal   tv, tv2;
308
309   g_get_current_time (&tv);
310   dt = g_date_time_new_from_timeval_local (&tv);
311
312   if (g_test_verbose ())
313     g_print ("\nDT%04d-%02d-%02dT%02d:%02d:%02d%s\n",
314              g_date_time_get_year (dt),
315              g_date_time_get_month (dt),
316              g_date_time_get_day_of_month (dt),
317              g_date_time_get_hour (dt),
318              g_date_time_get_minute (dt),
319              g_date_time_get_second (dt),
320              g_date_time_get_timezone_abbreviation (dt));
321
322   g_date_time_to_timeval (dt, &tv2);
323   g_assert_cmpint (tv.tv_sec, ==, tv2.tv_sec);
324   g_assert_cmpint (tv.tv_usec, ==, tv2.tv_usec);
325   g_date_time_unref (dt);
326 }
327
328 static void
329 test_GDateTime_new_from_timeval_utc (void)
330 {
331   GDateTime *dt;
332   GTimeVal   tv, tv2;
333
334   g_get_current_time (&tv);
335   dt = g_date_time_new_from_timeval_utc (&tv);
336
337   if (g_test_verbose ())
338     g_print ("\nDT%04d-%02d-%02dT%02d:%02d:%02d%s\n",
339              g_date_time_get_year (dt),
340              g_date_time_get_month (dt),
341              g_date_time_get_day_of_month (dt),
342              g_date_time_get_hour (dt),
343              g_date_time_get_minute (dt),
344              g_date_time_get_second (dt),
345              g_date_time_get_timezone_abbreviation (dt));
346
347   g_date_time_to_timeval (dt, &tv2);
348   g_assert_cmpint (tv.tv_sec, ==, tv2.tv_sec);
349   g_assert_cmpint (tv.tv_usec, ==, tv2.tv_usec);
350   g_date_time_unref (dt);
351 }
352
353 static void
354 test_GDateTime_to_unix (void)
355 {
356   GDateTime *dt;
357   time_t     t;
358
359   t = time (NULL);
360   dt = g_date_time_new_from_unix_local (t);
361   g_assert_cmpint (g_date_time_to_unix (dt), ==, t);
362   g_date_time_unref (dt);
363 }
364
365 static void
366 test_GDateTime_add_years (void)
367 {
368   GDateTime *dt, *dt2;
369
370   dt = g_date_time_new_local (2009, 10, 19, 0, 0, 0);
371   dt2 = g_date_time_add_years (dt, 1);
372   g_assert_cmpint (2010, ==, g_date_time_get_year (dt2));
373   g_date_time_unref (dt);
374   g_date_time_unref (dt2);
375 }
376
377 static void
378 test_GDateTime_add_months (void)
379 {
380 #define TEST_ADD_MONTHS(y,m,d,a,ny,nm,nd) G_STMT_START { \
381   GDateTime *dt, *dt2; \
382   dt = g_date_time_new_utc (y, m, d, 0, 0, 0); \
383   dt2 = g_date_time_add_months (dt, a); \
384   ASSERT_DATE (dt2, ny, nm, nd); \
385   g_date_time_unref (dt); \
386   g_date_time_unref (dt2); \
387 } G_STMT_END
388
389   TEST_ADD_MONTHS (2009, 12, 31,    1, 2010, 1, 31);
390   TEST_ADD_MONTHS (2009, 12, 31,    1, 2010, 1, 31);
391   TEST_ADD_MONTHS (2009,  6, 15,    1, 2009, 7, 15);
392   TEST_ADD_MONTHS (1400,  3,  1,    1, 1400, 4,  1);
393   TEST_ADD_MONTHS (1400,  1, 31,    1, 1400, 2, 28);
394   TEST_ADD_MONTHS (1400,  1, 31, 7200, 2000, 1, 31);
395   TEST_ADD_MONTHS (2008,  2, 29,   12, 2009, 2, 28);
396   TEST_ADD_MONTHS (2000,  8, 16,   -5, 2000, 3, 16);
397   TEST_ADD_MONTHS (2000,  8, 16,  -12, 1999, 8, 16);
398   TEST_ADD_MONTHS (2011,  2,  1,  -13, 2010, 1,  1);
399   TEST_ADD_MONTHS (1776,  7,  4, 1200, 1876, 7,  4);
400 }
401
402 static void
403 test_GDateTime_add_days (void)
404 {
405 #define TEST_ADD_DAYS(y,m,d,a,ny,nm,nd) G_STMT_START { \
406   GDateTime *dt, *dt2; \
407   dt = g_date_time_new_local (y, m, d, 0, 0, 0); \
408   dt2 = g_date_time_add_days (dt, a); \
409   g_assert_cmpint (ny, ==, g_date_time_get_year (dt2)); \
410   g_assert_cmpint (nm, ==, g_date_time_get_month (dt2)); \
411   g_assert_cmpint (nd, ==, g_date_time_get_day_of_month (dt2)); \
412   g_date_time_unref (dt); \
413   g_date_time_unref (dt2); \
414 } G_STMT_END
415
416   TEST_ADD_DAYS (2009, 1, 31, 1, 2009, 2, 1);
417   TEST_ADD_DAYS (2009, 2, 1, -1, 2009, 1, 31);
418   TEST_ADD_DAYS (2008, 2, 28, 1, 2008, 2, 29);
419   TEST_ADD_DAYS (2008, 12, 31, 1, 2009, 1, 1);
420   TEST_ADD_DAYS (1, 1, 1, 1, 1, 1, 2);
421   TEST_ADD_DAYS (1955, 5, 24, 10, 1955, 6, 3);
422   TEST_ADD_DAYS (1955, 5, 24, -10, 1955, 5, 14);
423 }
424
425 static void
426 test_GDateTime_add_weeks (void)
427 {
428 #define TEST_ADD_WEEKS(y,m,d,a,ny,nm,nd) G_STMT_START { \
429   GDateTime *dt, *dt2; \
430   dt = g_date_time_new_local (y, m, d, 0, 0, 0); \
431   dt2 = g_date_time_add_weeks (dt, a); \
432   g_assert_cmpint (ny, ==, g_date_time_get_year (dt2)); \
433   g_assert_cmpint (nm, ==, g_date_time_get_month (dt2)); \
434   g_assert_cmpint (nd, ==, g_date_time_get_day_of_month (dt2)); \
435   g_date_time_unref (dt); \
436   g_date_time_unref (dt2); \
437 } G_STMT_END
438
439   TEST_ADD_WEEKS (2009, 1, 1, 1, 2009, 1, 8);
440   TEST_ADD_WEEKS (2009, 8, 30, 1, 2009, 9, 6);
441   TEST_ADD_WEEKS (2009, 12, 31, 1, 2010, 1, 7);
442   TEST_ADD_WEEKS (2009, 1, 1, -1, 2008, 12, 25);
443 }
444
445 static void
446 test_GDateTime_add_hours (void)
447 {
448 #define TEST_ADD_HOURS(y,m,d,h,mi,s,a,ny,nm,nd,nh,nmi,ns) G_STMT_START { \
449   GDateTime *dt, *dt2; \
450   dt = g_date_time_new_utc (y, m, d, h, mi, s); \
451   dt2 = g_date_time_add_hours (dt, a); \
452   g_assert_cmpint (ny, ==, g_date_time_get_year (dt2)); \
453   g_assert_cmpint (nm, ==, g_date_time_get_month (dt2)); \
454   g_assert_cmpint (nd, ==, g_date_time_get_day_of_month (dt2)); \
455   g_assert_cmpint (nh, ==, g_date_time_get_hour (dt2)); \
456   g_assert_cmpint (nmi, ==, g_date_time_get_minute (dt2)); \
457   g_assert_cmpint (ns, ==, g_date_time_get_second (dt2)); \
458   g_date_time_unref (dt); \
459   g_date_time_unref (dt2); \
460 } G_STMT_END
461
462   TEST_ADD_HOURS (2009,  1,  1,  0, 0, 0, 1, 2009, 1, 1, 1, 0, 0);
463   TEST_ADD_HOURS (2008, 12, 31, 23, 0, 0, 1, 2009, 1, 1, 0, 0, 0);
464 }
465
466 static void
467 test_GDateTime_add_full (void)
468 {
469 #define TEST_ADD_FULL(y,m,d,h,mi,s,ay,am,ad,ah,ami,as,ny,nm,nd,nh,nmi,ns) G_STMT_START { \
470   GDateTime *dt, *dt2; \
471   dt = g_date_time_new_utc (y, m, d, h, mi, s); \
472   dt2 = g_date_time_add_full (dt, ay, am, ad, ah, ami, as); \
473   g_assert_cmpint (ny, ==, g_date_time_get_year (dt2)); \
474   g_assert_cmpint (nm, ==, g_date_time_get_month (dt2)); \
475   g_assert_cmpint (nd, ==, g_date_time_get_day_of_month (dt2)); \
476   g_assert_cmpint (nh, ==, g_date_time_get_hour (dt2)); \
477   g_assert_cmpint (nmi, ==, g_date_time_get_minute (dt2)); \
478   g_assert_cmpint (ns, ==, g_date_time_get_second (dt2)); \
479   g_date_time_unref (dt); \
480   g_date_time_unref (dt2); \
481 } G_STMT_END
482
483   TEST_ADD_FULL (2009, 10, 21,  0,  0, 0,
484                     1,  1,  1,  1,  1, 1,
485                  2010, 11, 22,  1,  1, 1);
486   TEST_ADD_FULL (2000,  1,  1,  1,  1, 1,
487                     0,  1,  0,  0,  0, 0,
488                  2000,  2,  1,  1,  1, 1);
489   TEST_ADD_FULL (2000,  1,  1,  0,  0, 0,
490                    -1,  1,  0,  0,  0, 0,
491                  1999,  2,  1,  0,  0, 0);
492   TEST_ADD_FULL (2010, 10, 31,  0,  0, 0,
493                     0,  4,  0,  0,  0, 0,
494                  2011,  2, 28,  0,  0, 0);
495   TEST_ADD_FULL (2010,  8, 25, 22, 45, 0,
496                     0,  1,  6,  1, 25, 0,
497                  2010, 10,  2,  0, 10, 0);
498 }
499
500 static void
501 test_GDateTime_add_minutes (void)
502 {
503 #define TEST_ADD_MINUTES(i,o) G_STMT_START { \
504   GDateTime *dt, *dt2; \
505   dt = g_date_time_new_local (2000, 1, 1, 0, 0, 0); \
506   dt2 = g_date_time_add_minutes (dt, i); \
507   g_assert_cmpint (o, ==, g_date_time_get_minute (dt2)); \
508   g_date_time_unref (dt); \
509   g_date_time_unref (dt2); \
510 } G_STMT_END
511
512   TEST_ADD_MINUTES (60, 0);
513   TEST_ADD_MINUTES (100, 40);
514   TEST_ADD_MINUTES (5, 5);
515   TEST_ADD_MINUTES (1441, 1);
516   TEST_ADD_MINUTES (-1441, 59);
517 }
518
519 static void
520 test_GDateTime_add_seconds (void)
521 {
522 #define TEST_ADD_SECONDS(i,o) G_STMT_START { \
523   GDateTime *dt, *dt2; \
524   dt = g_date_time_new_local (2000, 1, 1, 0, 0, 0); \
525   dt2 = g_date_time_add_seconds (dt, i); \
526   g_assert_cmpint (o, ==, g_date_time_get_second (dt2)); \
527   g_date_time_unref (dt); \
528   g_date_time_unref (dt2); \
529 } G_STMT_END
530
531   TEST_ADD_SECONDS (1, 1);
532   TEST_ADD_SECONDS (60, 0);
533   TEST_ADD_SECONDS (61, 1);
534   TEST_ADD_SECONDS (120, 0);
535   TEST_ADD_SECONDS (-61, 59);
536   TEST_ADD_SECONDS (86401, 1);
537   TEST_ADD_SECONDS (-86401, 59);
538   TEST_ADD_SECONDS (-31, 29);
539   TEST_ADD_SECONDS (13, 13);
540 }
541
542 static void
543 test_GDateTime_diff (void)
544 {
545 #define TEST_DIFF(y,m,d,y2,m2,d2,u) G_STMT_START { \
546   GDateTime *dt1, *dt2; \
547   GTimeSpan  ts = 0; \
548   dt1 = g_date_time_new_local (y, m, d, 0, 0, 0); \
549   dt2 = g_date_time_new_local (y2, m2, d2, 0, 0, 0); \
550   ts = g_date_time_difference (dt2, dt1); \
551   g_assert_cmpint (ts, ==, u); \
552   g_date_time_unref (dt1); \
553   g_date_time_unref (dt2); \
554 } G_STMT_END
555
556   TEST_DIFF (2009, 1, 1, 2009, 2, 1, G_TIME_SPAN_DAY * 31);
557   TEST_DIFF (2009, 1, 1, 2010, 1, 1, G_TIME_SPAN_DAY * 365);
558   TEST_DIFF (2008, 2, 28, 2008, 2, 29, G_TIME_SPAN_DAY);
559   TEST_DIFF (2008, 2, 29, 2008, 2, 28, -G_TIME_SPAN_DAY);
560
561   /* TODO: Add usec tests */
562 }
563
564 static void
565 test_GDateTime_get_minute (void)
566 {
567   GDateTime *dt;
568
569   dt = g_date_time_new_utc (2009, 12, 1, 1, 31, 0);
570   g_assert_cmpint (31, ==, g_date_time_get_minute (dt));
571   g_date_time_unref (dt);
572 }
573
574 static void
575 test_GDateTime_get_month (void)
576 {
577   GDateTime *dt;
578
579   dt = g_date_time_new_utc (2009, 12, 1, 1, 31, 0);
580   g_assert_cmpint (12, ==, g_date_time_get_month (dt));
581   g_date_time_unref (dt);
582 }
583
584 static void
585 test_GDateTime_get_second (void)
586 {
587   GDateTime *dt;
588
589   dt = g_date_time_new_utc (2009, 12, 1, 1, 31, 44);
590   g_assert_cmpint (44, ==, g_date_time_get_second (dt));
591   g_date_time_unref (dt);
592 }
593
594 static void
595 test_GDateTime_new_full (void)
596 {
597   GTimeZone *tz;
598   GDateTime *dt;
599
600   dt = g_date_time_new_utc (2009, 12, 11, 12, 11, 10);
601   g_assert_cmpint (2009, ==, g_date_time_get_year (dt));
602   g_assert_cmpint (12, ==, g_date_time_get_month (dt));
603   g_assert_cmpint (11, ==, g_date_time_get_day_of_month (dt));
604   g_assert_cmpint (12, ==, g_date_time_get_hour (dt));
605   g_assert_cmpint (11, ==, g_date_time_get_minute (dt));
606   g_assert_cmpint (10, ==, g_date_time_get_second (dt));
607   g_date_time_unref (dt);
608
609   tz = g_time_zone_new ("America/Recife");
610   dt = g_date_time_new (tz, 2010, 5, 24, 8, 4, 0);
611   g_time_zone_unref (tz);
612   g_assert_cmpint (2010, ==, g_date_time_get_year (dt));
613   g_assert_cmpint (5, ==, g_date_time_get_month (dt));
614   g_assert_cmpint (24, ==, g_date_time_get_day_of_month (dt));
615   g_assert_cmpint (8, ==, g_date_time_get_hour (dt));
616   g_assert_cmpint (4, ==, g_date_time_get_minute (dt));
617   g_assert_cmpint (0, ==, g_date_time_get_second (dt));
618   g_assert_cmpstr ("BRT", ==, g_date_time_get_timezone_abbreviation (dt));
619   g_assert (!g_date_time_is_daylight_savings (dt));
620   g_date_time_unref (dt);
621 }
622
623 static void
624 test_GDateTime_now_utc (void)
625 {
626   GDateTime *dt;
627   time_t     t;
628   struct tm  tm;
629
630   t = time (NULL);
631 #ifdef HAVE_GMTIME_R
632   gmtime_r (&t, &tm);
633 #else
634   {
635     struct tm *tmp = gmtime (&t);
636     /* Assume gmtime() can't fail as we got t from time(NULL). (Note
637      * that on Windows, gmtime() *is* MT-safe, it uses a thread-local
638      * buffer.)
639      */
640     memcpy (&tm, tmp, sizeof (struct tm));
641   }
642 #endif
643   dt = g_date_time_new_now_utc ();
644   g_assert_cmpint (tm.tm_year + 1900, ==, g_date_time_get_year (dt));
645   g_assert_cmpint (tm.tm_mon + 1, ==, g_date_time_get_month (dt));
646   g_assert_cmpint (tm.tm_mday, ==, g_date_time_get_day_of_month (dt));
647   g_assert_cmpint (tm.tm_hour, ==, g_date_time_get_hour (dt));
648   g_assert_cmpint (tm.tm_min, ==, g_date_time_get_minute (dt));
649   g_assert_cmpint (tm.tm_sec, ==, g_date_time_get_second (dt));
650   g_date_time_unref (dt);
651 }
652
653 static void
654 test_GDateTime_new_from_unix_utc (void)
655 {
656   GDateTime *dt;
657   gint64 t;
658
659   t = g_get_real_time ();
660
661 #if 0
662   dt = g_date_time_new_from_unix_utc (t);
663   g_assert (dt == NULL);
664 #endif
665
666   t = t / 1e6;  /* oops, this was microseconds */
667
668   dt = g_date_time_new_from_unix_utc (t);
669   g_assert (dt != NULL);
670
671   g_assert (dt == g_date_time_ref (dt));
672   g_date_time_unref (dt);
673   g_assert_cmpint (g_date_time_to_unix (dt), ==, t);
674   g_date_time_unref (dt);
675 }
676
677 static void
678 test_GDateTime_get_utc_offset (void)
679 {
680   GDateTime *dt;
681   GTimeSpan ts;
682   struct tm tm;
683
684   memset (&tm, 0, sizeof (tm));
685   get_localtime_tm (time (NULL), &tm);
686
687   dt = g_date_time_new_now_local ();
688   ts = g_date_time_get_utc_offset (dt);
689 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
690   g_assert_cmpint (ts, ==, (tm.tm_gmtoff * G_TIME_SPAN_SECOND));
691 #endif
692 #ifdef HAVE_STRUCT_TM___TM_GMTOFF
693   g_assert_cmpint (ts, ==, (tm.__tm_gmtoff * G_TIME_SPAN_SECOND));
694 #endif
695   g_date_time_unref (dt);
696 }
697
698 static void
699 test_GDateTime_to_timeval (void)
700 {
701   GTimeVal tv1, tv2;
702   GDateTime *dt;
703
704   memset (&tv1, 0, sizeof (tv1));
705   memset (&tv2, 0, sizeof (tv2));
706
707   g_get_current_time (&tv1);
708   dt = g_date_time_new_from_timeval_local (&tv1);
709   g_date_time_to_timeval (dt, &tv2);
710   g_assert_cmpint (tv1.tv_sec, ==, tv2.tv_sec);
711   g_assert_cmpint (tv1.tv_usec, ==, tv2.tv_usec);
712   g_date_time_unref (dt);
713 }
714
715 static void
716 test_GDateTime_to_local (void)
717 {
718   GDateTime *utc, *now, *dt;
719
720   utc = g_date_time_new_now_utc ();
721   now = g_date_time_new_now_local ();
722   dt = g_date_time_to_local (utc);
723
724   g_assert_cmpint (g_date_time_get_year (now), ==, g_date_time_get_year (dt));
725   g_assert_cmpint (g_date_time_get_month (now), ==, g_date_time_get_month (dt));
726   g_assert_cmpint (g_date_time_get_day_of_month (now), ==, g_date_time_get_day_of_month (dt));
727   g_assert_cmpint (g_date_time_get_hour (now), ==, g_date_time_get_hour (dt));
728   g_assert_cmpint (g_date_time_get_minute (now), ==, g_date_time_get_minute (dt));
729   g_assert_cmpint (g_date_time_get_second (now), ==, g_date_time_get_second (dt));
730
731   g_date_time_unref (now);
732   g_date_time_unref (utc);
733   g_date_time_unref (dt);
734 }
735
736 static void
737 test_GDateTime_to_utc (void)
738 {
739   GDateTime *dt, *dt2;
740   time_t     t;
741   struct tm  tm;
742
743   t = time (NULL);
744 #ifdef HAVE_GMTIME_R
745   gmtime_r (&t, &tm);
746 #else
747   {
748     struct tm *tmp = gmtime (&t);
749     memcpy (&tm, tmp, sizeof (struct tm));
750   }
751 #endif
752   dt2 = g_date_time_new_from_unix_local (t);
753   dt = g_date_time_to_utc (dt2);
754   g_assert_cmpint (tm.tm_year + 1900, ==, g_date_time_get_year (dt));
755   g_assert_cmpint (tm.tm_mon + 1, ==, g_date_time_get_month (dt));
756   g_assert_cmpint (tm.tm_mday, ==, g_date_time_get_day_of_month (dt));
757   g_assert_cmpint (tm.tm_hour, ==, g_date_time_get_hour (dt));
758   g_assert_cmpint (tm.tm_min, ==, g_date_time_get_minute (dt));
759   g_assert_cmpint (tm.tm_sec, ==, g_date_time_get_second (dt));
760   g_date_time_unref (dt);
761   g_date_time_unref (dt2);
762 }
763
764 static void
765 test_GDateTime_get_day_of_year (void)
766 {
767 #define TEST_DAY_OF_YEAR(y,m,d,o)                       G_STMT_START {  \
768   GDateTime *__dt = g_date_time_new_local ((y), (m), (d), 0, 0, 0);     \
769   g_assert_cmpint ((o), ==, g_date_time_get_day_of_year (__dt));        \
770   g_date_time_unref (__dt);                             } G_STMT_END
771
772   TEST_DAY_OF_YEAR (2009, 1, 1, 1);
773   TEST_DAY_OF_YEAR (2009, 2, 1, 32);
774   TEST_DAY_OF_YEAR (2009, 8, 16, 228);
775   TEST_DAY_OF_YEAR (2008, 8, 16, 229);
776 }
777
778 static void
779 test_GDateTime_printf (void)
780 {
781   gchar dst[16];
782   struct tm tt;
783   time_t t;
784   gchar t_str[16];
785
786 #define TEST_PRINTF(f,o)                        G_STMT_START {  \
787 GDateTime *__dt = g_date_time_new_local (2009, 10, 24, 0, 0, 0);\
788   gchar *__p = g_date_time_format (__dt, (f));                  \
789   g_assert_cmpstr (__p, ==, (o));                               \
790   g_date_time_unref (__dt);                                     \
791   g_free (__p);                                 } G_STMT_END
792
793 #define TEST_PRINTF_DATE(y,m,d,f,o)             G_STMT_START {  \
794   GDateTime *dt = g_date_time_new_local (y, m, d, 0, 0, 0);     \
795   gchar *p = g_date_time_format (dt, (f));                      \
796   g_assert_cmpstr (p, ==, (o));                                 \
797   g_date_time_unref (dt);                                       \
798   g_free (p);                                   } G_STMT_END
799
800 #define TEST_PRINTF_TIME(h,m,s,f,o)             G_STMT_START { \
801   GDateTime *dt = g_date_time_new_local (2009, 10, 24, (h), (m), (s)); \
802   gchar *p = g_date_time_format (dt, (f));                      \
803   g_assert_cmpstr (p, ==, (o));                                 \
804   g_date_time_unref (dt);                                       \
805   g_free (p);                                   } G_STMT_END
806
807   /*
808    * This is a little helper to make sure we can compare timezones to
809    * that of the generated timezone.
810    */
811   t = time (NULL);
812   memset (&tt, 0, sizeof(tt));
813   get_localtime_tm (t, &tt);
814   tt.tm_year = 2009 - 1900;
815   tt.tm_mon = 9; /* 0 indexed */
816   tt.tm_mday = 24;
817   t = mktime (&tt);
818   memset (&tt, 0, sizeof(tt));
819   get_localtime_tm (t, &tt);
820   strftime (dst, sizeof(dst), "%Z", &tt);
821
822   /* get current time_t for 20090924 in the local timezone */
823   tt.tm_sec = 0;
824   tt.tm_min = 0;
825   tt.tm_hour = 0;
826   t = mktime (&tt);
827   g_sprintf (t_str, "%ld", t);
828
829   TEST_PRINTF ("%a", "Sat");
830   TEST_PRINTF ("%A", "Saturday");
831   TEST_PRINTF ("%b", "Oct");
832   TEST_PRINTF ("%B", "October");
833   TEST_PRINTF ("%d", "24");
834   TEST_PRINTF_DATE (2009, 1, 1, "%d", "01");
835   TEST_PRINTF ("%e", "24"); // fixme
836   TEST_PRINTF ("%h", "Oct");
837   TEST_PRINTF ("%H", "00");
838   TEST_PRINTF_TIME (15, 0, 0, "%H", "15");
839   TEST_PRINTF ("%I", "12");
840   TEST_PRINTF_TIME (12, 0, 0, "%I", "12");
841   TEST_PRINTF_TIME (15, 0, 0, "%I", "03");
842   TEST_PRINTF ("%j", "297");
843   TEST_PRINTF ("%k", " 0");
844   TEST_PRINTF_TIME (13, 13, 13, "%k", "13");
845   TEST_PRINTF ("%l", "12");
846   TEST_PRINTF_TIME (12, 0, 0, "%I", "12");
847   TEST_PRINTF_TIME (13, 13, 13, "%l", " 1");
848   TEST_PRINTF_TIME (10, 13, 13, "%l", "10");
849   TEST_PRINTF ("%m", "10");
850   TEST_PRINTF ("%M", "00");
851   TEST_PRINTF ("%p", "AM");
852   TEST_PRINTF_TIME (13, 13, 13, "%p", "PM");
853   TEST_PRINTF ("%P", "am");
854   TEST_PRINTF_TIME (13, 13, 13, "%P", "pm");
855   TEST_PRINTF ("%r", "12:00:00 AM");
856   TEST_PRINTF_TIME (13, 13, 13, "%r", "01:13:13 PM");
857   TEST_PRINTF ("%R", "00:00");
858   TEST_PRINTF_TIME (13, 13, 31, "%R", "13:13");
859   //TEST_PRINTF ("%s", t_str);
860   TEST_PRINTF ("%S", "00");
861   TEST_PRINTF ("%t", "  ");
862   TEST_PRINTF ("%u", "6");
863   TEST_PRINTF ("%x", "10/24/09");
864   TEST_PRINTF ("%X", "00:00:00");
865   TEST_PRINTF_TIME (13, 14, 15, "%X", "13:14:15");
866   TEST_PRINTF ("%y", "09");
867   TEST_PRINTF ("%Y", "2009");
868   TEST_PRINTF ("%%", "%");
869   TEST_PRINTF ("%", "");
870   TEST_PRINTF ("%9", NULL);
871   TEST_PRINTF ("%Z", dst);
872 }
873
874 static void
875 test_non_utf8_printf (void)
876 {
877   gchar *oldlocale;
878
879   oldlocale = g_strdup (setlocale (LC_ALL, NULL));
880   setlocale (LC_ALL, "ja_JP.eucjp");
881   if (strstr (setlocale (LC_ALL, NULL), "ja_JP") == NULL)
882     {
883       g_test_message ("locale ja_JP.eucjp not available, skipping non-UTF8 tests");
884       g_free (oldlocale);
885       return;
886     }
887
888   /* These are the outputs that ja_JP.UTF-8 generates; if everything
889    * is working then ja_JP.eucjp should generate the same.
890    */
891   TEST_PRINTF ("%a", "\345\234\237");
892   TEST_PRINTF ("%A", "\345\234\237\346\233\234\346\227\245");
893   TEST_PRINTF ("%b", "10\346\234\210");
894   TEST_PRINTF ("%B", "10\346\234\210");
895   TEST_PRINTF ("%d", "24");
896   TEST_PRINTF_DATE (2009, 1, 1, "%d", "01");
897   TEST_PRINTF ("%e", "24"); // fixme
898   TEST_PRINTF ("%h", "10\346\234\210");
899   TEST_PRINTF ("%H", "00");
900   TEST_PRINTF_TIME (15, 0, 0, "%H", "15");
901   TEST_PRINTF ("%I", "12");
902   TEST_PRINTF_TIME (12, 0, 0, "%I", "12");
903   TEST_PRINTF_TIME (15, 0, 0, "%I", "03");
904   TEST_PRINTF ("%j", "297");
905   TEST_PRINTF ("%k", " 0");
906   TEST_PRINTF_TIME (13, 13, 13, "%k", "13");
907   TEST_PRINTF ("%l", "12");
908   TEST_PRINTF_TIME (12, 0, 0, "%I", "12");
909   TEST_PRINTF_TIME (13, 13, 13, "%l", " 1");
910   TEST_PRINTF_TIME (10, 13, 13, "%l", "10");
911   TEST_PRINTF ("%m", "10");
912   TEST_PRINTF ("%M", "00");
913   TEST_PRINTF ("%p", "\345\215\210\345\211\215");
914   TEST_PRINTF_TIME (13, 13, 13, "%p", "\345\215\210\345\276\214");
915   TEST_PRINTF ("%P", "\345\215\210\345\211\215");
916   TEST_PRINTF_TIME (13, 13, 13, "%P", "\345\215\210\345\276\214");
917   TEST_PRINTF ("%r", "\345\215\210\345\211\21512\346\231\20200\345\210\20600\347\247\222");
918   TEST_PRINTF_TIME (13, 13, 13, "%r", "\345\215\210\345\276\21401\346\231\20213\345\210\20613\347\247\222");
919   TEST_PRINTF ("%R", "00:00");
920   TEST_PRINTF_TIME (13, 13, 31, "%R", "13:13");
921   TEST_PRINTF ("%S", "00");
922   TEST_PRINTF ("%t", "  ");
923   TEST_PRINTF ("%u", "6");
924   TEST_PRINTF ("%x", "2009\345\271\26410\346\234\21024\346\227\245");
925   TEST_PRINTF ("%X", "00\346\231\20200\345\210\20600\347\247\222");
926   TEST_PRINTF_TIME (13, 14, 15, "%X", "13\346\231\20214\345\210\20615\347\247\222");
927   TEST_PRINTF ("%y", "09");
928   TEST_PRINTF ("%Y", "2009");
929   TEST_PRINTF ("%%", "%");
930   TEST_PRINTF ("%", "");
931   TEST_PRINTF ("%9", NULL);
932
933   setlocale (LC_ALL, oldlocale);
934   g_free (oldlocale);
935 }
936
937 static void
938 test_modifiers (void)
939 {
940   gchar *oldlocale;
941
942   TEST_PRINTF_DATE (2009, 1,  1,  "%d", "01");
943   TEST_PRINTF_DATE (2009, 1,  1, "%_d", " 1");
944   TEST_PRINTF_DATE (2009, 1,  1, "%-d", "1");
945   TEST_PRINTF_DATE (2009, 1,  1, "%0d", "01");
946   TEST_PRINTF_DATE (2009, 1, 21,  "%d", "21");
947   TEST_PRINTF_DATE (2009, 1, 21, "%_d", "21");
948   TEST_PRINTF_DATE (2009, 1, 21, "%-d", "21");
949   TEST_PRINTF_DATE (2009, 1, 21, "%0d", "21");
950
951   TEST_PRINTF_DATE (2009, 1,  1,  "%e", " 1");
952   TEST_PRINTF_DATE (2009, 1,  1, "%_e", " 1");
953   TEST_PRINTF_DATE (2009, 1,  1, "%-e", "1");
954   TEST_PRINTF_DATE (2009, 1,  1, "%0e", "01");
955   TEST_PRINTF_DATE (2009, 1, 21,  "%e", "21");
956   TEST_PRINTF_DATE (2009, 1, 21, "%_e", "21");
957   TEST_PRINTF_DATE (2009, 1, 21, "%-e", "21");
958   TEST_PRINTF_DATE (2009, 1, 21, "%0e", "21");
959
960   TEST_PRINTF_TIME ( 1, 0, 0,  "%H", "01");
961   TEST_PRINTF_TIME ( 1, 0, 0, "%_H", " 1");
962   TEST_PRINTF_TIME ( 1, 0, 0, "%-H", "1");
963   TEST_PRINTF_TIME ( 1, 0, 0, "%0H", "01");
964   TEST_PRINTF_TIME (21, 0, 0,  "%H", "21");
965   TEST_PRINTF_TIME (21, 0, 0, "%_H", "21");
966   TEST_PRINTF_TIME (21, 0, 0, "%-H", "21");
967   TEST_PRINTF_TIME (21, 0, 0, "%0H", "21");
968
969   TEST_PRINTF_TIME ( 1, 0, 0,  "%I", "01");
970   TEST_PRINTF_TIME ( 1, 0, 0, "%_I", " 1");
971   TEST_PRINTF_TIME ( 1, 0, 0, "%-I", "1");
972   TEST_PRINTF_TIME ( 1, 0, 0, "%0I", "01");
973   TEST_PRINTF_TIME (23, 0, 0,  "%I", "11");
974   TEST_PRINTF_TIME (23, 0, 0, "%_I", "11");
975   TEST_PRINTF_TIME (23, 0, 0, "%-I", "11");
976   TEST_PRINTF_TIME (23, 0, 0, "%0I", "11");
977
978   TEST_PRINTF_TIME ( 1, 0, 0,  "%k", " 1");
979   TEST_PRINTF_TIME ( 1, 0, 0, "%_k", " 1");
980   TEST_PRINTF_TIME ( 1, 0, 0, "%-k", "1");
981   TEST_PRINTF_TIME ( 1, 0, 0, "%0k", "01");
982
983   oldlocale = g_strdup (setlocale (LC_ALL, NULL));
984   setlocale (LC_ALL, "fa_IR.utf-8");
985   if (strstr (setlocale (LC_ALL, NULL), "fa_IR") != NULL)
986     {
987       TEST_PRINTF_TIME (23, 0, 0, "%OH", "\333\262\333\263");    /* '23' */
988       TEST_PRINTF_TIME (23, 0, 0, "%OI", "\333\261\333\261");    /* '11' */
989       TEST_PRINTF_TIME (23, 0, 0, "%OM", "\333\260\333\260");    /* '00' */
990
991       TEST_PRINTF_DATE (2011, 7, 1, "%Om", "\333\260\333\267");  /* '07' */
992       TEST_PRINTF_DATE (2011, 7, 1, "%0Om", "\333\260\333\267"); /* '07' */
993       TEST_PRINTF_DATE (2011, 7, 1, "%-Om", "\333\267");         /* '7' */
994       TEST_PRINTF_DATE (2011, 7, 1, "%_Om", " \333\267");        /* ' 7' */
995     }
996   else
997     g_test_message ("locale fa_IR not available, skipping O modifier tests");
998   setlocale (LC_ALL, oldlocale);
999   g_free (oldlocale);
1000 }
1001
1002 static void
1003 test_GDateTime_dst (void)
1004 {
1005   GDateTime *dt1, *dt2;
1006   GTimeZone *tz;
1007
1008   /* this date has the DST state set for Europe/London */
1009   tz = g_time_zone_new ("Europe/London");
1010   dt1 = g_date_time_new (tz, 2009, 8, 15, 3, 0, 1);
1011   g_assert (g_date_time_is_daylight_savings (dt1));
1012   g_assert_cmpint (g_date_time_get_utc_offset (dt1) / G_USEC_PER_SEC, ==, 3600);
1013   g_assert_cmpint (g_date_time_get_hour (dt1), ==, 3);
1014
1015   /* add 6 months to clear the DST flag but keep the same time */
1016   dt2 = g_date_time_add_months (dt1, 6);
1017   g_assert (!g_date_time_is_daylight_savings (dt2));
1018   g_assert_cmpint (g_date_time_get_utc_offset (dt2) / G_USEC_PER_SEC, ==, 0);
1019   g_assert_cmpint (g_date_time_get_hour (dt2), ==, 3);
1020
1021   g_date_time_unref (dt2);
1022   g_date_time_unref (dt1);
1023
1024   /* now do the reverse: start with a non-DST state and move to DST */
1025   dt1 = g_date_time_new (tz, 2009, 2, 15, 2, 0, 1);
1026   g_assert (!g_date_time_is_daylight_savings (dt1));
1027   g_assert_cmpint (g_date_time_get_hour (dt1), ==, 2);
1028
1029   dt2 = g_date_time_add_months (dt1, 6);
1030   g_assert (g_date_time_is_daylight_savings (dt2));
1031   g_assert_cmpint (g_date_time_get_hour (dt2), ==, 2);
1032
1033   g_date_time_unref (dt2);
1034   g_date_time_unref (dt1);
1035   g_time_zone_unref (tz);
1036 }
1037
1038 static inline gboolean
1039 is_leap_year (gint year)
1040 {
1041   g_assert (1 <= year && year <= 9999);
1042
1043   return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
1044 }
1045
1046 static inline gint
1047 days_in_month (gint year, gint month)
1048 {
1049   const gint table[2][13] = {
1050     {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
1051     {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
1052   };
1053
1054   g_assert (1 <= month && month <= 12);
1055
1056   return table[is_leap_year (year)][month];
1057 }
1058
1059 static void
1060 test_all_dates (void)
1061 {
1062   gint year, month, day;
1063   GTimeZone *timezone;
1064   gint64 unix_time;
1065   gint day_of_year;
1066   gint week_year;
1067   gint week_num;
1068   gint weekday;
1069
1070   /* save some time by hanging on to this. */
1071   timezone = g_time_zone_new_utc ();
1072
1073   unix_time = G_GINT64_CONSTANT(-62135596800);
1074
1075   /* 0001-01-01 is 0001-W01-1 */
1076   week_year = 1;
1077   week_num = 1;
1078   weekday = 1;
1079
1080
1081   /* The calendar makes a full cycle every 400 years, so we could
1082    * theoretically just test years 1 through 400.  That assumes that our
1083    * software has no bugs, so probably we should just test them all. :)
1084    */
1085   for (year = 1; year <= 9999; year++)
1086     {
1087       day_of_year = 1;
1088
1089       for (month = 1; month <= 12; month++)
1090         for (day = 1; day <= days_in_month (year, month); day++)
1091           {
1092             GDateTime *dt;
1093
1094             dt = g_date_time_new (timezone, year, month, day, 0, 0, 0);
1095
1096 #if 0
1097             g_print ("%04d-%02d-%02d = %04d-W%02d-%d = %04d-%03d\n",
1098                      year, month, day,
1099                      week_year, week_num, weekday,
1100                      year, day_of_year);
1101 #endif
1102
1103             /* sanity check */
1104             if G_UNLIKELY (g_date_time_get_year (dt) != year ||
1105                            g_date_time_get_month (dt) != month ||
1106                            g_date_time_get_day_of_month (dt) != day)
1107               g_error ("%04d-%02d-%02d comes out as %04d-%02d-%02d",
1108                        year, month, day,
1109                        g_date_time_get_year (dt),
1110                        g_date_time_get_month (dt),
1111                        g_date_time_get_day_of_month (dt));
1112
1113             if G_UNLIKELY (g_date_time_get_week_numbering_year (dt) != week_year ||
1114                            g_date_time_get_week_of_year (dt) != week_num ||
1115                            g_date_time_get_day_of_week (dt) != weekday)
1116               g_error ("%04d-%02d-%02d should be %04d-W%02d-%d but "
1117                        "comes out as %04d-W%02d-%d", year, month, day,
1118                        week_year, week_num, weekday,
1119                        g_date_time_get_week_numbering_year (dt),
1120                        g_date_time_get_week_of_year (dt),
1121                        g_date_time_get_day_of_week (dt));
1122
1123             if G_UNLIKELY (g_date_time_to_unix (dt) != unix_time)
1124               g_error ("%04d-%02d-%02d 00:00:00 UTC should have unix time %"
1125                        G_GINT64_FORMAT " but comes out as %"G_GINT64_FORMAT,
1126                        year, month, day, unix_time, g_date_time_to_unix (dt));
1127
1128             if G_UNLIKELY (g_date_time_get_day_of_year (dt) != day_of_year)
1129               g_error ("%04d-%02d-%02d should be day of year %d"
1130                        " but comes out as %d", year, month, day,
1131                        day_of_year, g_date_time_get_day_of_year (dt));
1132
1133             if G_UNLIKELY (g_date_time_get_hour (dt) != 0 ||
1134                            g_date_time_get_minute (dt) != 0 ||
1135                            g_date_time_get_seconds (dt) != 0)
1136               g_error ("%04d-%02d-%02d 00:00:00 UTC comes out "
1137                        "as %02d:%02d:%02.6f", year, month, day,
1138                        g_date_time_get_hour (dt),
1139                        g_date_time_get_minute (dt),
1140                        g_date_time_get_seconds (dt));
1141             /* done */
1142
1143             /* add 24 hours to unix time */
1144             unix_time += 24 * 60 * 60;
1145
1146             /* move day of year forward */
1147             day_of_year++;
1148
1149             /* move the week date forward */
1150             if (++weekday == 8)
1151               {
1152                 weekday = 1; /* Sunday -> Monday */
1153
1154                 /* NOTE: year/month/day is the final day of the week we
1155                  * just finished.
1156                  *
1157                  * If we just finished the last week of last year then
1158                  * we are definitely starting the first week of this
1159                  * year.
1160                  *
1161                  * Otherwise, if we're still in this year, but Sunday
1162                  * fell on or after December 28 then December 29, 30, 31
1163                  * could be days within the next year's first year.
1164                  */
1165                 if (year != week_year || (month == 12 && day >= 28))
1166                   {
1167                     /* first week of the new year */
1168                     week_num = 1;
1169                     week_year++;
1170                   }
1171                 else
1172                   week_num++;
1173               }
1174
1175             g_date_time_unref (dt);
1176           }
1177     }
1178
1179   g_time_zone_unref (timezone);
1180 }
1181
1182 static void
1183 test_z (void)
1184 {
1185   GTimeZone *tz;
1186   GDateTime *dt;
1187
1188   g_test_bug ("642935");
1189
1190   tz = g_time_zone_new ("-08:00");
1191   dt = g_date_time_new (tz, 0, 0, 0, 0, 0, 0);
1192   gchar *p = g_date_time_format (dt, "%z");
1193   g_assert_cmpstr (p, ==, "-0800");
1194   g_date_time_unref (dt);
1195   g_time_zone_unref (tz);
1196   g_free (p);
1197 }
1198
1199 static void
1200 test_strftime (void)
1201 {
1202   /* this is probably going to cause various buggy libcs to explode... */
1203 #define TEST_FORMAT \
1204   "a%a A%A b%b B%B c%c C%C d%d e%e F%F g%g G%G h%h H%H I%I j%j m%m M%M " \
1205   "n%n p%p r%r R%R S%S t%t T%T u%u V%V w%w x%x X%X y%y Y%Y z%z Z%Z %%"
1206   time_t t;
1207
1208   /* 127997 is prime, 1315005118 is now */
1209   for (t = 0; t < 1315005118; t += 127997)
1210     {
1211       GDateTime *date_time;
1212       gchar c_str[1000];
1213       gchar *dt_str;
1214
1215       date_time = g_date_time_new_from_unix_local (t);
1216       dt_str = g_date_time_format (date_time, TEST_FORMAT);
1217       strftime (c_str, sizeof c_str, TEST_FORMAT, localtime (&t));
1218       g_assert_cmpstr (c_str, ==, dt_str);
1219       g_date_time_unref (date_time);
1220       g_free (dt_str);
1221     }
1222 }
1223
1224 gint
1225 main (gint   argc,
1226       gchar *argv[])
1227 {
1228   g_test_init (&argc, &argv, NULL);
1229   g_test_bug_base ("http://bugzilla.gnome.org/");
1230
1231   /* GDateTime Tests */
1232
1233   g_test_add_func ("/GDateTime/add_days", test_GDateTime_add_days);
1234   g_test_add_func ("/GDateTime/add_full", test_GDateTime_add_full);
1235   g_test_add_func ("/GDateTime/add_hours", test_GDateTime_add_hours);
1236   g_test_add_func ("/GDateTime/add_minutes", test_GDateTime_add_minutes);
1237   g_test_add_func ("/GDateTime/add_months", test_GDateTime_add_months);
1238   g_test_add_func ("/GDateTime/add_seconds", test_GDateTime_add_seconds);
1239   g_test_add_func ("/GDateTime/add_weeks", test_GDateTime_add_weeks);
1240   g_test_add_func ("/GDateTime/add_years", test_GDateTime_add_years);
1241   g_test_add_func ("/GDateTime/compare", test_GDateTime_compare);
1242   g_test_add_func ("/GDateTime/diff", test_GDateTime_diff);
1243   g_test_add_func ("/GDateTime/equal", test_GDateTime_equal);
1244   g_test_add_func ("/GDateTime/get_day_of_week", test_GDateTime_get_day_of_week);
1245   g_test_add_func ("/GDateTime/get_day_of_month", test_GDateTime_get_day_of_month);
1246   g_test_add_func ("/GDateTime/get_day_of_year", test_GDateTime_get_day_of_year);
1247   g_test_add_func ("/GDateTime/get_hour", test_GDateTime_get_hour);
1248   g_test_add_func ("/GDateTime/get_microsecond", test_GDateTime_get_microsecond);
1249   g_test_add_func ("/GDateTime/get_minute", test_GDateTime_get_minute);
1250   g_test_add_func ("/GDateTime/get_month", test_GDateTime_get_month);
1251   g_test_add_func ("/GDateTime/get_second", test_GDateTime_get_second);
1252   g_test_add_func ("/GDateTime/get_utc_offset", test_GDateTime_get_utc_offset);
1253   g_test_add_func ("/GDateTime/get_year", test_GDateTime_get_year);
1254   g_test_add_func ("/GDateTime/hash", test_GDateTime_hash);
1255   g_test_add_func ("/GDateTime/new_from_unix", test_GDateTime_new_from_unix);
1256   g_test_add_func ("/GDateTime/new_from_unix_utc", test_GDateTime_new_from_unix_utc);
1257   g_test_add_func ("/GDateTime/new_from_timeval", test_GDateTime_new_from_timeval);
1258   g_test_add_func ("/GDateTime/new_from_timeval_utc", test_GDateTime_new_from_timeval_utc);
1259   g_test_add_func ("/GDateTime/new_full", test_GDateTime_new_full);
1260   g_test_add_func ("/GDateTime/now", test_GDateTime_now);
1261   g_test_add_func ("/GDateTime/printf", test_GDateTime_printf);
1262   g_test_add_func ("/GDateTime/non_utf8_printf", test_non_utf8_printf);
1263   g_test_add_func ("/GDateTime/strftime", test_strftime);
1264   g_test_add_func ("/GDateTime/modifiers", test_modifiers);
1265   g_test_add_func ("/GDateTime/to_local", test_GDateTime_to_local);
1266   g_test_add_func ("/GDateTime/to_unix", test_GDateTime_to_unix);
1267   g_test_add_func ("/GDateTime/to_timeval", test_GDateTime_to_timeval);
1268   g_test_add_func ("/GDateTime/to_utc", test_GDateTime_to_utc);
1269   g_test_add_func ("/GDateTime/now_utc", test_GDateTime_now_utc);
1270   g_test_add_func ("/GDateTime/dst", test_GDateTime_dst);
1271   g_test_add_func ("/GDateTime/test_z", test_z);
1272   g_test_add_func ("/GDateTime/test-all-dates", test_all_dates);
1273
1274   return g_test_run ();
1275 }