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