datetime: Clean up macros and unused variables
[platform/upstream/glib.git] / glib / gdatetime.c
1 /* gdatetime.c
2  *
3  * Copyright (C) 2009-2010 Christian Hergert <chris@dronelabs.com>
4  * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
5  * Copyright (C) 2010 Emmanuele Bassi <ebassi@linux.intel.com>
6  *
7  * This is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 /* Algorithms within this file are based on the Calendar FAQ by
23  * Claus Tondering.  It can be found at
24  * http://www.tondering.dk/claus/cal/calendar29.txt
25  *
26  * Copyright and disclaimer
27  * ------------------------
28  *   This document is Copyright (C) 2008 by Claus Tondering.
29  *   E-mail: claus@tondering.dk. (Please include the word
30  *   "calendar" in the subject line.)
31  *   The document may be freely distributed, provided this
32  *   copyright notice is included and no money is charged for
33  *   the document.
34  *
35  *   This document is provided "as is". No warranties are made as
36  *   to its correctness.
37  */
38
39 #include "config.h"
40
41 #include "glib.h"
42
43 #include <stdlib.h>
44 #include <string.h>
45
46 #ifdef HAVE_UNISTD_H
47 #include <unistd.h>
48 #endif
49
50 #ifndef G_OS_WIN32
51 #include <sys/time.h>
52 #include <time.h>
53 #endif /* !G_OS_WIN32 */
54
55 #include "glibintl.h"
56
57 #include "gdatetime.h"
58
59 /**
60  * SECTION:date-time
61  * @title: GDateTime
62  * @short_description: A Date and Time structure
63  *
64  * #GDateTime is a structure that combines a date and time into a single
65  * structure. It provides many conversion and methods to manipulate dates
66  * and times. Time precision is provided down to microseconds.
67  *
68  * #GDateTime is an immutable object: once it has been created it cannot be
69  * modified further. All modifiers will create a new #GDateTime.
70  *
71  * #GDateTime is reference counted: the reference count is increased by calling
72  * g_date_time_ref() and decreased by calling g_date_time_unref(). When the
73  * reference count drops to 0, the resources allocated by the #GDateTime
74  * structure are released.
75  *
76  * Internally, #GDateTime uses the Julian Day Number since the
77  * initial Julian Period (-4712 BC). However, the public API uses the
78  * internationally accepted Gregorian Calendar.
79  *
80  * #GDateTime is available since GLib 2.26.
81  */
82
83 #define USEC_PER_SECOND      (G_GINT64_CONSTANT (1000000))
84 #define USEC_PER_MINUTE      (G_GINT64_CONSTANT (60000000))
85 #define USEC_PER_HOUR        (G_GINT64_CONSTANT (3600000000))
86 #define USEC_PER_MILLISECOND (G_GINT64_CONSTANT (1000))
87 #define USEC_PER_DAY         (G_GINT64_CONSTANT (86400000000))
88
89 #define GREGORIAN_LEAP(y)    (((y % 4) == 0) && (!(((y % 100) == 0) && ((y % 400) != 0))))
90 #define JULIAN_YEAR(d)       ((d)->julian / 365.25)
91 #define DAYS_PER_PERIOD      (G_GINT64_CONSTANT (2914695))
92
93 #define GET_AMPM(d,l)         ((g_date_time_get_hour (d) < 12)  \
94                                 ? (l ? C_("GDateTime", "am") : C_("GDateTime", "AM"))       \
95                                 : (l ? C_("GDateTime", "pm") : C_("GDateTime", "PM")))
96
97 #define WEEKDAY_ABBR(d)       (get_weekday_name_abbr (g_date_time_get_day_of_week (datetime)))
98 #define WEEKDAY_FULL(d)       (get_weekday_name (g_date_time_get_day_of_week (datetime)))
99
100 #define MONTH_ABBR(d)         (get_month_name_abbr (g_date_time_get_month (datetime)))
101 #define MONTH_FULL(d)         (get_month_name (g_date_time_get_month (datetime)))
102
103 /* Translators: this is the preferred format for expressing the date */
104 #define GET_PREFERRED_DATE(d) (g_date_time_printf ((d), C_("GDateTime", "%m/%d/%y")))
105
106 /* Translators: this is the preferred format for expressing the time */
107 #define GET_PREFERRED_TIME(d) (g_date_time_printf ((d), C_("GDateTime", "%H:%M:%S")))
108
109 typedef struct _GTimeZone       GTimeZone;
110
111 struct _GDateTime
112 {
113   /* Julian Period, 0 is Initial Epoch */
114   gint period  :  3;
115
116   /* Day within Julian Period */
117   guint julian : 22;
118
119   /* Microsecond timekeeping within Day */
120   guint64 usec : 37;
121
122   gint reserved : 2;
123
124   /* TimeZone information, NULL is UTC */
125   GTimeZone *tz;
126
127   volatile gint ref_count;
128 };
129
130 struct _GTimeZone
131 {
132   /* TZ abbreviation (e.g. PST) */
133   gchar  *name;
134
135   gint64 offset;
136
137   guint is_dst : 1;
138 };
139
140 static const guint16 days_in_months[2][13] =
141 {
142   { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
143   { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
144 };
145
146 static const guint16 days_in_year[2][13] =
147 {
148   {  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
149   {  0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
150 };
151
152 static const gchar *
153 get_month_name (gint month)
154 {
155   switch (month)
156     {
157     case 1:
158       return C_("GDateTime", "January");
159     case 2:
160       return C_("GDateTime", "February");
161     case 3:
162       return C_("GDateTime", "March");
163     case 4:
164       return C_("GDateTime", "April");
165     case 5:
166       return C_("GDateTime", "May");
167     case 6:
168       return C_("GDateTime", "June");
169     case 7:
170       return C_("GDateTime", "July");
171     case 8:
172       return C_("GDateTime", "August");
173     case 9:
174       return C_("GDateTime", "September");
175     case 10:
176       return C_("GDateTime", "October");
177     case 11:
178       return C_("GDateTime", "November");
179     case 12:
180       return C_("GDateTime", "December");
181
182     default:
183       g_warning ("Invalid month number %d", month);
184     }
185
186   return NULL;
187 }
188
189 static const gchar *
190 get_month_name_abbr (gint month)
191 {
192   switch (month)
193     {
194     case 1:
195       return C_("GDateTime", "Jan");
196     case 2:
197       return C_("GDateTime", "Feb");
198     case 3:
199       return C_("GDateTime", "Mar");
200     case 4:
201       return C_("GDateTime", "Apr");
202     case 5:
203       return C_("GDateTime", "May");
204     case 6:
205       return C_("GDateTime", "Jun");
206     case 7:
207       return C_("GDateTime", "Jul");
208     case 8:
209       return C_("GDateTime", "Aug");
210     case 9:
211       return C_("GDateTime", "Sep");
212     case 10:
213       return C_("GDateTime", "Oct");
214     case 11:
215       return C_("GDateTime", "Nov");
216     case 12:
217       return C_("GDateTime", "Dec");
218
219     default:
220       g_warning ("Invalid month number %d", month);
221     }
222
223   return NULL;
224 }
225
226 static const gchar *
227 get_weekday_name (gint day)
228 {
229   switch (day)
230     {
231     case 1:
232       return C_("GDateTime", "Monday");
233     case 2:
234       return C_("GDateTime", "Tuesday");
235     case 3:
236       return C_("GDateTime", "Wednesday");
237     case 4:
238       return C_("GDateTime", "Thursday");
239     case 5:
240       return C_("GDateTime", "Friday");
241     case 6:
242       return C_("GDateTime", "Saturday");
243     case 7:
244       return C_("GDateTime", "Sunday");
245
246     default:
247       g_warning ("Invalid week day number %d", day);
248     }
249
250   return NULL;
251 }
252
253 static const gchar *
254 get_weekday_name_abbr (gint day)
255 {
256   switch (day)
257     {
258     case 1:
259       return C_("GDateTime", "Mon");
260     case 2:
261       return C_("GDateTime", "Tue");
262     case 3:
263       return C_("GDateTime", "Wed");
264     case 4:
265       return C_("GDateTime", "Thu");
266     case 5:
267       return C_("GDateTime", "Fri");
268     case 6:
269       return C_("GDateTime", "Sat");
270     case 7:
271       return C_("GDateTime", "Sun");
272
273     default:
274       g_warning ("Invalid week day number %d", day);
275     }
276
277   return NULL;
278 }
279
280 static inline void
281 g_date_time_add_days_internal (GDateTime *datetime,
282                                gint64     days)
283 {
284   gint __day = datetime->julian + days;
285   if (__day < 1)
286     {
287       datetime->period += -1 + (__day / DAYS_PER_PERIOD);
288       datetime->period += DAYS_PER_PERIOD + (__day % DAYS_PER_PERIOD);
289     }
290   else if (__day > DAYS_PER_PERIOD)
291     {
292       datetime->period += (datetime->julian + days) / DAYS_PER_PERIOD;
293       datetime->julian = (datetime->julian + days) % DAYS_PER_PERIOD;
294     }
295   else
296     datetime->julian += days;
297 }
298
299 static inline void
300 g_date_time_add_usec (GDateTime *datetime,
301                       gint64     usecs)
302 {
303   gint64 __usec = datetime->usec + usecs;
304   gint __days = __usec / USEC_PER_DAY;
305
306   if (__usec < 0)
307     __days -= 1;
308
309   if (__days != 0)
310     g_date_time_add_days_internal (datetime, __days);
311
312   if (__usec < 0)
313     datetime->usec = USEC_PER_DAY + (__usec % USEC_PER_DAY);
314   else
315     datetime->usec = __usec % USEC_PER_DAY;
316 }
317
318 #define ZONEINFO_DIR            "zoneinfo"
319 #define TZ_MAGIC                "TZif"
320 #define TZ_MAGIC_LEN            (strlen (TZ_MAGIC))
321 #define TZ_HEADER_SIZE          44
322 #define TZ_TIMECNT_OFFSET       32
323 #define TZ_TYPECNT_OFFSET       36
324 #define TZ_TRANSITIONS_OFFSET   44
325
326 #define TZ_TTINFO_SIZE          6
327 #define TZ_TTINFO_GMTOFF_OFFSET 0
328 #define TZ_TTINFO_ISDST_OFFSET  4
329 #define TZ_TTINFO_NAME_OFFSET   5
330
331 static gchar *
332 get_tzdata_path (const gchar *tz_name)
333 {
334   gchar *retval;
335
336   if (tz_name != NULL)
337     {
338       const gchar *tz_dir = g_getenv ("TZDIR");
339
340       if (tz_dir != NULL)
341         retval = g_build_filename (tz_dir, tz_name, NULL);
342       else
343         retval = g_build_filename ("/", "usr", "share", ZONEINFO_DIR, tz_name, NULL);
344     }
345   else
346     {
347       /* an empty tz_name means "the current timezone file". tzset(3) defines
348        * it to be /usr/share/zoneinfo/localtime, and it also allows an
349        * /etc/localtime as a symlink to the localtime file under
350        * /usr/share/zoneinfo or to the correct timezone file. Fedora does not
351        * have /usr/share/zoneinfo/localtime, but it does have a real
352        * /etc/localtime.
353        *
354        * in any case, this path should resolve correctly.
355        */
356       retval = g_build_filename ("/", "etc", "localtime", NULL);
357     }
358
359   return retval;
360 }
361
362 /*
363  * Parses tzdata database times to get timezone info.
364  *
365  * @tzname: Olson database name for the timezone
366  * @start: Time offset from epoch we want to know the timezone
367  * @_is_dst: Returns if this time in the timezone is in DST
368  * @_offset: Returns the offset from UTC for this timezone
369  * @_name: Returns the abreviated name for thie timezone
370  */
371 static gboolean
372 parse_tzdata (const gchar  *tzname,
373               gint64        start,
374               gboolean      is_utc,
375               gboolean     *_is_dst,
376               gint64       *_offset,
377               gchar       **_name)
378 {
379   gchar *filename, *contents;
380   gsize length;
381   guint32 timecnt, typecnt;
382   gint transitions_size, ttinfo_map_size;
383   guint8 *ttinfo_map, *ttinfos;
384   gint start_transition = -1;
385   guint32 *transitions;
386   gint32 offset;
387   guint8 isdst;
388   guint8 name_offset;
389   gint i;
390   GError *error;
391
392   filename = get_tzdata_path (tzname);
393
394   /* XXX: should we be caching this in memory for faster access?
395    * and if so, how do we expire the cache?
396    */
397   error = NULL;
398   if (!g_file_get_contents (filename, &contents, &length, &error))
399     {
400       g_free (filename);
401       return FALSE;
402     }
403
404   g_free (filename);
405
406   if (length < TZ_HEADER_SIZE ||
407       (strncmp (contents, TZ_MAGIC, TZ_MAGIC_LEN) != 0))
408     {
409       g_free (contents);
410       return FALSE;
411     }
412
413   timecnt = GUINT32_FROM_BE (*(guint32 *)(contents + TZ_TIMECNT_OFFSET));
414   typecnt = GUINT32_FROM_BE (*(guint32 *)(contents + TZ_TYPECNT_OFFSET));
415
416   transitions = (guint32 *)(contents + TZ_TRANSITIONS_OFFSET);
417   transitions_size = timecnt * sizeof (*transitions);
418   ttinfo_map = (void *)(contents + TZ_TRANSITIONS_OFFSET + transitions_size);
419   ttinfo_map_size = timecnt;
420   ttinfos = (void *)(ttinfo_map + ttinfo_map_size);
421
422   /*
423    * Find the first transition that contains the 'start' time
424    */
425   for (i = 1; i < timecnt && start_transition == -1; i++)
426     {
427       gint32 transition_time = GINT32_FROM_BE (transitions[i]);
428
429       /* if is_utc is not set, we need to add this time offset to compare with
430        * start, because it is already on the timezone time */
431       if (!is_utc)
432         {
433           gint32 off;
434
435           off = *(gint32 *)(ttinfos + ttinfo_map[i] * TZ_TTINFO_SIZE +
436                 TZ_TTINFO_GMTOFF_OFFSET);
437           off = GINT32_FROM_BE (off);
438
439           transition_time += off;
440         }
441
442       if (transition_time > start)
443         {
444           start_transition = ttinfo_map[i - 1];
445           break;
446         }
447     }
448
449   if (start_transition == -1)
450     {
451       if (timecnt)
452         start_transition = ttinfo_map[timecnt - 1];
453       else
454         start_transition = 0;
455     }
456
457   /* Copy the data out of the corresponding ttinfo structs */
458   offset = *(gint32 *)(ttinfos + start_transition * TZ_TTINFO_SIZE +
459            TZ_TTINFO_GMTOFF_OFFSET);
460   offset = GINT32_FROM_BE (offset);
461   isdst = *(ttinfos + start_transition * TZ_TTINFO_SIZE +
462           TZ_TTINFO_ISDST_OFFSET);
463   name_offset = *(ttinfos + start_transition * TZ_TTINFO_SIZE +
464                 TZ_TTINFO_NAME_OFFSET);
465
466   if (_name != NULL)
467     *_name = g_strdup ((gchar*) (ttinfos + TZ_TTINFO_SIZE * typecnt + name_offset));
468
469   g_free (contents);
470
471   if (_offset)
472     *_offset = offset;
473
474   if (_is_dst)
475     *_is_dst = isdst;
476
477   return TRUE;
478 }
479
480 /*< internal >
481  * g_time_zone_new_from_epoc:
482  * @tzname: The Olson's database timezone name
483  * @epoch: The epoch offset
484  * @is_utc: If the @epoch is in UTC or already in the @tzname timezone
485  *
486  * Creates a new timezone
487  */
488 static GTimeZone *
489 g_time_zone_new_from_epoch (const gchar *tzname,
490                             gint64       epoch,
491                             gboolean     is_utc)
492 {
493   GTimeZone *tz = NULL;
494   gint64 offset;
495   gboolean is_dst;
496   gchar *name = NULL;
497
498   if (parse_tzdata (tzname, epoch, is_utc, &is_dst, &offset, &name))
499     {
500       tz = g_slice_new (GTimeZone);
501       tz->is_dst = is_dst;
502       tz->offset = offset;
503       tz->name = name;
504     }
505
506   return tz;
507 }
508
509 #define SECS_PER_MINUTE (60)
510 #define SECS_PER_HOUR   (60 * SECS_PER_MINUTE)
511 #define SECS_PER_DAY    (24 * SECS_PER_HOUR)
512 #define SECS_PER_YEAR   (365 * SECS_PER_DAY)
513 #define SECS_PER_JULIAN (DAYS_PER_PERIOD * SECS_PER_DAY)
514
515 static gint64
516 g_date_time_secs_offset (GDateTime * dt)
517 {
518   gint64 secs;
519   gint d, y, h, m, s;
520   gint leaps;
521
522   y = g_date_time_get_year (dt) - 1970;
523   d = g_date_time_get_day_of_year (dt);
524   h = g_date_time_get_hour (dt);
525   m = g_date_time_get_minute (dt);
526   s = g_date_time_get_second (dt);
527
528   /* FIXME this is an approximation */
529   leaps = y / 4;
530
531   secs = 0;
532   secs += y * SECS_PER_YEAR;
533   secs += d * SECS_PER_DAY;
534   secs += leaps * SECS_PER_DAY;
535   secs += h * SECS_PER_HOUR;
536   secs += m * SECS_PER_MINUTE;
537   secs += s;
538
539   return secs;
540 }
541
542 /*< internal >
543  * g_date_time_create_time_zone:
544  * @dt: a #GDateTime
545  * @tzname: the name of the timezone
546  *
547  * Creates a timezone from a #GDateTime (disregarding its own timezone).
548  * This function transforms the #GDateTime into seconds since the epoch
549  * and creates a timezone for it in the @tzname zone.
550  *
551  * Return value: a newly created #GTimeZone
552  */
553 static GTimeZone *
554 g_date_time_create_time_zone (GDateTime   *dt,
555                               const gchar *tzname)
556 {
557   gint64 secs;
558
559   secs = g_date_time_secs_offset (dt);
560
561   return g_time_zone_new_from_epoch (tzname, secs, FALSE);
562 }
563
564 static GDateTime *
565 g_date_time_new (void)
566 {
567   GDateTime *datetime;
568
569   datetime = g_slice_new0 (GDateTime);
570   datetime->ref_count = 1;
571
572   return datetime;
573 }
574
575 static GTimeZone *
576 g_time_zone_copy (const GTimeZone *timezone)
577 {
578   GTimeZone *tz;
579
580   if (G_UNLIKELY (timezone == NULL))
581     return NULL;
582
583   tz = g_slice_new (GTimeZone);
584   memcpy (tz, timezone, sizeof (GTimeZone));
585
586   tz->name = g_strdup (timezone->name);
587
588   return tz;
589 }
590
591 static void
592 g_time_zone_free (GTimeZone *timezone)
593 {
594   if (G_LIKELY (timezone != NULL))
595     {
596       g_free (timezone->name);
597       g_slice_free (GTimeZone, timezone);
598     }
599 }
600
601 static void
602 g_date_time_free (GDateTime *datetime)
603 {
604   if (G_UNLIKELY (datetime == NULL))
605     return;
606
607   if (datetime->tz)
608     g_time_zone_free (datetime->tz);
609
610   g_slice_free (GDateTime, datetime);
611 }
612
613 static void
614 g_date_time_get_week_number (const GDateTime *datetime,
615                              gint            *week_number,
616                              gint            *day_of_week,
617                              gint            *day_of_year)
618 {
619   gint a, b, c, d, e, f, g, n, s, month, day, year;
620
621   g_date_time_get_dmy (datetime, &day, &month, &year);
622
623   if (month <= 2)
624     {
625       a = g_date_time_get_year (datetime) - 1;
626       b = (a / 4) - (a / 100) + (a / 400);
627       c = ((a - 1) / 4) - ((a - 1) / 100) + ((a - 1) / 400);
628       s = b - c;
629       e = 0;
630       f = day - 1 + (31 * (month - 1));
631     }
632   else
633     {
634       a = year;
635       b = (a / 4) - (a / 100) + (a / 400);
636       c = ((a - 1) / 4) - ((a - 1) / 100) + ((a - 1) / 400);
637       s = b - c;
638       e = s + 1;
639       f = day + (((153 * (month - 3)) + 2) / 5) + 58 + s;
640     }
641
642   g = (a + b) % 7;
643   d = (f + g - e) % 7;
644   n = f + 3 - d;
645
646   if (week_number)
647     {
648       if (n < 0)
649         *week_number = 53 - ((g - s) / 5);
650       else if (n > 364 + s)
651         *week_number = 1;
652       else
653         *week_number = (n / 7) + 1;
654     }
655
656   if (day_of_week)
657     *day_of_week = d + 1;
658
659   if (day_of_year)
660     *day_of_year = f + 1;
661 }
662
663 /**
664  * g_date_time_add:
665  * @datetime: a #GDateTime
666  * @timespan: a #GTimeSpan
667  *
668  * Creates a copy of @datetime and adds the specified timespan to the copy.
669  *
670  * Return value: the newly created #GDateTime which should be freed with
671  *   g_date_time_unref().
672  *
673  * Since: 2.26
674  */
675 GDateTime*
676 g_date_time_add (const GDateTime *datetime,
677                  GTimeSpan        timespan)
678 {
679   GDateTime *dt;
680
681   g_return_val_if_fail (datetime != NULL, NULL);
682
683   dt = g_date_time_copy (datetime);
684   g_date_time_add_usec (dt, timespan);
685
686   return dt;
687 }
688
689 /**
690  * g_date_time_add_years:
691  * @datetime: a #GDateTime
692  * @years: the number of years
693  *
694  * Creates a copy of @datetime and adds the specified number of years to the
695  * copy.
696  *
697  * Return value: the newly created #GDateTime which should be freed with
698  *   g_date_time_unref().
699  *
700  * Since: 2.26
701  */
702 GDateTime*
703 g_date_time_add_years (const GDateTime *datetime,
704                        gint             years)
705 {
706   GDateTime *dt;
707   gint       day;
708
709   g_return_val_if_fail (datetime != NULL, NULL);
710
711   day = g_date_time_get_day_of_month (datetime);
712   if (g_date_time_is_leap_year (datetime) &&
713       g_date_time_get_month (datetime) == 2)
714     {
715       if (day == 29)
716         day--;
717     }
718
719   dt = g_date_time_new_from_date (g_date_time_get_year (datetime) + years,
720                                   g_date_time_get_month (datetime),
721                                   day);
722   dt->usec = datetime->usec;
723
724   return dt;
725 }
726
727 /**
728  * g_date_time_add_months:
729  * @datetime: a #GDateTime
730  * @months: the number of months
731  *
732  * Creates a copy of @datetime and adds the specified number of months to the
733  * copy.
734  *
735  * Return value: the newly created #GDateTime which should be freed with
736  *   g_date_time_unref().
737  *
738  * Since: 2.26
739  */
740 GDateTime*
741 g_date_time_add_months (const GDateTime *datetime,
742                         gint             months)
743 {
744   GDateTime     *dt;
745   gint           year,
746                  month,
747                  day,
748                  i,
749                  a;
750   const guint16 *days;
751
752   g_return_val_if_fail (datetime != NULL, NULL);
753   g_return_val_if_fail (months != 0, NULL);
754
755   month = g_date_time_get_month (datetime);
756   year = g_date_time_get_year (datetime);
757   a = months > 0 ? 1 : -1;
758
759   for (i = 0; i < ABS (months); i++)
760     {
761       month += a;
762       if (month < 1)
763         {
764           year--;
765           month = 12;
766         }
767       else if (month > 12)
768         {
769           year++;
770           month = 1;
771         }
772     }
773
774   day = g_date_time_get_day_of_month (datetime);
775   days = days_in_months [GREGORIAN_LEAP (year) ? 1 : 0];
776
777   if (days[month] < day)
778     day = days[month];
779
780   dt = g_date_time_new_from_date (year, month, day);
781   dt->usec = datetime->usec;
782
783   return dt;
784 }
785
786 /**
787  * g_date_time_add_weeks:
788  * @datetime: a #GDateTime
789  * @weeks: the number of weeks
790  *
791  * Creates a copy of @datetime and adds the specified number of weeks to the
792  * copy.
793  *
794  * Return value: the newly created #GDateTime which should be freed with
795  *   g_date_time_unref().
796  *
797  * Since: 2.26
798  */
799 GDateTime*
800 g_date_time_add_weeks (const GDateTime *datetime,
801                        gint             weeks)
802 {
803   g_return_val_if_fail (datetime != NULL, NULL);
804
805   return g_date_time_add_days (datetime, weeks * 7);
806 }
807
808 /**
809  * g_date_time_add_days:
810  * @datetime: a #GDateTime
811  * @days: the number of days
812  *
813  * Creates a copy of @datetime and adds the specified number of days to the
814  * copy.
815  *
816  * Return value: the newly created #GDateTime which should be freed with
817  *   g_date_time_unref().
818  *
819  * Since: 2.26
820  */
821 GDateTime*
822 g_date_time_add_days (const GDateTime *datetime,
823                       gint             days)
824 {
825   GDateTime *dt;
826
827   g_return_val_if_fail (datetime != NULL, NULL);
828
829   dt = g_date_time_copy (datetime);
830   g_date_time_add_days_internal (dt, days);
831
832   return dt;
833 }
834
835 /**
836  * g_date_time_add_hours:
837  * @datetime: a #GDateTime
838  * @hours: the number of hours to add
839  *
840  * Creates a copy of @datetime and adds the specified number of hours
841  *
842  * Return value: the newly created #GDateTime which should be freed with
843  *   g_date_time_unref().
844  *
845  * Since: 2.26
846  */
847 GDateTime*
848 g_date_time_add_hours (const GDateTime *datetime,
849                        gint             hours)
850 {
851   GDateTime *dt;
852
853   g_return_val_if_fail (datetime != NULL, NULL);
854
855   dt = g_date_time_copy (datetime);
856   g_date_time_add_usec (dt, (gint64) hours * USEC_PER_HOUR);
857
858   return dt;
859 }
860
861 /**
862  * g_date_time_add_seconds:
863  * @datetime: a #GDateTime
864  * @seconds: the number of seconds to add
865  *
866  * Creates a copy of @datetime and adds the specified number of seconds.
867  *
868  * Return value: the newly created #GDateTime which should be freed with
869  *   g_date_time_unref().
870  *
871  * Since: 2.26
872  */
873 GDateTime*
874 g_date_time_add_seconds (const GDateTime *datetime,
875                          gint             seconds)
876 {
877   GDateTime *dt;
878
879   g_return_val_if_fail (datetime != NULL, NULL);
880
881   dt = g_date_time_copy (datetime);
882   g_date_time_add_usec (dt, (gint64) seconds * USEC_PER_SECOND);
883
884   return dt;
885 }
886
887 /**
888  * g_date_time_add_milliseconds:
889  * @datetime: a #GDateTime
890  * @milliseconds: the number of milliseconds to add
891  *
892  * Creates a copy of @datetime adding the specified number of milliseconds.
893  *
894  * Return value: the newly created #GDateTime which should be freed with
895  *   g_date_time_unref().
896  *
897  * Since: 2.26
898  */
899 GDateTime*
900 g_date_time_add_milliseconds (const GDateTime *datetime,
901                               gint             milliseconds)
902 {
903   GDateTime *dt;
904
905   g_return_val_if_fail (datetime != NULL, NULL);
906
907   dt = g_date_time_copy (datetime);
908   g_date_time_add_usec (dt, (gint64) milliseconds * USEC_PER_MILLISECOND);
909
910   return dt;
911 }
912
913 /**
914  * g_date_time_add_minutes:
915  * @datetime: a #GDateTime
916  * @minutes: the number of minutes to add
917  *
918  * Creates a copy of @datetime adding the specified number of minutes.
919  *
920  * Return value: the newly created #GDateTime which should be freed with
921  *   g_date_time_unref().
922  *
923  * Since: 2.26
924  */
925 GDateTime*
926 g_date_time_add_minutes (const GDateTime *datetime,
927                          gint             minutes)
928 {
929   GDateTime *dt;
930
931   g_return_val_if_fail (datetime != NULL, NULL);
932
933   dt = g_date_time_copy (datetime);
934   g_date_time_add_usec (dt, (gint64) minutes * USEC_PER_MINUTE);
935
936   return dt;
937 }
938
939 /**
940  * g_date_time_add_full:
941  * @datetime: a #GDateTime
942  * @years: the number of years to add
943  * @months: the number of months to add
944  * @days: the number of days to add
945  * @hours: the number of hours to add
946  * @minutes: the number of minutes to add
947  * @seconds: the number of seconds to add
948  *
949  * Creates a new #GDateTime adding the specified values to the current date and
950  * time in @datetime.
951  *
952  * Return value: the newly created #GDateTime that should be freed with
953  *   g_date_time_unref().
954  *
955  * Since: 2.26
956  */
957 GDateTime *
958 g_date_time_add_full (const GDateTime *datetime,
959                       gint             years,
960                       gint             months,
961                       gint             days,
962                       gint             hours,
963                       gint             minutes,
964                       gint             seconds)
965 {
966   GDateTime *tmp, *dt;
967
968   g_return_val_if_fail (datetime != NULL, NULL);
969
970   dt = g_date_time_add_years (datetime, years);
971   tmp = dt;
972
973   dt = g_date_time_add_months (tmp, months);
974   g_date_time_unref (tmp);
975   tmp = dt;
976
977   dt = g_date_time_add_days (tmp, days);
978   g_date_time_unref (tmp);
979   tmp = dt;
980
981   dt = g_date_time_add_hours (tmp, hours);
982   g_date_time_unref (tmp);
983   tmp = dt;
984
985   dt = g_date_time_add_minutes (tmp, minutes);
986   g_date_time_unref (tmp);
987   tmp = dt;
988
989   dt = g_date_time_add_seconds (tmp, seconds);
990   g_date_time_unref (tmp);
991
992   return dt;
993 }
994
995 /**
996  * g_date_time_compare:
997  * @dt1: first #GDateTime to compare
998  * @dt2: second #GDateTime to compare
999  *
1000  * qsort()-style comparison for #GDateTime<!-- -->'s. Both #GDateTime<-- -->'s
1001  * must be non-%NULL.
1002  *
1003  * Return value: 0 for equal, less than zero if dt1 is less than dt2, greater
1004  *   than zero if dt2 is greator than dt1.
1005  *
1006  * Since: 2.26
1007  */
1008 gint
1009 g_date_time_compare (gconstpointer dt1,
1010                      gconstpointer dt2)
1011 {
1012   const GDateTime *a, *b;
1013
1014   a = dt1;
1015   b = dt2;
1016
1017   if ((a->period == b->period) &&
1018       (a->julian == b->julian) &&
1019       (a->usec == b->usec))
1020     {
1021       return 0;
1022     }
1023   else if ((a->period > b->period) ||
1024            ((a->period == b->period) && (a->julian > b->julian)) ||
1025            ((a->period == b->period) && (a->julian == b->julian) && a->usec > b->usec))
1026     {
1027       return 1;
1028     }
1029   else
1030     return -1;
1031 }
1032
1033 /**
1034  * g_date_time_copy:
1035  * @datetime: a #GDateTime
1036  *
1037  * Creates a copy of @datetime.
1038  *
1039  * Return value: the newly created #GDateTime which should be freed with
1040  *   g_date_time_unref().
1041  *
1042  * Since: 2.26
1043  */
1044 GDateTime*
1045 g_date_time_copy (const GDateTime *datetime)
1046 {
1047   GDateTime *copied;
1048
1049   g_return_val_if_fail (datetime != NULL, NULL);
1050
1051   copied = g_date_time_new ();
1052   copied->period = datetime->period;
1053   copied->julian = datetime->julian;
1054   copied->usec = datetime->usec;
1055   copied->tz = g_time_zone_copy (datetime->tz);
1056
1057   return copied;
1058 }
1059
1060 /**
1061  * g_date_time_day:
1062  * @datetime: a #GDateTime
1063  *
1064  * Creates a new #GDateTime at Midnight on the date represented by @datetime.
1065  *
1066  * Return value: the newly created #GDateTime which should be freed with
1067  *   g_date_time_unref().
1068  *
1069  * Since: 2.26
1070  */
1071 GDateTime*
1072 g_date_time_day (const GDateTime *datetime)
1073 {
1074   GDateTime *date;
1075
1076   g_return_val_if_fail (datetime != NULL, NULL);
1077
1078   date = g_date_time_copy (datetime);
1079   date->usec = 0;
1080
1081   return date;
1082 }
1083
1084 /**
1085  * g_date_time_difference:
1086  * @begin: a #GDateTime
1087  * @end: a #GDateTime
1088  *
1089  * Calculates the known difference in time between @begin and @end.
1090  *
1091  * Since the exact precision cannot always be known due to incomplete
1092  * historic information, an attempt is made to calculate the difference.
1093  *
1094  * Return value: the difference between the two #GDateTime, as a time
1095  *   span expressed in microseconds.
1096  *
1097  * Since: 2.26
1098  */
1099 GTimeSpan
1100 g_date_time_difference (const GDateTime *begin,
1101                         const GDateTime *end)
1102 {
1103   g_return_val_if_fail (begin != NULL, 0);
1104   g_return_val_if_fail (end != NULL, 0);
1105
1106   if (begin->period != 0 || end->period != 0)
1107     {
1108       g_warning ("GDateTime only supports the current Julian period");
1109       return 0;
1110     }
1111
1112   return ((end->julian - begin->julian) * USEC_PER_DAY) + (end->usec - begin->usec);
1113 }
1114
1115 /**
1116  * g_date_time_equal:
1117  * @dt1: a #GDateTime
1118  * @dt2: a #GDateTime
1119  *
1120  * Checks to see if @dt1 and @dt2 are equal.
1121  *
1122  * Equal here means that they represent the same moment after converting
1123  * them to the same timezone.
1124  *
1125  * Return value: %TRUE if @dt1 and @dt2 are equal
1126  *
1127  * Since: 2.26
1128  */
1129 gboolean
1130 g_date_time_equal (gconstpointer dt1,
1131                    gconstpointer dt2)
1132 {
1133   const GDateTime *a, *b;
1134   GDateTime *a_utc, *b_utc;
1135   gint64 a_epoch, b_epoch;
1136
1137   a = dt1;
1138   b = dt2;
1139
1140   a_utc = g_date_time_to_utc ((GDateTime *) a);
1141   b_utc = g_date_time_to_utc ((GDateTime *) b);
1142
1143   a_epoch = g_date_time_to_epoch (a_utc);
1144   b_epoch = g_date_time_to_epoch (b_utc);
1145
1146   g_date_time_unref (a_utc);
1147   g_date_time_unref (b_utc);
1148
1149   return a_epoch == b_epoch;
1150 }
1151
1152 /**
1153  * g_date_time_get_day_of_week:
1154  * @datetime: a #GDateTime
1155  *
1156  * Retrieves the day of the week represented by @datetime within the gregorian
1157  * calendar. 1 is Sunday, 2 is Monday, etc.
1158  *
1159  * Return value: the day of the week
1160  *
1161  * Since: 2.26
1162  */
1163 gint
1164 g_date_time_get_day_of_week (const GDateTime *datetime)
1165 {
1166   gint a, y, m,
1167        year  = 0,
1168        month = 0,
1169        day   = 0,
1170        dow;
1171
1172   g_return_val_if_fail (datetime != NULL, 0);
1173
1174   /*
1175    * See Calendar FAQ Section 2.6 for algorithm information
1176    * http://www.tondering.dk/claus/cal/calendar29.txt
1177    */
1178
1179   g_date_time_get_dmy (datetime, &day, &month, &year);
1180   a = (14 - month) / 12;
1181   y = year - a;
1182   m = month + (12 * a) - 2;
1183   dow = ((day + y + (y / 4) - (y / 100) + (y / 400) + (31 * m) / 12) % 7);
1184
1185   /* 1 is Monday and 7 is Sunday */
1186   return (dow == 0) ? 7 : dow;
1187 }
1188
1189 /**
1190  * g_date_time_get_day_of_month:
1191  * @datetime: a #GDateTime
1192  *
1193  * Retrieves the day of the month represented by @datetime in the gregorian
1194  * calendar.
1195  *
1196  * Return value: the day of the month
1197  *
1198  * Since: 2.26
1199  */
1200 gint
1201 g_date_time_get_day_of_month (const GDateTime *datetime)
1202 {
1203   gint           day_of_year,
1204                  i;
1205   const guint16 *days;
1206   guint16        last = 0;
1207
1208   g_return_val_if_fail (datetime != NULL, 0);
1209
1210   days = days_in_year[g_date_time_is_leap_year (datetime) ? 1 : 0];
1211   g_date_time_get_week_number (datetime, NULL, NULL, &day_of_year);
1212
1213   for (i = 1; i <= 12; i++)
1214     {
1215       if (days [i] >= day_of_year)
1216         return day_of_year - last;
1217       last = days [i];
1218     }
1219
1220   g_warn_if_reached ();
1221   return 0;
1222 }
1223
1224 /**
1225  * g_date_time_get_day_of_year:
1226  * @datetime: a #GDateTime
1227  *
1228  * Retrieves the day of the year represented by @datetime in the Gregorian
1229  * calendar.
1230  *
1231  * Return value: the day of the year
1232  *
1233  * Since: 2.26
1234  */
1235 gint
1236 g_date_time_get_day_of_year (const GDateTime *datetime)
1237 {
1238   gint doy = 0;
1239
1240   g_return_val_if_fail (datetime != NULL, 0);
1241
1242   g_date_time_get_week_number (datetime, NULL, NULL, &doy);
1243   return doy;
1244 }
1245
1246 /**
1247  * g_date_time_get_dmy:
1248  * @datetime: a #GDateTime.
1249  * @day: (out): the return location for the day of the month, or %NULL.
1250  * @month: (out): the return location for the monty of the year, or %NULL.
1251  * @year: (out): the return location for the gregorian year, or %NULL.
1252  *
1253  * Retrieves the Gregorian day, month, and year of a given #GDateTime.
1254  *
1255  * Since: 2.26
1256  */
1257 void
1258 g_date_time_get_dmy (const GDateTime *datetime,
1259                      gint            *day,
1260                      gint            *month,
1261                      gint            *year)
1262 {
1263   gint a, b, c, d, e, m;
1264
1265   a = datetime->julian + 32044;
1266   b = ((4 * a) + 3) / 146097;
1267   c = a - ((b * 146097) / 4);
1268   d = ((4 * c) + 3) / 1461;
1269   e = c - (1461 * d) / 4;
1270   m = (5 * e + 2) / 153;
1271
1272   if (day != NULL)
1273     *day = e - (((153 * m) + 2) / 5) + 1;
1274
1275   if (month != NULL)
1276     *month = m + 3 - (12 * (m / 10));
1277
1278   if (year != NULL)
1279     *year  = (b * 100) + d - 4800 + (m / 10);
1280 }
1281
1282 /**
1283  * g_date_time_get_hour:
1284  * @datetime: a #GDateTime
1285  *
1286  * Retrieves the hour of the day represented by @datetime
1287  *
1288  * Return value: the hour of the day
1289  *
1290  * Since: 2.26
1291  */
1292 gint
1293 g_date_time_get_hour (const GDateTime *datetime)
1294 {
1295   g_return_val_if_fail (datetime != NULL, 0);
1296
1297   return (datetime->usec / USEC_PER_HOUR);
1298 }
1299
1300 /**
1301  * g_date_time_get_julian:
1302  * @datetime: a #GDateTime
1303  * @period: (out): a location for the Julian period
1304  * @julian: (out): a location for the day in the Julian period
1305  * @hour: (out): a location for the hour of the day
1306  * @minute: (out): a location for the minute of the hour
1307  * @second: (out): a location for hte second of the minute
1308  *
1309  * Retrieves the Julian period, day, hour, minute, and second which @datetime
1310  * represents in the Julian calendar.
1311  *
1312  * Since: 2.26
1313  */
1314 void
1315 g_date_time_get_julian (const GDateTime *datetime,
1316                         gint            *period,
1317                         gint            *julian,
1318                         gint            *hour,
1319                         gint            *minute,
1320                         gint            *second)
1321 {
1322   g_return_if_fail (datetime != NULL);
1323
1324   if (period)
1325     *period = datetime->period;
1326
1327   if (julian)
1328     *julian = datetime->julian;
1329
1330   if (hour)
1331     *hour = (datetime->usec / USEC_PER_HOUR);
1332
1333   if (minute)
1334     *minute = (datetime->usec % USEC_PER_HOUR) / USEC_PER_MINUTE;
1335
1336   if (second)
1337     *second = (datetime->usec % USEC_PER_MINUTE) / USEC_PER_SECOND;
1338 }
1339
1340 /**
1341  * g_date_time_get_microsecond:
1342  * @datetime: a #GDateTime
1343  *
1344  * Retrieves the microsecond of the date represented by @datetime
1345  *
1346  * Return value: the microsecond of the second
1347  *
1348  * Since: 2.26
1349  */
1350 gint
1351 g_date_time_get_microsecond (const GDateTime *datetime)
1352 {
1353   g_return_val_if_fail (datetime != NULL, 0);
1354
1355   return (datetime->usec % USEC_PER_SECOND);
1356 }
1357
1358 /**
1359  * g_date_time_get_millisecond:
1360  * @datetime: a #GDateTime
1361  *
1362  * Retrieves the millisecond of the date represented by @datetime
1363  *
1364  * Return value: the millisecond of the second
1365  *
1366  * Since: 2.26
1367  */
1368 gint
1369 g_date_time_get_millisecond (const GDateTime *datetime)
1370 {
1371   g_return_val_if_fail (datetime != NULL, 0);
1372
1373   return (datetime->usec % USEC_PER_SECOND) / USEC_PER_MILLISECOND;
1374 }
1375
1376 /**
1377  * g_date_time_get_minute:
1378  * @datetime: a #GDateTime
1379  *
1380  * Retrieves the minute of the hour represented by @datetime
1381  *
1382  * Return value: the minute of the hour
1383  *
1384  * Since: 2.26
1385  */
1386 gint
1387 g_date_time_get_minute (const GDateTime *datetime)
1388 {
1389   g_return_val_if_fail (datetime != NULL, 0);
1390
1391   return (datetime->usec % USEC_PER_HOUR) / USEC_PER_MINUTE;
1392 }
1393
1394 /**
1395  * g_date_time_get_month:
1396  * @datetime: a #GDateTime
1397  *
1398  * Retrieves the month of the year represented by @datetime in the Gregorian
1399  * calendar.
1400  *
1401  * Return value: the month represented by @datetime
1402  *
1403  * Since: 2.26
1404  */
1405 gint
1406 g_date_time_get_month (const GDateTime *datetime)
1407 {
1408   gint month;
1409
1410   g_return_val_if_fail (datetime != NULL, 0);
1411
1412   g_date_time_get_dmy (datetime, NULL, &month, NULL);
1413
1414   return month;
1415 }
1416
1417 /**
1418  * g_date_time_get_second:
1419  * @datetime: a #GDateTime
1420  *
1421  * Retrieves the second of the minute represented by @datetime
1422  *
1423  * Return value: the second represented by @datetime
1424  *
1425  * Since: 2.26
1426  */
1427 gint
1428 g_date_time_get_second (const GDateTime *datetime)
1429 {
1430   g_return_val_if_fail (datetime != NULL, 0);
1431
1432   return (datetime->usec % USEC_PER_MINUTE) / USEC_PER_SECOND;
1433 }
1434
1435 /**
1436  * g_date_time_get_utc_offset:
1437  * @datetime: a #GDateTime
1438  *
1439  * Retrieves the offset from UTC that the local timezone specified by
1440  * @datetime represents.
1441  *
1442  * If @datetime represents UTC time, then the offset is zero.
1443  *
1444  * Return value: the offset, expressed as a time span expressed in
1445  *   microseconds.
1446  *
1447  * Since: 2.26
1448  */
1449 GTimeSpan
1450 g_date_time_get_utc_offset (const GDateTime *datetime)
1451 {
1452   gint offset = 0;
1453
1454   g_return_val_if_fail (datetime != NULL, 0);
1455
1456   if (datetime->tz != NULL)
1457     offset = datetime->tz->offset;
1458
1459   return (gint64) offset * USEC_PER_SECOND;
1460 }
1461
1462 /**
1463  * g_date_time_get_timezone_name:
1464  * @datetime: a #GDateTime
1465  *
1466  * Retrieves the Olson's database timezone name of the timezone specified
1467  * by @datetime.
1468  *
1469  * Return value: (transfer none): the name of the timezone. The returned
1470  *   string is owned by the #GDateTime and it should not be modified or
1471  *   freed
1472  *
1473  * Since: 2.26
1474  */
1475 G_CONST_RETURN gchar *
1476 g_date_time_get_timezone_name (const GDateTime *datetime)
1477 {
1478   g_return_val_if_fail (datetime != NULL, NULL);
1479
1480   if (datetime->tz != NULL)
1481     return datetime->tz->name;
1482
1483   return "UTC";
1484 }
1485
1486 /**
1487  * g_date_time_get_year:
1488  * @datetime: A #GDateTime
1489  *
1490  * Retrieves the year represented by @datetime in the Gregorian calendar.
1491  *
1492  * Return value: the year represented by @datetime
1493  *
1494  * Since: 2.26
1495  */
1496 gint
1497 g_date_time_get_year (const GDateTime *datetime)
1498 {
1499   gint year;
1500
1501   g_return_val_if_fail (datetime != NULL, 0);
1502
1503   g_date_time_get_dmy (datetime, NULL, NULL, &year);
1504
1505   return year;
1506 }
1507
1508 /**
1509  * g_date_time_hash:
1510  * @datetime: a #GDateTime
1511  *
1512  * Hashes @datetime into a #guint, suitable for use within #GHashTable.
1513  *
1514  * Return value: a #guint containing the hash
1515  *
1516  * Since: 2.26
1517  */
1518 guint
1519 g_date_time_hash (gconstpointer datetime)
1520 {
1521   return (guint) (*((guint64 *) datetime));
1522 }
1523
1524 /**
1525  * g_date_time_is_leap_year:
1526  * @datetime: a #GDateTime
1527  *
1528  * Determines if @datetime represents a date known to fall within
1529  * a leap year in the Gregorian calendar.
1530  *
1531  * Return value: %TRUE if @datetime is a leap year.
1532  *
1533  * Since: 2.26
1534  */
1535 gboolean
1536 g_date_time_is_leap_year (const GDateTime *datetime)
1537 {
1538   gint year;
1539
1540   g_return_val_if_fail (datetime != NULL, FALSE);
1541
1542   year = g_date_time_get_year (datetime);
1543
1544   return GREGORIAN_LEAP (year);
1545 }
1546
1547 /**
1548  * g_date_time_is_daylight_savings:
1549  * @datetime: a #GDateTime
1550  *
1551  * Determines if @datetime represents a date known to fall within daylight
1552  * savings time in the gregorian calendar.
1553  *
1554  * Return value: %TRUE if @datetime falls within daylight savings time.
1555  *
1556  * Since: 2.26
1557  */
1558 gboolean
1559 g_date_time_is_daylight_savings (const GDateTime *datetime)
1560 {
1561   g_return_val_if_fail (datetime != NULL, FALSE);
1562
1563   if (!datetime->tz)
1564     return FALSE;
1565
1566   return datetime->tz->is_dst;
1567 }
1568
1569 static inline gint
1570 date_to_julian (gint year,
1571                 gint month,
1572                 gint day)
1573 {
1574   gint a = (14 - month) / 12;
1575   gint y = year + 4800 - a;
1576   gint m = month + (12 * a) - 3;
1577
1578   return day
1579        + (((153 * m) + 2) / 5)
1580        + (y * 365)
1581        + (y / 4)
1582        - (y / 100)
1583        + (y / 400)
1584        - 32045;
1585 }
1586
1587 /**
1588  * g_date_time_new_from_date:
1589  * @year: the Gregorian year
1590  * @month: the Gregorian month
1591  * @day: the day in the Gregorian month
1592  *
1593  * Creates a new #GDateTime using the specified date within the Gregorian
1594  * calendar.
1595  *
1596  * Return value: the newly created #GDateTime or %NULL if it is outside of
1597  *   the representable range.
1598  *
1599  * Since: 2.26
1600  */
1601 GDateTime *
1602 g_date_time_new_from_date (gint year,
1603                            gint month,
1604                            gint day)
1605 {
1606   GDateTime *dt;
1607
1608   g_return_val_if_fail (year > -4712 && year <= 3268, NULL);
1609   g_return_val_if_fail (month > 0 && month <= 12, NULL);
1610   g_return_val_if_fail (day > 0 && day <= 31, NULL);
1611
1612   dt = g_date_time_new ();
1613   dt->julian = date_to_julian (year, month, day);
1614   dt->tz = g_date_time_create_time_zone (dt, NULL);
1615
1616   return dt;
1617 }
1618
1619 /**
1620  * g_date_time_new_from_epoch:
1621  * @t: seconds from the Unix epoch
1622  *
1623  * Creates a new #GDateTime using the time since Jan 1, 1970 specified by @t.
1624  *
1625  * Return value: the newly created #GDateTime
1626  *
1627  * Since: 2.26
1628  */
1629 GDateTime*
1630 g_date_time_new_from_epoch (gint64 t) /* IN */
1631 {
1632   struct tm tm;
1633   time_t tt;
1634
1635   tt = (time_t) t;
1636   memset (&tm, 0, sizeof (tm));
1637
1638   /* XXX: GLib should probably have a wrapper for this */
1639 #ifdef HAVE_LOCALTIME_R
1640   localtime_r (&tt, &tm);
1641 #else
1642   {
1643     struct tm *ptm = localtime (&timet);
1644
1645     if (ptm == NULL)
1646       {
1647         /* Happens at least in Microsoft's C library if you pass a
1648          * negative time_t. Use 2000-01-01 as default date.
1649          */
1650 #ifndef G_DISABLE_CHECKS
1651         g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, "ptm != NULL");
1652 #endif
1653
1654         tm.tm_mon = 0;
1655         tm.tm_mday = 1;
1656         tm.tm_year = 100;
1657       }
1658     else
1659       memcpy ((void *) &tm, (void *) ptm, sizeof (struct tm));
1660   }
1661 #endif /* HAVE_LOCALTIME_R */
1662
1663   return g_date_time_new_full (tm.tm_year + 1900,
1664                                tm.tm_mon  + 1,
1665                                tm.tm_mday,
1666                                tm.tm_hour,
1667                                tm.tm_min,
1668                                tm.tm_sec,
1669                                NULL);
1670 }
1671
1672 /**
1673  * g_date_time_new_from_timeval:
1674  * @tv: #GTimeVal
1675  *
1676  * Creates a new #GDateTime using the date and time specified by #GTimeVal.
1677  *
1678  * Return value: the newly created #GDateTime
1679  *
1680  * Since: 2.26
1681  */
1682 GDateTime *
1683 g_date_time_new_from_timeval (GTimeVal *tv)
1684 {
1685   GDateTime *datetime;
1686
1687   g_return_val_if_fail (tv != NULL, NULL);
1688
1689   datetime = g_date_time_new_from_epoch (tv->tv_sec);
1690   datetime->usec += tv->tv_usec;
1691   datetime->tz = g_date_time_create_time_zone (datetime, NULL);
1692
1693   return datetime;
1694 }
1695
1696 /**
1697  * g_date_time_new_full:
1698  * @year: the Gregorian year
1699  * @month: the Gregorian month
1700  * @day: the day of the Gregorian month
1701  * @hour: the hour of the day
1702  * @minute: the minute of the hour
1703  * @second: the second of the minute
1704  * @timezone: (allow-none): the Olson's database timezone name, or %NULL
1705  *   for local (e.g. America/New_York)
1706  *
1707  * Creates a new #GDateTime using the date and times in the Gregorian calendar.
1708  *
1709  * Return value: the newly created #GDateTime
1710  *
1711  * Since: 2.26
1712  */
1713 GDateTime *
1714 g_date_time_new_full (gint         year,
1715                       gint         month,
1716                       gint         day,
1717                       gint         hour,
1718                       gint         minute,
1719                       gint         second,
1720                       const gchar *timezone)
1721 {
1722   GDateTime *dt;
1723
1724   g_return_val_if_fail (hour >= 0 && hour < 24, NULL);
1725   g_return_val_if_fail (minute >= 0 && minute < 60, NULL);
1726   g_return_val_if_fail (second >= 0 && second <= 60, NULL);
1727
1728   if ((dt = g_date_time_new_from_date (year, month, day)) == NULL)
1729     return NULL;
1730
1731   dt->usec = (hour   * USEC_PER_HOUR)
1732            + (minute * USEC_PER_MINUTE)
1733            + (second * USEC_PER_SECOND);
1734
1735   dt->tz = g_date_time_create_time_zone (dt, timezone);
1736   if (timezone != NULL && dt->tz == NULL)
1737     {
1738       /* timezone creation failed */
1739       g_date_time_unref (dt);
1740       dt = NULL;
1741     }
1742
1743   return dt;
1744 }
1745
1746 /**
1747  * g_date_time_new_now:
1748  *
1749  * Creates a new #GDateTime representing the current date and time.
1750  *
1751  * Return value: the newly created #GDateTime which should be freed with
1752  *   g_date_time_unref().
1753  *
1754  * Since: 2.26
1755  */
1756 GDateTime*
1757 g_date_time_new_now (void)
1758 {
1759   GTimeVal tv;
1760
1761   g_get_current_time (&tv);
1762
1763   return g_date_time_new_from_timeval (&tv);
1764 }
1765
1766 /**
1767  * g_date_time_printf:
1768  * @datetime: A #GDateTime
1769  * @format: a valid UTF-8 string, containing the format for the #GDateTime
1770  *
1771  * Creates a newly allocated string representing the requested @format.
1772  *
1773  * The following format specifiers are supported:
1774  *
1775  * %%a  The abbreviated weekday name according to the current locale.
1776  * %%A  The full weekday name according to the current locale.
1777  * %%b  The abbreviated month name according to the current locale.
1778  * %%B  The full month name according to the current locale.
1779  * %%d  The day of the month as a decimal number (range 01 to 31).
1780  * %%e  The day of the month as a decimal number (range  1 to 31).
1781  * %%F  Equivalent to %Y-%m-%d (the ISO 8601 date format).
1782  * %%h  Equivalent to %b.
1783  * %%H  The hour as a decimal number using a 24-hour clock (range 00 to 23).
1784  * %%I  The hour as a decimal number using a 12-hour clock (range 01 to 12).
1785  * %%j  The day of the year as a decimal number (range 001 to 366).
1786  * %%k  The hour (24-hour clock) as a decimal number (range 0 to 23);
1787  *      single digits are preceded by a blank.
1788  * %%l  The hour (12-hour clock) as a decimal number (range 1 to 12);
1789  *      single digits are preceded by a blank.
1790  * %%m  The month as a decimal number (range 01 to 12).
1791  * %%M  The minute as a decimal number (range 00 to 59).
1792  * %%N  The micro-seconds as a decimal number.
1793  * %%p  Either "AM" or "PM" according to the given time  value, or the
1794  *      corresponding  strings  for the current locale.  Noon is treated
1795  *      as "PM" and midnight as "AM".
1796  * %%P  Like %%p but lowercase: "am" or "pm" or a corresponding string for
1797  *      the current locale.
1798  * %%r  The time in a.m. or p.m. notation.
1799  * %%R  The time in 24-hour notation (%H:%M).
1800  * %%s  The number of seconds since the Epoch, that is, since 1970-01-01
1801  *      00:00:00 UTC.
1802  * %%S  The second as a decimal number (range 00 to 60).
1803  * %%t  A tab character.
1804  * %%u  The day of the week as a decimal, range 1 to 7, Monday being 1.
1805  * %%W  The week number of the current year as a decimal number.
1806  * %%x  The preferred date representation for the current locale without
1807  *      the date.
1808  * %%X  The preferred date representation for the current locale without
1809  *      the time.
1810  * %%y  The year as a decimal number without the century.
1811  * %%Y  The year as a decimal number including the century.
1812  * %%z  The timezone or name or abbreviation.
1813  * %%%  A literal %% character.
1814  *
1815  * Return value: a newly allocated string formatted to the requested format or
1816  *   %NULL in the case that there was an error.  The string should be freed
1817  *   with g_free().
1818  *
1819  * Since: 2.26
1820  */
1821 gchar *
1822 g_date_time_printf (const GDateTime *datetime,
1823                     const gchar     *format)
1824 {
1825   GString     *outstr;
1826   const gchar *tmp;
1827   gchar       *tmp2,
1828                c;
1829   glong        utf8len;
1830   gint         i;
1831   gboolean     in_mod;
1832
1833   g_return_val_if_fail (datetime != NULL, NULL);
1834   g_return_val_if_fail (format != NULL, NULL);
1835   g_return_val_if_fail (g_utf8_validate (format, -1, NULL), NULL);
1836
1837   outstr = g_string_sized_new (strlen (format) * 2);
1838   utf8len = g_utf8_strlen (format, -1);
1839   in_mod = FALSE;
1840
1841   for (i = 0; i < utf8len; i++)
1842     {
1843       tmp = g_utf8_offset_to_pointer (format, i);
1844       c = g_utf8_get_char (tmp);
1845
1846       switch (c) {
1847       case '%':
1848         if (!in_mod)
1849           {
1850             in_mod = TRUE;
1851             break;
1852           }
1853         /* Fall through */
1854       default:
1855         if (in_mod)
1856           {
1857             switch (c) {
1858             case 'a':
1859               g_string_append (outstr, WEEKDAY_ABBR (datetime));
1860               break;
1861             case 'A':
1862               g_string_append (outstr, WEEKDAY_FULL (datetime));
1863               break;
1864             case 'b':
1865               g_string_append (outstr, MONTH_ABBR (datetime));
1866               break;
1867             case 'B':
1868               g_string_append (outstr, MONTH_FULL (datetime));
1869               break;
1870             case 'd':
1871               g_string_append_printf (outstr, "%02d",
1872                                       g_date_time_get_day_of_month (datetime));
1873               break;
1874             case 'e':
1875               g_string_append_printf (outstr, "%2d",
1876                                       g_date_time_get_day_of_month (datetime));
1877               break;
1878             case 'F':
1879               g_string_append_printf (outstr, "%d-%02d-%02d",
1880                                       g_date_time_get_year (datetime),
1881                                       g_date_time_get_month (datetime),
1882                                       g_date_time_get_day_of_month (datetime));
1883               break;
1884             case 'h':
1885               g_string_append (outstr, MONTH_ABBR (datetime));
1886               break;
1887             case 'H':
1888               g_string_append_printf (outstr, "%02d",
1889                                       g_date_time_get_hour (datetime));
1890               break;
1891             case 'I':
1892               if (g_date_time_get_hour (datetime) == 0)
1893                 g_string_append (outstr, "12");
1894               else
1895                 g_string_append_printf (outstr, "%02d",
1896                                         g_date_time_get_hour (datetime) % 12);
1897               break;
1898             case 'j':
1899               g_string_append_printf (outstr, "%03d",
1900                                       g_date_time_get_day_of_year (datetime));
1901               break;
1902             case 'k':
1903               g_string_append_printf (outstr, "%2d",
1904                                       g_date_time_get_hour (datetime));
1905               break;
1906             case 'l':
1907               if (g_date_time_get_hour (datetime) == 0)
1908                 g_string_append (outstr, "12");
1909               else
1910                 g_string_append_printf (outstr, "%2d",
1911                                         g_date_time_get_hour (datetime) % 12);
1912               break;
1913             case 'm':
1914               g_string_append_printf (outstr, "%02d",
1915                                       g_date_time_get_month (datetime));
1916               break;
1917             case 'M':
1918               g_string_append_printf (outstr, "%02d",
1919                                       g_date_time_get_minute (datetime));
1920               break;
1921             case 'N':
1922               g_string_append_printf (outstr, "%"G_GUINT64_FORMAT,
1923                                       datetime->usec % USEC_PER_SECOND);
1924               break;
1925             case 'p':
1926               g_string_append (outstr, GET_AMPM (datetime, FALSE));
1927               break;
1928             case 'P':
1929               g_string_append (outstr, GET_AMPM (datetime, TRUE));
1930               break;
1931             case 'r': {
1932               gint hour = g_date_time_get_hour (datetime) % 12;
1933               if (hour == 0)
1934                 hour = 12;
1935               g_string_append_printf (outstr, "%02d:%02d:%02d %s",
1936                                       hour,
1937                                       g_date_time_get_minute (datetime),
1938                                       g_date_time_get_second (datetime),
1939                                       GET_AMPM (datetime, FALSE));
1940               break;
1941             }
1942             case 'R':
1943               g_string_append_printf (outstr, "%02d:%02d",
1944                                       g_date_time_get_hour (datetime),
1945                                       g_date_time_get_minute (datetime));
1946               break;
1947             case 's':
1948               g_string_append_printf (outstr, "%" G_GINT64_FORMAT,
1949                                       g_date_time_to_epoch (datetime));
1950               break;
1951             case 'S':
1952               g_string_append_printf (outstr, "%02d",
1953                                       g_date_time_get_second (datetime));
1954               break;
1955             case 't':
1956               g_string_append_c (outstr, '\t');
1957               break;
1958             case 'u':
1959               g_string_append_printf (outstr, "%d",
1960                                       g_date_time_get_day_of_week (datetime));
1961               break;
1962             case 'W':
1963               g_string_append_printf (outstr, "%d",
1964                                       g_date_time_get_day_of_year (datetime) / 7);
1965               break;
1966             case 'x': {
1967               tmp2 = GET_PREFERRED_DATE (datetime);
1968               g_string_append (outstr, tmp2);
1969               g_free (tmp2);
1970               break;
1971             }
1972             case 'X': {
1973               tmp2 = GET_PREFERRED_TIME (datetime);
1974               g_string_append (outstr, tmp2);
1975               g_free (tmp2);
1976               break;
1977             }
1978             case 'y':
1979               g_string_append_printf (outstr, "%02d",
1980                                       g_date_time_get_year (datetime) % 100);
1981               break;
1982             case 'Y':
1983               g_string_append_printf (outstr, "%d",
1984                                       g_date_time_get_year (datetime));
1985               break;
1986             case 'z':
1987               if (datetime->tz)
1988                 g_string_append_printf (outstr, "%s", datetime->tz->name);
1989               else
1990                 g_string_append_printf (outstr, "UTC");
1991               break;
1992             case '%':
1993               g_string_append_c (outstr, '%');
1994               break;
1995             case 'n':
1996               g_string_append_c (outstr, '\n');
1997               break;
1998             default:
1999               goto bad_format;
2000             }
2001             in_mod = FALSE;
2002           }
2003         else
2004           g_string_append_unichar (outstr, c);
2005       }
2006   }
2007
2008   tmp = outstr->str;
2009   g_string_free (outstr, FALSE);
2010
2011   return (gchar*)tmp;
2012
2013 bad_format:
2014   g_string_free (outstr, TRUE);
2015   return NULL;
2016 }
2017
2018 /**
2019  * g_date_time_ref:
2020  * @datetime: a #GDateTime
2021  *
2022  * Atomically increments the reference count of @datetime by one.
2023  *
2024  * Return value: the #GDateTime with the reference count increased
2025  *
2026  * Since: 2.26
2027  */
2028 GDateTime *
2029 g_date_time_ref (GDateTime *datetime)
2030 {
2031   g_return_val_if_fail (datetime != NULL, NULL);
2032   g_return_val_if_fail (datetime->ref_count > 0, NULL);
2033
2034   g_atomic_int_inc (&datetime->ref_count);
2035
2036   return datetime;
2037 }
2038
2039 /**
2040  * g_date_time_unref:
2041  * @datetime: a #GDateTime
2042  *
2043  * Atomically decrements the reference count of @datetime by one.
2044  *
2045  * When the reference count reaches zero, the resources allocated by
2046  * @datetime are freed
2047  *
2048  * Since: 2.26
2049  */
2050 void
2051 g_date_time_unref (GDateTime *datetime)
2052 {
2053   g_return_if_fail (datetime != NULL);
2054   g_return_if_fail (datetime->ref_count > 0);
2055
2056   if (g_atomic_int_dec_and_test (&datetime->ref_count))
2057     g_date_time_free (datetime);
2058 }
2059
2060 /**
2061  * g_date_time_to_local:
2062  * @datetime: a #GDateTime
2063  *
2064  * Creates a new #GDateTime with @datetime converted to local time.
2065  *
2066  * Return value: the newly created #GDateTime
2067  *
2068  * Since: 2.26
2069  */
2070 GDateTime *
2071 g_date_time_to_local (const GDateTime *datetime)
2072 {
2073   GDateTime *dt;
2074
2075   g_return_val_if_fail (datetime != NULL, NULL);
2076
2077   dt = g_date_time_copy (datetime);
2078   if (dt->tz == NULL)
2079     {
2080       dt->tz = g_date_time_create_time_zone (dt, NULL);
2081       if (dt->tz == NULL)
2082         return dt;
2083
2084       g_date_time_add_usec (dt, dt->tz->offset * USEC_PER_SECOND);
2085     }
2086
2087   return dt;
2088 }
2089
2090 /**
2091  * g_date_time_to_epoch:
2092  * @datetime: a #GDateTime
2093  *
2094  * Converts @datetime into an integer representing seconds since the
2095  * Unix epoch
2096  *
2097  * Return value: @datetime as seconds since the Unix epoch
2098  *
2099  * Since: 2.26
2100  */
2101 gint64
2102 g_date_time_to_epoch (const GDateTime *datetime)
2103 {
2104   struct tm tm;
2105   gint      year,
2106             month,
2107             day;
2108
2109   g_return_val_if_fail (datetime != NULL, 0);
2110   g_return_val_if_fail (datetime->period == 0, 0);
2111
2112   g_date_time_get_dmy (datetime, &day, &month, &year);
2113
2114   /* FIXME we use gint64, we shold expand these limits */
2115   if (year < 1970)
2116     return 0;
2117   else if (year > 2037)
2118     return G_MAXINT64;
2119
2120   memset (&tm, 0, sizeof (tm));
2121
2122   tm.tm_year = year - 1900;
2123   tm.tm_mon = month - 1;
2124   tm.tm_mday = day;
2125   tm.tm_hour = g_date_time_get_hour (datetime);
2126   tm.tm_min = g_date_time_get_minute (datetime);
2127   tm.tm_sec = g_date_time_get_second (datetime);
2128   tm.tm_isdst = -1;
2129
2130   return (gint64) mktime (&tm);
2131 }
2132
2133 /**
2134  * g_date_time_to_timeval:
2135  * @datetime: a #GDateTime
2136  * @tv: A #GTimeVal
2137  *
2138  * Converts @datetime into a #GTimeVal and stores the result into @timeval.
2139  *
2140  * Since: 2.26
2141  */
2142 void
2143 g_date_time_to_timeval (const GDateTime *datetime,
2144                         GTimeVal        *tv)
2145 {
2146   g_return_if_fail (datetime != NULL);
2147
2148   tv->tv_sec = 0;
2149   tv->tv_usec = 0;
2150
2151   if (G_LIKELY (datetime->period == 0))
2152     {
2153       tv->tv_sec = g_date_time_to_epoch (datetime);
2154       tv->tv_usec = datetime->usec % USEC_PER_SECOND;
2155     }
2156 }
2157
2158 /**
2159  * g_date_time_to_utc:
2160  * @datetime: a #GDateTime
2161  *
2162  * Creates a new #GDateTime that reprents @datetime in Universal coordinated
2163  * time.
2164  *
2165  * Return value: the newly created #GDateTime which should be freed with
2166  *   g_date_time_unref().
2167  *
2168  * Since: 2.26
2169  */
2170 GDateTime *
2171 g_date_time_to_utc (const GDateTime *datetime)
2172 {
2173   GDateTime *dt;
2174   GTimeSpan  ts;
2175
2176   g_return_val_if_fail (datetime != NULL, NULL);
2177
2178   ts = g_date_time_get_utc_offset (datetime) * -1;
2179   dt = g_date_time_add (datetime, ts);
2180   dt->tz = NULL;
2181
2182   return dt;
2183 }
2184
2185 /**
2186  * g_date_time_new_today:
2187  *
2188  * Createsa new #GDateTime that represents Midnight on the current day.
2189  *
2190  * Return value: the newly created #GDateTime which should be freed with
2191  *   g_date_time_unref().
2192  *
2193  * Since: 2.26
2194  */
2195 GDateTime*
2196 g_date_time_new_today (void)
2197 {
2198   GDateTime *dt;
2199
2200   dt = g_date_time_new_now ();
2201   dt->usec = 0;
2202
2203   return dt;
2204 }
2205
2206 /**
2207  * g_date_time_new_utc_now:
2208  *
2209  * Creates a new #GDateTime that represents the current instant in Universal
2210  * Coordinated Time (UTC).
2211  *
2212  * Return value: the newly created #GDateTime which should be freed with
2213  *   g_date_time_unref().
2214  *
2215  * Since: 2.26
2216  */
2217 GDateTime *
2218 g_date_time_new_utc_now (void)
2219 {
2220   GDateTime *utc, *now;
2221
2222   now = g_date_time_new_now ();
2223   utc = g_date_time_to_utc (now);
2224   g_date_time_unref (now);
2225
2226   return utc;
2227 }