Fix typo in API docs for GDateTime
[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  * Copyright © 2010 Codethink Limited
7  *
8  * This library is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as
10  * published by the Free Software Foundation; either version 2.1 of the
11  * licence, or (at your option) any later version.
12  *
13  * This is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16  * License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
21  * USA.
22  *
23  * Authors: Christian Hergert <chris@dronelabs.com>
24  *          Thiago Santos <thiago.sousa.santos@collabora.co.uk>
25  *          Emmanuele Bassi <ebassi@linux.intel.com>
26  *          Ryan Lortie <desrt@desrt.ca>
27  */
28
29 /* Algorithms within this file are based on the Calendar FAQ by
30  * Claus Tondering.  It can be found at
31  * http://www.tondering.dk/claus/cal/calendar29.txt
32  *
33  * Copyright and disclaimer
34  * ------------------------
35  *   This document is Copyright (C) 2008 by Claus Tondering.
36  *   E-mail: claus@tondering.dk. (Please include the word
37  *   "calendar" in the subject line.)
38  *   The document may be freely distributed, provided this
39  *   copyright notice is included and no money is charged for
40  *   the document.
41  *
42  *   This document is provided "as is". No warranties are made as
43  *   to its correctness.
44  */
45
46 /* Prologue {{{1 */
47
48 #include "config.h"
49
50 #include <stdlib.h>
51 #include <string.h>
52
53 #ifdef HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
56
57 #include "gdatetime.h"
58
59 #include "gatomic.h"
60 #include "gfileutils.h"
61 #include "ghash.h"
62 #include "gmain.h"
63 #include "gmappedfile.h"
64 #include "gstrfuncs.h"
65 #include "gtestutils.h"
66 #include "gthread.h"
67 #include "gtimezone.h"
68
69 #include "glibintl.h"
70
71 #ifndef G_OS_WIN32
72 #include <sys/time.h>
73 #include <time.h>
74 #endif /* !G_OS_WIN32 */
75
76 /**
77  * SECTION:date-time
78  * @title: GDateTime
79  * @short_description: A structure representing Date and Time
80  * @see_also: #GTimeZone
81  *
82  * #GDateTime is a structure that combines a Gregorian date and time
83  * into a single structure.  It provides many conversion and methods to
84  * manipulate dates and times.  Time precision is provided down to
85  * microseconds and the time can range (proleptically) from 0001-01-01
86  * 00:00:00 to 9999-12-31 23:59:59.999999.  #GDateTime follows POSIX
87  * time in the sense that it is oblivious to leap seconds.
88  *
89  * #GDateTime is an immutable object; once it has been created it cannot
90  * be modified further.  All modifiers will create a new #GDateTime.
91  * Nearly all such functions can fail due to the date or time going out
92  * of range, in which case %NULL will be returned.
93  *
94  * #GDateTime is reference counted: the reference count is increased by calling
95  * g_date_time_ref() and decreased by calling g_date_time_unref(). When the
96  * reference count drops to 0, the resources allocated by the #GDateTime
97  * structure are released.
98  *
99  * Many parts of the API may produce non-obvious results.  As an
100  * example, adding two months to January 31st will yield March 31st
101  * whereas adding one month and then one month again will yield either
102  * March 28th or March 29th.  Also note that adding 24 hours is not
103  * always the same as adding one day (since days containing daylight
104  * savings time transitions are either 23 or 25 hours in length).
105  *
106  * #GDateTime is available since GLib 2.26.
107  */
108
109 struct _GDateTime
110 {
111   /* 1 is 0001-01-01 in Proleptic Gregorian */
112   gint32 days;
113
114   /* Microsecond timekeeping within Day */
115   guint64 usec;
116
117   /* TimeZone information */
118   GTimeZone *tz;
119   gint interval;
120
121   volatile gint ref_count;
122 };
123
124 /* Time conversion {{{1 */
125
126 #define UNIX_EPOCH_START     719163
127 #define INSTANT_TO_UNIX(instant) \
128   ((instant)/USEC_PER_SECOND - UNIX_EPOCH_START * SEC_PER_DAY)
129 #define UNIX_TO_INSTANT(unix) \
130   (((unix) + UNIX_EPOCH_START * SEC_PER_DAY) * USEC_PER_SECOND)
131
132 #define DAYS_IN_4YEARS    1461    /* days in 4 years */
133 #define DAYS_IN_100YEARS  36524   /* days in 100 years */
134 #define DAYS_IN_400YEARS  146097  /* days in 400 years  */
135
136 #define USEC_PER_SECOND      (G_GINT64_CONSTANT (1000000))
137 #define USEC_PER_MINUTE      (G_GINT64_CONSTANT (60000000))
138 #define USEC_PER_HOUR        (G_GINT64_CONSTANT (3600000000))
139 #define USEC_PER_MILLISECOND (G_GINT64_CONSTANT (1000))
140 #define USEC_PER_DAY         (G_GINT64_CONSTANT (86400000000))
141 #define SEC_PER_DAY          (G_GINT64_CONSTANT (86400))
142
143 #define GREGORIAN_LEAP(y)    ((((y) % 4) == 0) && (!((((y) % 100) == 0) && (((y) % 400) != 0))))
144 #define JULIAN_YEAR(d)       ((d)->julian / 365.25)
145 #define DAYS_PER_PERIOD      (G_GINT64_CONSTANT (2914695))
146
147 #define GET_AMPM(d,l)         ((g_date_time_get_hour (d) < 12)  \
148                                        /* Translators: 'before midday' indicator */ \
149                                 ? (l ? C_("GDateTime", "am") \
150                                        /* Translators: 'before midday' indicator */ \
151                                      : C_("GDateTime", "AM")) \
152                                   /* Translators: 'after midday' indicator */ \
153                                 : (l ? C_("GDateTime", "pm") \
154                                   /* Translators: 'after midday' indicator */ \
155                                      : C_("GDateTime", "PM")))
156
157 #define WEEKDAY_ABBR(d)       (get_weekday_name_abbr (g_date_time_get_day_of_week (datetime)))
158 #define WEEKDAY_FULL(d)       (get_weekday_name (g_date_time_get_day_of_week (datetime)))
159
160 #define MONTH_ABBR(d)         (get_month_name_abbr (g_date_time_get_month (datetime)))
161 #define MONTH_FULL(d)         (get_month_name (g_date_time_get_month (datetime)))
162
163 /* Translators: this is the preferred format for expressing the date */
164 #define GET_PREFERRED_DATE(d) (g_date_time_format ((d), C_("GDateTime", "%m/%d/%y")))
165
166 /* Translators: this is the preferred format for expressing the time */
167 #define GET_PREFERRED_TIME(d) (g_date_time_format ((d), C_("GDateTime", "%H:%M:%S")))
168
169 #define SECS_PER_MINUTE (60)
170 #define SECS_PER_HOUR   (60 * SECS_PER_MINUTE)
171 #define SECS_PER_DAY    (24 * SECS_PER_HOUR)
172 #define SECS_PER_YEAR   (365 * SECS_PER_DAY)
173 #define SECS_PER_JULIAN (DAYS_PER_PERIOD * SECS_PER_DAY)
174
175 static const guint16 days_in_months[2][13] =
176 {
177   { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
178   { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
179 };
180
181 static const guint16 days_in_year[2][13] =
182 {
183   {  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
184   {  0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
185 };
186
187 static const gchar *
188 get_month_name (gint month)
189 {
190   switch (month)
191     {
192     case 1:
193       return C_("full month name", "January");
194     case 2:
195       return C_("full month name", "February");
196     case 3:
197       return C_("full month name", "March");
198     case 4:
199       return C_("full month name", "April");
200     case 5:
201       return C_("full month name", "May");
202     case 6:
203       return C_("full month name", "June");
204     case 7:
205       return C_("full month name", "July");
206     case 8:
207       return C_("full month name", "August");
208     case 9:
209       return C_("full month name", "September");
210     case 10:
211       return C_("full month name", "October");
212     case 11:
213       return C_("full month name", "November");
214     case 12:
215       return C_("full month name", "December");
216
217     default:
218       g_warning ("Invalid month number %d", month);
219     }
220
221   return NULL;
222 }
223
224 static const gchar *
225 get_month_name_abbr (gint month)
226 {
227   switch (month)
228     {
229     case 1:
230       return C_("abbreviated month name", "Jan");
231     case 2:
232       return C_("abbreviated month name", "Feb");
233     case 3:
234       return C_("abbreviated month name", "Mar");
235     case 4:
236       return C_("abbreviated month name", "Apr");
237     case 5:
238       return C_("abbreviated month name", "May");
239     case 6:
240       return C_("abbreviated month name", "Jun");
241     case 7:
242       return C_("abbreviated month name", "Jul");
243     case 8:
244       return C_("abbreviated month name", "Aug");
245     case 9:
246       return C_("abbreviated month name", "Sep");
247     case 10:
248       return C_("abbreviated month name", "Oct");
249     case 11:
250       return C_("abbreviated month name", "Nov");
251     case 12:
252       return C_("abbreviated month name", "Dec");
253
254     default:
255       g_warning ("Invalid month number %d", month);
256     }
257
258   return NULL;
259 }
260
261 static const gchar *
262 get_weekday_name (gint day)
263 {
264   switch (day)
265     {
266     case 1:
267       return C_("full weekday name", "Monday");
268     case 2:
269       return C_("full weekday name", "Tuesday");
270     case 3:
271       return C_("full weekday name", "Wednesday");
272     case 4:
273       return C_("full weekday name", "Thursday");
274     case 5:
275       return C_("full weekday name", "Friday");
276     case 6:
277       return C_("full weekday name", "Saturday");
278     case 7:
279       return C_("full weekday name", "Sunday");
280
281     default:
282       g_warning ("Invalid week day number %d", day);
283     }
284
285   return NULL;
286 }
287
288 static const gchar *
289 get_weekday_name_abbr (gint day)
290 {
291   switch (day)
292     {
293     case 1:
294       return C_("abbreviated weekday name", "Mon");
295     case 2:
296       return C_("abbreviated weekday name", "Tue");
297     case 3:
298       return C_("abbreviated weekday name", "Wed");
299     case 4:
300       return C_("abbreviated weekday name", "Thu");
301     case 5:
302       return C_("abbreviated weekday name", "Fri");
303     case 6:
304       return C_("abbreviated weekday name", "Sat");
305     case 7:
306       return C_("abbreviated weekday name", "Sun");
307
308     default:
309       g_warning ("Invalid week day number %d", day);
310     }
311
312   return NULL;
313 }
314
315 static inline gint
316 ymd_to_days (gint year,
317              gint month,
318              gint day)
319 {
320   gint64 days;
321
322   days = (year - 1) * 365 + ((year - 1) / 4) - ((year - 1) / 100)
323       + ((year - 1) / 400);
324
325   days += days_in_year[0][month - 1];
326   if (GREGORIAN_LEAP (year) && month > 2)
327     day++;
328
329   days += day;
330
331   return days;
332 }
333
334 static void
335 g_date_time_get_week_number (GDateTime *datetime,
336                              gint      *week_number,
337                              gint      *day_of_week,
338                              gint      *day_of_year)
339 {
340   gint a, b, c, d, e, f, g, n, s, month, day, year;
341
342   g_date_time_get_ymd (datetime, &year, &month, &day);
343
344   if (month <= 2)
345     {
346       a = g_date_time_get_year (datetime) - 1;
347       b = (a / 4) - (a / 100) + (a / 400);
348       c = ((a - 1) / 4) - ((a - 1) / 100) + ((a - 1) / 400);
349       s = b - c;
350       e = 0;
351       f = day - 1 + (31 * (month - 1));
352     }
353   else
354     {
355       a = year;
356       b = (a / 4) - (a / 100) + (a / 400);
357       c = ((a - 1) / 4) - ((a - 1) / 100) + ((a - 1) / 400);
358       s = b - c;
359       e = s + 1;
360       f = day + (((153 * (month - 3)) + 2) / 5) + 58 + s;
361     }
362
363   g = (a + b) % 7;
364   d = (f + g - e) % 7;
365   n = f + 3 - d;
366
367   if (week_number)
368     {
369       if (n < 0)
370         *week_number = 53 - ((g - s) / 5);
371       else if (n > 364 + s)
372         *week_number = 1;
373       else
374         *week_number = (n / 7) + 1;
375     }
376
377   if (day_of_week)
378     *day_of_week = d + 1;
379
380   if (day_of_year)
381     *day_of_year = f + 1;
382 }
383
384 /* Lifecycle {{{1 */
385
386 static GDateTime *
387 g_date_time_alloc (GTimeZone *tz)
388 {
389   GDateTime *datetime;
390
391   datetime = g_slice_new0 (GDateTime);
392   datetime->tz = g_time_zone_ref (tz);
393   datetime->ref_count = 1;
394
395   return datetime;
396 }
397
398 /**
399  * g_date_time_ref:
400  * @datetime: a #GDateTime
401  *
402  * Atomically increments the reference count of @datetime by one.
403  *
404  * Return value: the #GDateTime with the reference count increased
405  *
406  * Since: 2.26
407  */
408 GDateTime *
409 g_date_time_ref (GDateTime *datetime)
410 {
411   g_return_val_if_fail (datetime != NULL, NULL);
412   g_return_val_if_fail (datetime->ref_count > 0, NULL);
413
414   g_atomic_int_inc (&datetime->ref_count);
415
416   return datetime;
417 }
418
419 /**
420  * g_date_time_unref:
421  * @datetime: a #GDateTime
422  *
423  * Atomically decrements the reference count of @datetime by one.
424  *
425  * When the reference count reaches zero, the resources allocated by
426  * @datetime are freed
427  *
428  * Since: 2.26
429  */
430 void
431 g_date_time_unref (GDateTime *datetime)
432 {
433   g_return_if_fail (datetime != NULL);
434   g_return_if_fail (datetime->ref_count > 0);
435
436   if (g_atomic_int_dec_and_test (&datetime->ref_count))
437     {
438       g_time_zone_unref (datetime->tz);
439       g_slice_free (GDateTime, datetime);
440     }
441 }
442
443 /* Internal state transformers {{{1 */
444 /*< internal >
445  * g_date_time_to_instant:
446  * @datetime: a #GDateTime
447  *
448  * Convert a @datetime into an instant.
449  *
450  * An instant is a number that uniquely describes a particular
451  * microsecond in time, taking time zone considerations into account.
452  * (ie: "03:00 -0400" is the same instant as "02:00 -0500").
453  *
454  * An instant is always positive but we use a signed return value to
455  * avoid troubles with C.
456  */
457 static gint64
458 g_date_time_to_instant (GDateTime *datetime)
459 {
460   gint64 offset;
461
462   offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
463   offset *= USEC_PER_SECOND;
464
465   return datetime->days * USEC_PER_DAY + datetime->usec - offset;
466 }
467
468 /*< internal >
469  * g_date_time_from_instant:
470  * @tz: a #GTimeZone
471  * @instant: a instant in time
472  *
473  * Creates a #GDateTime from a time zone and an instant.
474  *
475  * This might fail if the time ends up being out of range.
476  */
477 static GDateTime *
478 g_date_time_from_instant (GTimeZone *tz,
479                           gint64     instant)
480 {
481   GDateTime *datetime;
482   gint64 offset;
483
484   if (instant < 0 || instant > G_GINT64_CONSTANT (1000000000000000000))
485     return NULL;
486
487   datetime = g_date_time_alloc (tz);
488   datetime->interval = g_time_zone_find_interval (tz,
489                                                   G_TIME_TYPE_UNIVERSAL,
490                                                   INSTANT_TO_UNIX (instant));
491   offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
492   offset *= USEC_PER_SECOND;
493
494   instant += offset;
495
496   datetime->days = instant / USEC_PER_DAY;
497   datetime->usec = instant % USEC_PER_DAY;
498
499   if (datetime->days < 1 || 3652059 < datetime->days)
500     {
501       g_date_time_unref (datetime);
502       datetime = NULL;
503     }
504
505   return datetime;
506 }
507
508
509 /*< internal >
510  * g_date_time_deal_with_date_change:
511  * @datetime: a #GDateTime
512  *
513  * This function should be called whenever the date changes by adding
514  * days, months or years.  It does three things.
515  *
516  * First, we ensure that the date falls between 0001-01-01 and
517  * 9999-12-31 and return %FALSE if it does not.
518  *
519  * Next we update the ->interval field.
520  *
521  * Finally, we ensure that the resulting date and time pair exists (by
522  * ensuring that our time zone has an interval containing it) and
523  * adjusting as required.  For example, if we have the time 02:30:00 on
524  * March 13 2010 in Toronto and we add 1 day to it, we would end up with
525  * 2:30am on March 14th, which doesn't exist.  In that case, we bump the
526  * time up to 3:00am.
527  */
528 static gboolean
529 g_date_time_deal_with_date_change (GDateTime *datetime)
530 {
531   GTimeType was_dst;
532   gint64 full_time;
533   gint64 usec;
534
535   if (datetime->days < 1 || datetime->days > 3652059)
536     return FALSE;
537
538   was_dst = g_time_zone_is_dst (datetime->tz, datetime->interval);
539
540   full_time = datetime->days * USEC_PER_DAY + datetime->usec;
541
542
543   usec = full_time % USEC_PER_SECOND;
544   full_time /= USEC_PER_SECOND;
545   full_time -= UNIX_EPOCH_START * SEC_PER_DAY;
546
547   datetime->interval = g_time_zone_adjust_time (datetime->tz,
548                                                 was_dst,
549                                                 &full_time);
550   full_time += UNIX_EPOCH_START * SEC_PER_DAY;
551   full_time *= USEC_PER_SECOND;
552   full_time += usec;
553
554   datetime->days = full_time / USEC_PER_DAY;
555   datetime->usec = full_time % USEC_PER_DAY;
556
557   /* maybe daylight time caused us to shift to a different day,
558    * but it definitely didn't push us into a different year */
559   return TRUE;
560 }
561
562 static GDateTime *
563 g_date_time_replace_days (GDateTime *datetime,
564                           gint       days)
565 {
566   GDateTime *new;
567
568   new = g_date_time_alloc (datetime->tz);
569   new->interval = datetime->interval;
570   new->usec = datetime->usec;
571   new->days = days;
572
573   if (!g_date_time_deal_with_date_change (new))
574     {
575       g_date_time_unref (new);
576       new = NULL;
577     }
578
579   return new;
580 }
581
582 /* now/unix/timeval Constructors {{{1 */
583
584 /*< internal >
585  * g_date_time_new_from_timeval:
586  * @tz: a #GTimeZone
587  * @tv: a #GTimeVal
588  *
589  * Creates a #GDateTime corresponding to the given #GTimeVal @tv in the
590  * given time zone @tz.
591  *
592  * The time contained in a #GTimeVal is always stored in the form of
593  * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the
594  * given time zone.
595  *
596  * This call can fail (returning %NULL) if @tv represents a time outside
597  * of the supported range of #GDateTime.
598  *
599  * You should release the return value by calling g_date_time_unref()
600  * when you are done with it.
601  *
602  * Returns: a new #GDateTime, or %NULL
603  *
604  * Since: 2.26
605  **/
606 static GDateTime *
607 g_date_time_new_from_timeval (GTimeZone      *tz,
608                               const GTimeVal *tv)
609 {
610   return g_date_time_from_instant (tz, tv->tv_usec +
611                                    UNIX_TO_INSTANT (tv->tv_sec));
612 }
613
614 /*< internal >
615  * g_date_time_new_from_unix:
616  * @tz: a #GTimeZone
617  * @t: the Unix time
618  *
619  * Creates a #GDateTime corresponding to the given Unix time @t in the
620  * given time zone @tz.
621  *
622  * Unix time is the number of seconds that have elapsed since 1970-01-01
623  * 00:00:00 UTC, regardless of the time zone given.
624  *
625  * This call can fail (returning %NULL) if @t represents a time outside
626  * of the supported range of #GDateTime.
627  *
628  * You should release the return value by calling g_date_time_unref()
629  * when you are done with it.
630  *
631  * Returns: a new #GDateTime, or %NULL
632  *
633  * Since: 2.26
634  **/
635 static GDateTime *
636 g_date_time_new_from_unix (GTimeZone *tz,
637                            gint64     secs)
638 {
639   return g_date_time_from_instant (tz, UNIX_TO_INSTANT (secs));
640 }
641
642 /**
643  * g_date_time_new_now:
644  * @tz: a #GTimeZone
645  *
646  * Creates a #GDateTime corresponding to this exact instant in the given
647  * time zone @tz.  The time is as accurate as the system allows, to a
648  * maximum accuracy of 1 microsecond.
649  *
650  * This function will always succeed unless the system clock is set to
651  * truly insane values (or unless GLib is still being used after the
652  * year 9999).
653  *
654  * You should release the return value by calling g_date_time_unref()
655  * when you are done with it.
656  *
657  * Returns: a new #GDateTime, or %NULL
658  *
659  * Since: 2.26
660  **/
661 GDateTime *
662 g_date_time_new_now (GTimeZone *tz)
663 {
664   GTimeVal tv;
665
666   g_get_current_time (&tv);
667
668   return g_date_time_new_from_timeval (tz, &tv);
669 }
670
671 /**
672  * g_date_time_new_now_local:
673  *
674  * Creates a #GDateTime corresponding to this exact instant in the local
675  * time zone.
676  *
677  * This is equivalent to calling g_date_time_new_now() with the time
678  * zone returned by g_time_zone_new_local().
679  *
680  * Returns: a new #GDateTime, or %NULL
681  *
682  * Since: 2.26
683  **/
684 GDateTime *
685 g_date_time_new_now_local (void)
686 {
687   GDateTime *datetime;
688   GTimeZone *local;
689
690   local = g_time_zone_new_local ();
691   datetime = g_date_time_new_now (local);
692   g_time_zone_unref (local);
693
694   return datetime;
695 }
696
697 /**
698  * g_date_time_new_now_utc:
699  *
700  * Creates a #GDateTime corresponding to this exact instant in UTC.
701  *
702  * This is equivalent to calling g_date_time_new_now() with the time
703  * zone returned by g_time_zone_new_utc().
704  *
705  * Returns: a new #GDateTime, or %NULL
706  *
707  * Since: 2.26
708  **/
709 GDateTime *
710 g_date_time_new_now_utc (void)
711 {
712   GDateTime *datetime;
713   GTimeZone *utc;
714
715   utc = g_time_zone_new_utc ();
716   datetime = g_date_time_new_now (utc);
717   g_time_zone_unref (utc);
718
719   return datetime;
720 }
721
722 /**
723  * g_date_time_new_from_unix_local:
724  * @t: the Unix time
725  *
726  * Creates a #GDateTime corresponding to the given Unix time @t in the
727  * local time zone.
728  *
729  * Unix time is the number of seconds that have elapsed since 1970-01-01
730  * 00:00:00 UTC, regardless of the local time offset.
731  *
732  * This call can fail (returning %NULL) if @t represents a time outside
733  * of the supported range of #GDateTime.
734  *
735  * You should release the return value by calling g_date_time_unref()
736  * when you are done with it.
737  *
738  * Returns: a new #GDateTime, or %NULL
739  *
740  * Since: 2.26
741  **/
742 GDateTime *
743 g_date_time_new_from_unix_local (gint64 t)
744 {
745   GDateTime *datetime;
746   GTimeZone *local;
747
748   local = g_time_zone_new_local ();
749   datetime = g_date_time_new_from_unix (local, t);
750   g_time_zone_unref (local);
751
752   return datetime;
753 }
754
755 /**
756  * g_date_time_new_from_unix_utc:
757  * @t: the Unix time
758  *
759  * Creates a #GDateTime corresponding to the given Unix time @t in UTC.
760  *
761  * Unix time is the number of seconds that have elapsed since 1970-01-01
762  * 00:00:00 UTC.
763  *
764  * This call can fail (returning %NULL) if @t represents a time outside
765  * of the supported range of #GDateTime.
766  *
767  * You should release the return value by calling g_date_time_unref()
768  * when you are done with it.
769  *
770  * Returns: a new #GDateTime, or %NULL
771  *
772  * Since: 2.26
773  **/
774 GDateTime *
775 g_date_time_new_from_unix_utc (gint64 t)
776 {
777   GDateTime *datetime;
778   GTimeZone *utc;
779
780   utc = g_time_zone_new_utc ();
781   datetime = g_date_time_new_from_unix (utc, t);
782   g_time_zone_unref (utc);
783
784   return datetime;
785 }
786
787 /**
788  * g_date_time_new_from_timeval_local:
789  * @tv: a #GTimeVal
790  *
791  * Creates a #GDateTime corresponding to the given #GTimeVal @tv in the
792  * local time zone.
793  *
794  * The time contained in a #GTimeVal is always stored in the form of
795  * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the
796  * local time offset.
797  *
798  * This call can fail (returning %NULL) if @tv represents a time outside
799  * of the supported range of #GDateTime.
800  *
801  * You should release the return value by calling g_date_time_unref()
802  * when you are done with it.
803  *
804  * Returns: a new #GDateTime, or %NULL
805  *
806  * Since: 2.26
807  **/
808 GDateTime *
809 g_date_time_new_from_timeval_local (const GTimeVal *tv)
810 {
811   GDateTime *datetime;
812   GTimeZone *local;
813
814   local = g_time_zone_new_local ();
815   datetime = g_date_time_new_from_timeval (local, tv);
816   g_time_zone_unref (local);
817
818   return datetime;
819 }
820
821 /**
822  * g_date_time_new_from_timeval_utc:
823  * @tv: a #GTimeVal
824  *
825  * Creates a #GDateTime corresponding to the given #GTimeVal @tv in UTC.
826  *
827  * The time contained in a #GTimeVal is always stored in the form of
828  * seconds elapsed since 1970-01-01 00:00:00 UTC.
829  *
830  * This call can fail (returning %NULL) if @tv represents a time outside
831  * of the supported range of #GDateTime.
832  *
833  * You should release the return value by calling g_date_time_unref()
834  * when you are done with it.
835  *
836  * Returns: a new #GDateTime, or %NULL
837  *
838  * Since: 2.26
839  **/
840 GDateTime *
841 g_date_time_new_from_timeval_utc (const GTimeVal *tv)
842 {
843   GDateTime *datetime;
844   GTimeZone *utc;
845
846   utc = g_time_zone_new_utc ();
847   datetime = g_date_time_new_from_timeval (utc, tv);
848   g_time_zone_unref (utc);
849
850   return datetime;
851 }
852
853 /* full new functions {{{1 */
854
855 /**
856  * g_date_time_new:
857  * @tz: a #GTimeZone
858  * @year: the year component of the date
859  * @month: the month component of the date
860  * @day: the day component of the date
861  * @hour: the hour component of the date
862  * @minute: the minute component of the date
863  * @seconds: the number of seconds past the minute
864  *
865  * Creates a new #GDateTime corresponding to the given date and time in
866  * the time zone @tz.
867  *
868  * The @year must be between 1 and 9999, @month between 1 and 12 and @day
869  * between 1 and 28, 29, 30 or 31 depending on the month and the year.
870  *
871  * @hour must be between 0 and 23 and @minute must be between 0 and 59.
872  *
873  * @seconds must be at least 0.0 and must be strictly less than 60.0.
874  * It will be rounded down to the nearest microsecond.
875  *
876  * If the given time is not representable in the given time zone (for
877  * example, 02:30 on March 14th 2010 in Toronto, due to daylight savings
878  * time) then the time will be rounded up to the nearest existing time
879  * (in this case, 03:00).  If this matters to you then you should verify
880  * the return value for containing the same as the numbers you gave.
881  *
882  * In the case that the given time is ambiguous in the given time zone
883  * (for example, 01:30 on November 7th 2010 in Toronto, due to daylight
884  * savings time) then the time falling within standard (ie:
885  * non-daylight) time is taken.
886  *
887  * It not considered a programmer error for the values to this function
888  * to be out of range, but in the case that they are, the function will
889  * return %NULL.
890  *
891  * You should release the return value by calling g_date_time_unref()
892  * when you are done with it.
893  *
894  * Returns: a new #GDateTime, or %NULL
895  *
896  * Since: 2.26
897  **/
898 GDateTime *
899 g_date_time_new (GTimeZone *tz,
900                  gint       year,
901                  gint       month,
902                  gint       day,
903                  gint       hour,
904                  gint       minute,
905                  gdouble    seconds)
906 {
907   GDateTime *datetime;
908   gint64 full_time;
909
910   datetime = g_date_time_alloc (tz);
911   datetime->days = ymd_to_days (year, month, day);
912   datetime->usec = (hour   * USEC_PER_HOUR)
913                  + (minute * USEC_PER_MINUTE)
914                  + (gint64) (seconds * USEC_PER_SECOND);
915
916   full_time = SEC_PER_DAY *
917                 (ymd_to_days (year, month, day) - UNIX_EPOCH_START) +
918               SECS_PER_HOUR * hour +
919               SECS_PER_MINUTE * minute +
920               (int) seconds;
921
922   datetime->interval = g_time_zone_adjust_time (datetime->tz,
923                                                 G_TIME_TYPE_STANDARD,
924                                                 &full_time);
925
926   full_time += UNIX_EPOCH_START * SEC_PER_DAY;
927   datetime->days = full_time / SEC_PER_DAY;
928   datetime->usec = (full_time % SEC_PER_DAY) * USEC_PER_SECOND;
929   datetime->usec += ((int) (seconds * USEC_PER_SECOND)) % USEC_PER_SECOND;
930
931   return datetime;
932 }
933
934 /**
935  * g_date_time_new_local:
936  * @year: the year component of the date
937  * @month: the month component of the date
938  * @day: the day component of the date
939  * @hour: the hour component of the date
940  * @minute: the minute component of the date
941  * @seconds: the number of seconds past the minute
942  *
943  * Creates a new #GDateTime corresponding to the given date and time in
944  * the local time zone.
945  *
946  * This call is equivalent to calling g_date_time_new() with the time
947  * zone returned by g_time_zone_new_local().
948  *
949  * Returns: a #GDateTime, or %NULL
950  *
951  * Since: 2.26.
952  **/
953 GDateTime *
954 g_date_time_new_local (gint    year,
955                        gint    month,
956                        gint    day,
957                        gint    hour,
958                        gint    minute,
959                        gdouble seconds)
960 {
961   GDateTime *datetime;
962   GTimeZone *local;
963
964   local = g_time_zone_new_local ();
965   datetime = g_date_time_new (local, year, month, day, hour, minute, seconds);
966   g_time_zone_unref (local);
967
968   return datetime;
969 }
970
971 /**
972  * g_date_time_new_utc:
973  * @year: the year component of the date
974  * @month: the month component of the date
975  * @day: the day component of the date
976  * @hour: the hour component of the date
977  * @minute: the minute component of the date
978  * @seconds: the number of seconds past the minute
979  *
980  * Creates a new #GDateTime corresponding to the given date and time in
981  * UTC.
982  *
983  * This call is equivalent to calling g_date_time_new() with the time
984  * zone returned by g_time_zone_new_utc().
985  *
986  * Returns: a #GDateTime, or %NULL
987  *
988  * Since: 2.26.
989  **/
990 GDateTime *
991 g_date_time_new_utc (gint    year,
992                      gint    month,
993                      gint    day,
994                      gint    hour,
995                      gint    minute,
996                      gdouble seconds)
997 {
998   GDateTime *datetime;
999   GTimeZone *utc;
1000
1001   utc = g_time_zone_new_utc ();
1002   datetime = g_date_time_new (utc, year, month, day, hour, minute, seconds);
1003   g_time_zone_unref (utc);
1004
1005   return datetime;
1006 }
1007
1008 /* Adders {{{1 */
1009
1010 /**
1011  * g_date_time_add:
1012  * @datetime: a #GDateTime
1013  * @timespan: a #GTimeSpan
1014  *
1015  * Creates a copy of @datetime and adds the specified timespan to the copy.
1016  *
1017  * Return value: the newly created #GDateTime which should be freed with
1018  *   g_date_time_unref().
1019  *
1020  * Since: 2.26
1021  */
1022 GDateTime*
1023 g_date_time_add (GDateTime *datetime,
1024                  GTimeSpan  timespan)
1025 {
1026   return g_date_time_from_instant (datetime->tz, timespan +
1027                                    g_date_time_to_instant (datetime));
1028 }
1029
1030 /**
1031  * g_date_time_add_years:
1032  * @datetime: a #GDateTime
1033  * @years: the number of years
1034  *
1035  * Creates a copy of @datetime and adds the specified number of years to the
1036  * copy.
1037  *
1038  * Return value: the newly created #GDateTime which should be freed with
1039  *   g_date_time_unref().
1040  *
1041  * Since: 2.26
1042  */
1043 GDateTime *
1044 g_date_time_add_years (GDateTime *datetime,
1045                        gint       years)
1046 {
1047   gint year, month, day;
1048
1049   g_return_val_if_fail (datetime != NULL, NULL);
1050
1051   if (years < -10000 || years > 10000)
1052     return NULL;
1053
1054   g_date_time_get_ymd (datetime, &year, &month, &day);
1055   year += years;
1056
1057   /* only possible issue is if we've entered a year with no February 29
1058    */
1059   if (month == 2 && day == 29 && !GREGORIAN_LEAP (year))
1060     day = 28;
1061
1062   return g_date_time_replace_days (datetime, ymd_to_days (year, month, day));
1063 }
1064
1065 /**
1066  * g_date_time_add_months:
1067  * @datetime: a #GDateTime
1068  * @months: the number of months
1069  *
1070  * Creates a copy of @datetime and adds the specified number of months to the
1071  * copy.
1072  *
1073  * Return value: the newly created #GDateTime which should be freed with
1074  *   g_date_time_unref().
1075  *
1076  * Since: 2.26
1077  */
1078 GDateTime*
1079 g_date_time_add_months (GDateTime *datetime,
1080                         gint       months)
1081 {
1082   gint year, month, day;
1083
1084   g_return_val_if_fail (datetime != NULL, NULL);
1085   g_date_time_get_ymd (datetime, &year, &month, &day);
1086
1087   if (months < -120000 || months > 120000)
1088     return NULL;
1089
1090   year += months / 12;
1091   month += months % 12;
1092   if (month < 1)
1093     {
1094       month += 12;
1095       year--;
1096     }
1097   else if (month > 12)
1098     {
1099       month -= 12;
1100       year++;
1101     }
1102
1103   day = MIN (day, days_in_months[GREGORIAN_LEAP (year)][month]);
1104
1105   return g_date_time_replace_days (datetime, ymd_to_days (year, month, day));
1106 }
1107
1108 /**
1109  * g_date_time_add_weeks:
1110  * @datetime: a #GDateTime
1111  * @weeks: the number of weeks
1112  *
1113  * Creates a copy of @datetime and adds the specified number of weeks to the
1114  * copy.
1115  *
1116  * Return value: the newly created #GDateTime which should be freed with
1117  *   g_date_time_unref().
1118  *
1119  * Since: 2.26
1120  */
1121 GDateTime*
1122 g_date_time_add_weeks (GDateTime *datetime,
1123                        gint             weeks)
1124 {
1125   g_return_val_if_fail (datetime != NULL, NULL);
1126
1127   return g_date_time_add_days (datetime, weeks * 7);
1128 }
1129
1130 /**
1131  * g_date_time_add_days:
1132  * @datetime: a #GDateTime
1133  * @days: the number of days
1134  *
1135  * Creates a copy of @datetime and adds the specified number of days to the
1136  * copy.
1137  *
1138  * Return value: the newly created #GDateTime which should be freed with
1139  *   g_date_time_unref().
1140  *
1141  * Since: 2.26
1142  */
1143 GDateTime*
1144 g_date_time_add_days (GDateTime *datetime,
1145                       gint       days)
1146 {
1147   g_return_val_if_fail (datetime != NULL, NULL);
1148
1149   if (days < -3660000 || days > 3660000)
1150     return NULL;
1151
1152   return g_date_time_replace_days (datetime, datetime->days + days);
1153 }
1154
1155 /**
1156  * g_date_time_add_hours:
1157  * @datetime: a #GDateTime
1158  * @hours: the number of hours to add
1159  *
1160  * Creates a copy of @datetime and adds the specified number of hours
1161  *
1162  * Return value: the newly created #GDateTime which should be freed with
1163  *   g_date_time_unref().
1164  *
1165  * Since: 2.26
1166  */
1167 GDateTime*
1168 g_date_time_add_hours (GDateTime *datetime,
1169                        gint       hours)
1170 {
1171   return g_date_time_add (datetime, hours * USEC_PER_HOUR);
1172 }
1173
1174 /**
1175  * g_date_time_add_minutes:
1176  * @datetime: a #GDateTime
1177  * @minutes: the number of minutes to add
1178  *
1179  * Creates a copy of @datetime adding the specified number of minutes.
1180  *
1181  * Return value: the newly created #GDateTime which should be freed with
1182  *   g_date_time_unref().
1183  *
1184  * Since: 2.26
1185  */
1186 GDateTime*
1187 g_date_time_add_minutes (GDateTime *datetime,
1188                          gint             minutes)
1189 {
1190   return g_date_time_add (datetime, minutes * USEC_PER_MINUTE);
1191 }
1192
1193
1194 /**
1195  * g_date_time_add_seconds:
1196  * @datetime: a #GDateTime
1197  * @seconds: the number of seconds to add
1198  *
1199  * Creates a copy of @datetime and adds the specified number of seconds.
1200  *
1201  * Return value: the newly created #GDateTime which should be freed with
1202  *   g_date_time_unref().
1203  *
1204  * Since: 2.26
1205  */
1206 GDateTime*
1207 g_date_time_add_seconds (GDateTime *datetime,
1208                          gdouble    seconds)
1209 {
1210   return g_date_time_add (datetime, seconds * USEC_PER_SECOND);
1211 }
1212
1213 /**
1214  * g_date_time_add_full:
1215  * @datetime: a #GDateTime
1216  * @years: the number of years to add
1217  * @months: the number of months to add
1218  * @days: the number of days to add
1219  * @hours: the number of hours to add
1220  * @minutes: the number of minutes to add
1221  * @seconds: the number of seconds to add
1222  *
1223  * Creates a new #GDateTime adding the specified values to the current date and
1224  * time in @datetime.
1225  *
1226  * Return value: the newly created #GDateTime that should be freed with
1227  *   g_date_time_unref().
1228  *
1229  * Since: 2.26
1230  */
1231 GDateTime *
1232 g_date_time_add_full (GDateTime *datetime,
1233                       gint       years,
1234                       gint       months,
1235                       gint       days,
1236                       gint       hours,
1237                       gint       minutes,
1238                       gdouble    seconds)
1239 {
1240   gint year, month, day;
1241   gint64 full_time;
1242   GDateTime *new;
1243   gint interval;
1244
1245   g_return_val_if_fail (datetime != NULL, NULL);
1246   g_date_time_get_ymd (datetime, &year, &month, &day);
1247
1248   months += years * 12;
1249
1250   if (months < -120000 || months > 120000)
1251     return NULL;
1252
1253   if (days < -3660000 || days > 3660000)
1254     return NULL;
1255
1256   year += months / 12;
1257   month += months % 12;
1258   if (month < 1)
1259     {
1260       month += 12;
1261       year--;
1262     }
1263   else if (month > 12)
1264     {
1265       month -= 12;
1266       year++;
1267     }
1268
1269   day = MIN (day, days_in_months[GREGORIAN_LEAP (year)][month]);
1270
1271   /* full_time is now in unix (local) time */
1272   full_time = datetime->usec / USEC_PER_SECOND + SEC_PER_DAY *
1273     (ymd_to_days (year, month, day) + days - UNIX_EPOCH_START);
1274
1275   interval = g_time_zone_adjust_time (datetime->tz,
1276                                       g_time_zone_is_dst (datetime->tz,
1277                                                           datetime->interval),
1278                                       &full_time);
1279
1280   /* move to UTC unix time */
1281   full_time -= g_time_zone_get_offset (datetime->tz, interval);
1282
1283   /* convert back to an instant, add back fractional seconds */
1284   full_time += UNIX_EPOCH_START * SEC_PER_DAY;
1285   full_time = full_time * USEC_PER_SECOND +
1286               datetime->usec % USEC_PER_SECOND;
1287
1288   /* do the actual addition now */
1289   full_time += (hours * USEC_PER_HOUR) +
1290                (minutes * USEC_PER_MINUTE) +
1291                (gint64) (seconds * USEC_PER_SECOND);
1292
1293   /* find the new interval */
1294   interval = g_time_zone_find_interval (datetime->tz,
1295                                         G_TIME_TYPE_UNIVERSAL,
1296                                         INSTANT_TO_UNIX (full_time));
1297
1298   /* convert back into local time */
1299   full_time += USEC_PER_SECOND *
1300                g_time_zone_get_offset (datetime->tz, interval);
1301
1302   /* split into days and usec of a new datetime */
1303   new = g_date_time_alloc (datetime->tz);
1304   new->interval = interval;
1305   new->days = full_time / USEC_PER_DAY;
1306   new->usec = full_time % USEC_PER_DAY;
1307
1308   /* XXX validate */
1309
1310   return new;
1311 }
1312
1313 /* Compare, difference, hash, equal {{{1 */
1314 /**
1315  * g_date_time_compare:
1316  * @dt1: first #GDateTime to compare
1317  * @dt2: second #GDateTime to compare
1318  *
1319  * #GCompareFunc-compatible comparison for #GDateTime<!-- -->'s. Both
1320  * #GDateTime<-- -->'s must be non-%NULL.
1321  *
1322  * Return value: 0 for equal, less than zero if dt1 is less than dt2, greater
1323  *   than zero if dt2 is greator than dt1.
1324  *
1325  * Since: 2.26
1326  */
1327 gint
1328 g_date_time_compare (gconstpointer dt1,
1329                      gconstpointer dt2)
1330 {
1331   gint64 difference;
1332
1333   difference = g_date_time_difference ((GDateTime *) dt1, (GDateTime *) dt2);
1334
1335   if (difference < 0)
1336     return -1;
1337
1338   else if (difference > 0)
1339     return 1;
1340
1341   else
1342     return 0;
1343 }
1344
1345 /**
1346  * g_date_time_difference:
1347  * @end: a #GDateTime
1348  * @begin: a #GDateTime
1349  *
1350  * Calculates the difference in time between @end and @begin.  The
1351  * #GTimeSpan that is returned is effectively @end - @begin (ie:
1352  * positive if the first simparameter is larger).
1353  *
1354  * Return value: the difference between the two #GDateTime, as a time
1355  *   span expressed in microseconds.
1356  *
1357  * Since: 2.26
1358  */
1359 GTimeSpan
1360 g_date_time_difference (GDateTime *end,
1361                         GDateTime *begin)
1362 {
1363   g_return_val_if_fail (begin != NULL, 0);
1364   g_return_val_if_fail (end != NULL, 0);
1365
1366   return g_date_time_to_instant (end) -
1367          g_date_time_to_instant (begin);
1368 }
1369
1370 /**
1371  * g_date_time_hash:
1372  * @datetime: a #GDateTime
1373  *
1374  * Hashes @datetime into a #guint, suitable for use within #GHashTable.
1375  *
1376  * Return value: a #guint containing the hash
1377  *
1378  * Since: 2.26
1379  */
1380 guint
1381 g_date_time_hash (gconstpointer datetime)
1382 {
1383   return g_date_time_to_instant ((GDateTime *) datetime);
1384 }
1385
1386 /**
1387  * g_date_time_equal:
1388  * @dt1: a #GDateTime
1389  * @dt2: a #GDateTime
1390  *
1391  * Checks to see if @dt1 and @dt2 are equal.
1392  *
1393  * Equal here means that they represent the same moment after converting
1394  * them to the same time zone.
1395  *
1396  * Return value: %TRUE if @dt1 and @dt2 are equal
1397  *
1398  * Since: 2.26
1399  */
1400 gboolean
1401 g_date_time_equal (gconstpointer dt1,
1402                    gconstpointer dt2)
1403 {
1404   return g_date_time_difference ((GDateTime *) dt1, (GDateTime *) dt2) == 0;
1405 }
1406
1407 /* Year, Month, Day Getters {{{1 */
1408 /**
1409  * g_date_time_get_ymd:
1410  * @datetime: a #GDateTime.
1411  * @year: (out): the return location for the gregorian year, or %NULL.
1412  * @month: (out): the return location for the month of the year, or %NULL.
1413  * @day: (out): the return location for the day of the month, or %NULL.
1414  *
1415  * Retrieves the Gregorian day, month, and year of a given #GDateTime.
1416  *
1417  * Since: 2.26
1418  **/
1419 void
1420 g_date_time_get_ymd (GDateTime *datetime,
1421                      gint      *year,
1422                      gint      *month,
1423                      gint      *day)
1424 {
1425   gint the_year;
1426   gint the_month;
1427   gint the_day;
1428   gint remaining_days;
1429   gint y100_cycles;
1430   gint y4_cycles;
1431   gint y1_cycles;
1432   gint preceding;
1433   gboolean leap;
1434
1435   g_return_if_fail (datetime != NULL);
1436
1437   remaining_days = datetime->days;
1438
1439   /*
1440    * We need to convert an offset in days to its year/month/day representation.
1441    * Leap years makes this a little trickier than it should be, so we use
1442    * 400, 100 and 4 years cycles here to get to the correct year.
1443    */
1444
1445   /* Our days offset starts sets 0001-01-01 as day 1, if it was day 0 our
1446    * math would be simpler, so let's do it */
1447   remaining_days--;
1448
1449   the_year = (remaining_days / DAYS_IN_400YEARS) * 400 + 1;
1450   remaining_days = remaining_days % DAYS_IN_400YEARS;
1451
1452   y100_cycles = remaining_days / DAYS_IN_100YEARS;
1453   remaining_days = remaining_days % DAYS_IN_100YEARS;
1454   the_year += y100_cycles * 100;
1455
1456   y4_cycles = remaining_days / DAYS_IN_4YEARS;
1457   remaining_days = remaining_days % DAYS_IN_4YEARS;
1458   the_year += y4_cycles * 4;
1459
1460   y1_cycles = remaining_days / 365;
1461   the_year += y1_cycles;
1462   remaining_days = remaining_days % 365;
1463
1464   if (y1_cycles == 4 || y100_cycles == 4) {
1465     g_assert (remaining_days == 0);
1466
1467     /* special case that indicates that the date is actually one year before,
1468      * in the 31th of December */
1469     the_year--;
1470     the_month = 12;
1471     the_day = 31;
1472     goto end;
1473   }
1474
1475   /* now get the month and the day */
1476   leap = y1_cycles == 3 && (y4_cycles != 24 || y100_cycles == 3);
1477
1478   g_assert (leap == GREGORIAN_LEAP(the_year));
1479
1480   the_month = (remaining_days + 50) >> 5;
1481   preceding = (days_in_year[0][the_month - 1] + (the_month > 2 && leap));
1482   if (preceding > remaining_days)
1483     {
1484       /* estimate is too large */
1485       the_month -= 1;
1486       preceding -= leap ? days_in_months[1][the_month]
1487                         : days_in_months[0][the_month];
1488     }
1489
1490   remaining_days -= preceding;
1491   g_assert(0 <= remaining_days);
1492
1493   the_day = remaining_days + 1;
1494
1495 end:
1496   if (year)
1497     *year = the_year;
1498   if (month)
1499     *month = the_month;
1500   if (day)
1501     *day = the_day;
1502 }
1503
1504 /**
1505  * g_date_time_get_year:
1506  * @datetime: A #GDateTime
1507  *
1508  * Retrieves the year represented by @datetime in the Gregorian calendar.
1509  *
1510  * Return value: the year represented by @datetime
1511  *
1512  * Since: 2.26
1513  */
1514 gint
1515 g_date_time_get_year (GDateTime *datetime)
1516 {
1517   gint year;
1518
1519   g_return_val_if_fail (datetime != NULL, 0);
1520
1521   g_date_time_get_ymd (datetime, &year, NULL, NULL);
1522
1523   return year;
1524 }
1525
1526 /**
1527  * g_date_time_get_month:
1528  * @datetime: a #GDateTime
1529  *
1530  * Retrieves the month of the year represented by @datetime in the Gregorian
1531  * calendar.
1532  *
1533  * Return value: the month represented by @datetime
1534  *
1535  * Since: 2.26
1536  */
1537 gint
1538 g_date_time_get_month (GDateTime *datetime)
1539 {
1540   gint month;
1541
1542   g_return_val_if_fail (datetime != NULL, 0);
1543
1544   g_date_time_get_ymd (datetime, NULL, &month, NULL);
1545
1546   return month;
1547 }
1548
1549 /**
1550  * g_date_time_get_day_of_month:
1551  * @datetime: a #GDateTime
1552  *
1553  * Retrieves the day of the month represented by @datetime in the gregorian
1554  * calendar.
1555  *
1556  * Return value: the day of the month
1557  *
1558  * Since: 2.26
1559  */
1560 gint
1561 g_date_time_get_day_of_month (GDateTime *datetime)
1562 {
1563   gint           day_of_year,
1564                  i;
1565   const guint16 *days;
1566   guint16        last = 0;
1567
1568   g_return_val_if_fail (datetime != NULL, 0);
1569
1570   days = days_in_year[GREGORIAN_LEAP (g_date_time_get_year (datetime)) ? 1 : 0];
1571   g_date_time_get_week_number (datetime, NULL, NULL, &day_of_year);
1572
1573   for (i = 1; i <= 12; i++)
1574     {
1575       if (days [i] >= day_of_year)
1576         return day_of_year - last;
1577       last = days [i];
1578     }
1579
1580   g_warn_if_reached ();
1581   return 0;
1582 }
1583
1584 /* Week of year / day of week getters {{{1 */
1585 /**
1586  * g_date_time_get_week_numbering_year:
1587  * @datetime: a #GDateTime
1588  *
1589  * Returns the ISO 8601 week-numbering year in which the week containing
1590  * @datetime falls.
1591  *
1592  * This function, taken together with g_date_time_get_week_of_year() and
1593  * g_date_time_get_day_of_week() can be used to determine the full ISO
1594  * week date on which @datetime falls.
1595  *
1596  * This is usually equal to the normal Gregorian year (as returned by
1597  * g_date_time_get_year()), except as detailed below:
1598  *
1599  * For Thursday, the week-numbering year is always equal to the usual
1600  * calendar year.  For other days, the number is such that every day
1601  * within a complete week (Monday to Sunday) is contained within the
1602  * same week-numbering year.
1603  *
1604  * For Monday, Tuesday and Wednesday occuring near the end of the year,
1605  * this may mean that the week-numbering year is one greater than the
1606  * calendar year (so that these days have the same week-numbering year
1607  * as the Thursday occuring early in the next year).
1608  *
1609  * For Friday, Saturaday and Sunday occuring near the start of the year,
1610  * this may mean that the week-numbering year is one less than the
1611  * calendar year (so that these days have the same week-numbering year
1612  * as the Thursday occuring late in the previous year).
1613  *
1614  * An equivalent description is that the week-numbering year is equal to
1615  * the calendar year containing the majority of the days in the current
1616  * week (Monday to Sunday).
1617  *
1618  * Note that January 1 0001 in the proleptic Gregorian calendar is a
1619  * Monday, so this function never returns 0.
1620  *
1621  * Returns: the ISO 8601 week-numbering year for @datetime
1622  *
1623  * Since: 2.26
1624  **/
1625 gint
1626 g_date_time_get_week_numbering_year (GDateTime *datetime)
1627 {
1628   gint year, month, day, weekday;
1629
1630   g_date_time_get_ymd (datetime, &year, &month, &day);
1631   weekday = g_date_time_get_day_of_week (datetime);
1632
1633   /* January 1, 2, 3 might be in the previous year if they occur after
1634    * Thursday.
1635    *
1636    *   Jan 1:  Friday, Saturday, Sunday    =>  day 1:  weekday 5, 6, 7
1637    *   Jan 2:  Saturday, Sunday            =>  day 2:  weekday 6, 7
1638    *   Jan 3:  Sunday                      =>  day 3:  weekday 7
1639    *
1640    * So we have a special case if (day - weekday) <= -4
1641    */
1642   if (month == 1 && (day - weekday) <= -4)
1643     return year - 1;
1644
1645   /* December 29, 30, 31 might be in the next year if they occur before
1646    * Thursday.
1647    *
1648    *   Dec 31: Monday, Tuesday, Wednesday  =>  day 31: weekday 1, 2, 3
1649    *   Dec 30: Monday, Tuesday             =>  day 30: weekday 1, 2
1650    *   Dec 29: Monday                      =>  day 29: weekday 1
1651    *
1652    * So we have a special case if (day - weekday) >= 28
1653    */
1654   else if (month == 12 && (day - weekday) >= 28)
1655     return year + 1;
1656
1657   else
1658     return year;
1659 }
1660
1661 /**
1662  * g_date_time_get_week_of_year:
1663  * @datetime: a #GDateTime
1664  *
1665  * Returns the ISO 8601 week number for the week containing @datetime.
1666  * The ISO 8601 week number is the same for every day of the week (from
1667  * Moday through Sunday).  That can produce some unusual results
1668  * (described below).
1669  *
1670  * The first week of the year is week 1.  This is the week that contains
1671  * the first Thursday of the year.  Equivalently, this is the first week
1672  * that has more than 4 of its days falling within the calendar year.
1673  *
1674  * The value 0 is never returned by this function.  Days contained
1675  * within a year but occuring before the first ISO 8601 week of that
1676  * year are considered as being contained in the last week of the
1677  * previous year.  Similarly, the final days of a calendar year may be
1678  * considered as being part of the first ISO 8601 week of the next year
1679  * if 4 or more days of that week are contained within the new year.
1680  *
1681  * Returns: the ISO 8601 week number for @datetime.
1682  *
1683  * Since: 2.26
1684  */
1685 gint
1686 g_date_time_get_week_of_year (GDateTime *datetime)
1687 {
1688   gint weeknum;
1689
1690   g_return_val_if_fail (datetime != NULL, 0);
1691
1692   g_date_time_get_week_number (datetime, &weeknum, NULL, NULL);
1693
1694   return weeknum;
1695 }
1696
1697 /**
1698  * g_date_time_get_day_of_week:
1699  * @datetime: a #GDateTime
1700  *
1701  * Retrieves the ISO 8601 day of the week on which @datetime falls (1 is
1702  * Monday, 2 is Tuesday... 7 is Sunday).
1703  *
1704  * Return value: the day of the week
1705  *
1706  * Since: 2.26
1707  */
1708 gint
1709 g_date_time_get_day_of_week (GDateTime *datetime)
1710 {
1711   g_return_val_if_fail (datetime != NULL, 0);
1712
1713   return (datetime->days - 1) % 7 + 1;
1714 }
1715
1716 /* Day of year getter {{{1 */
1717 /**
1718  * g_date_time_get_day_of_year:
1719  * @datetime: a #GDateTime
1720  *
1721  * Retrieves the day of the year represented by @datetime in the Gregorian
1722  * calendar.
1723  *
1724  * Return value: the day of the year
1725  *
1726  * Since: 2.26
1727  */
1728 gint
1729 g_date_time_get_day_of_year (GDateTime *datetime)
1730 {
1731   gint doy = 0;
1732
1733   g_return_val_if_fail (datetime != NULL, 0);
1734
1735   g_date_time_get_week_number (datetime, NULL, NULL, &doy);
1736   return doy;
1737 }
1738
1739 /* Time component getters {{{1 */
1740
1741 /**
1742  * g_date_time_get_hour:
1743  * @datetime: a #GDateTime
1744  *
1745  * Retrieves the hour of the day represented by @datetime
1746  *
1747  * Return value: the hour of the day
1748  *
1749  * Since: 2.26
1750  */
1751 gint
1752 g_date_time_get_hour (GDateTime *datetime)
1753 {
1754   g_return_val_if_fail (datetime != NULL, 0);
1755
1756   return (datetime->usec / USEC_PER_HOUR);
1757 }
1758
1759 /**
1760  * g_date_time_get_minute:
1761  * @datetime: a #GDateTime
1762  *
1763  * Retrieves the minute of the hour represented by @datetime
1764  *
1765  * Return value: the minute of the hour
1766  *
1767  * Since: 2.26
1768  */
1769 gint
1770 g_date_time_get_minute (GDateTime *datetime)
1771 {
1772   g_return_val_if_fail (datetime != NULL, 0);
1773
1774   return (datetime->usec % USEC_PER_HOUR) / USEC_PER_MINUTE;
1775 }
1776
1777 /**
1778  * g_date_time_get_second:
1779  * @datetime: a #GDateTime
1780  *
1781  * Retrieves the second of the minute represented by @datetime
1782  *
1783  * Return value: the second represented by @datetime
1784  *
1785  * Since: 2.26
1786  */
1787 gint
1788 g_date_time_get_second (GDateTime *datetime)
1789 {
1790   g_return_val_if_fail (datetime != NULL, 0);
1791
1792   return (datetime->usec % USEC_PER_MINUTE) / USEC_PER_SECOND;
1793 }
1794
1795 /**
1796  * g_date_time_get_microsecond:
1797  * @datetime: a #GDateTime
1798  *
1799  * Retrieves the microsecond of the date represented by @datetime
1800  *
1801  * Return value: the microsecond of the second
1802  *
1803  * Since: 2.26
1804  */
1805 gint
1806 g_date_time_get_microsecond (GDateTime *datetime)
1807 {
1808   g_return_val_if_fail (datetime != NULL, 0);
1809
1810   return (datetime->usec % USEC_PER_SECOND);
1811 }
1812
1813 /**
1814  * g_date_time_get_seconds:
1815  * @datetime: a #GDateTime
1816  *
1817  * Retrieves the number of seconds since the start of the last minute,
1818  * including the fractional part.
1819  *
1820  * Returns: the number of seconds
1821  *
1822  * Since: 2.26
1823  **/
1824 gdouble
1825 g_date_time_get_seconds (GDateTime *datetime)
1826 {
1827   g_return_val_if_fail (datetime != NULL, 0);
1828
1829   return (datetime->usec % USEC_PER_MINUTE) / 1000000.0;
1830 }
1831
1832 /* Exporters {{{1 */
1833 /**
1834  * g_date_time_to_unix:
1835  * @datetime: a #GDateTime
1836  *
1837  * Gives the Unix time corresponding to @datetime, rounding down to the
1838  * nearest second.
1839  *
1840  * Unix time is the number of seconds that have elapsed since 1970-01-01
1841  * 00:00:00 UTC, regardless of the time zone associated with @datetime.
1842  *
1843  * Returns: the Unix time corresponding to @datetime
1844  *
1845  * Since: 2.26
1846  **/
1847 gint64
1848 g_date_time_to_unix (GDateTime *datetime)
1849 {
1850   return INSTANT_TO_UNIX (g_date_time_to_instant (datetime));
1851 }
1852
1853 /**
1854  * g_date_time_to_timeval:
1855  * @datetime: a #GDateTime
1856  * @tv: a #GTimeVal to modify
1857  *
1858  * Stores the instant in time that @datetime represents into @tv.
1859  *
1860  * The time contained in a #GTimeVal is always stored in the form of
1861  * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the time
1862  * zone associated with @datetime.
1863  *
1864  * On systems where 'long' is 32bit (ie: all 32bit systems and all
1865  * Windows systems), a #GTimeVal is incapable of storing the entire
1866  * range of values that #GDateTime is capable of expressing.  On those
1867  * systems, this function returns %FALSE to indicate that the time is
1868  * out of range.
1869  *
1870  * On systems where 'long' is 64bit, this function never fails.
1871  *
1872  * Returns: %TRUE if successful, else %FALSE
1873  *
1874  * Since: 2.26
1875  **/
1876 gboolean
1877 g_date_time_to_timeval (GDateTime *datetime,
1878                         GTimeVal  *tv)
1879 {
1880   tv->tv_sec = INSTANT_TO_UNIX (g_date_time_to_instant (datetime));
1881   tv->tv_usec = datetime->usec % USEC_PER_SECOND;
1882
1883   return TRUE;
1884 }
1885
1886 /* Timezone queries {{{1 */
1887 /**
1888  * g_date_time_get_utc_offset:
1889  * @datetime: a #GDateTime
1890  *
1891  * Determines the offset to UTC in effect at the time and in the time
1892  * zone of @datetime.
1893  *
1894  * The offset is the number of microseconds that you add to UTC time to
1895  * arrive at local time for the time zone (ie: negative numbers for time
1896  * zones west of GMT, positive numbers for east).
1897  *
1898  * If @datetime represents UTC time, then the offset is always zero.
1899  *
1900  * Returns: the number of microseconds that should be added to UTC to
1901  *          get the local time
1902  *
1903  * Since: 2.26
1904  **/
1905 GTimeSpan
1906 g_date_time_get_utc_offset (GDateTime *datetime)
1907 {
1908   gint offset;
1909
1910   g_return_val_if_fail (datetime != NULL, 0);
1911
1912   offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
1913
1914   return (gint64) offset * USEC_PER_SECOND;
1915 }
1916
1917 /**
1918  * g_date_time_get_timezone_abbreviation:
1919  * @datetime: a #GDateTime
1920  *
1921  * Determines the time zone abbreviation to be used at the time and in
1922  * the time zone of @datetime.
1923  *
1924  * For example, in Toronto this is currently "EST" during the winter
1925  * months and "EDT" during the summer months when daylight savings
1926  * time is in effect.
1927  *
1928  * Returns: (transfer none): the time zone abbreviation. The returned
1929  *          string is owned by the #GDateTime and it should not be
1930  *          modified or freed
1931  *
1932  * Since: 2.26
1933  **/
1934 const gchar *
1935 g_date_time_get_timezone_abbreviation (GDateTime *datetime)
1936 {
1937   g_return_val_if_fail (datetime != NULL, NULL);
1938
1939   return g_time_zone_get_abbreviation (datetime->tz, datetime->interval);
1940 }
1941
1942 /**
1943  * g_date_time_is_daylight_savings:
1944  * @datetime: a #GDateTime
1945  *
1946  * Determines if daylight savings time is in effect at the time and in
1947  * the time zone of @datetime.
1948  *
1949  * Returns: %TRUE if daylight savings time is in effect
1950  *
1951  * Since: 2.26
1952  **/
1953 gboolean
1954 g_date_time_is_daylight_savings (GDateTime *datetime)
1955 {
1956   g_return_val_if_fail (datetime != NULL, FALSE);
1957
1958   return g_time_zone_is_dst (datetime->tz, datetime->interval);
1959 }
1960
1961 /* Timezone convert {{{1 */
1962 /**
1963  * g_date_time_to_timezone:
1964  * @datetime: a #GDateTime
1965  * @tz: the new #GTimeZone
1966  *
1967  * Create a new #GDateTime corresponding to the same instant in time as
1968  * @datetime, but in the time zone @tz.
1969  *
1970  * This call can fail in the case that the time goes out of bounds.  For
1971  * example, converting 0001-01-01 00:00:00 UTC to a time zone west of
1972  * Greenwich will fail (due to the year 0 being out of range).
1973  *
1974  * You should release the return value by calling g_date_time_unref()
1975  * when you are done with it.
1976  *
1977  * Returns: a new #GDateTime, or %NULL
1978  *
1979  * Since: 2.26
1980  **/
1981 GDateTime *
1982 g_date_time_to_timezone (GDateTime *datetime,
1983                          GTimeZone *tz)
1984 {
1985   return g_date_time_from_instant (tz, g_date_time_to_instant (datetime));
1986 }
1987
1988 /**
1989  * g_date_time_to_local:
1990  * @datetime: a #GDateTime
1991  *
1992  * Creates a new #GDateTime corresponding to the same instant in time as
1993  * @datetime, but in the local time zone.
1994  *
1995  * This call is equivalent to calling g_date_time_to_timezone() with the
1996  * time zone returned by g_time_zone_new_local().
1997  *
1998  * Returns: the newly created #GDateTime
1999  *
2000  * Since: 2.26
2001  **/
2002 GDateTime *
2003 g_date_time_to_local (GDateTime *datetime)
2004 {
2005   GDateTime *new;
2006   GTimeZone *local;
2007
2008   local = g_time_zone_new_local ();
2009   new = g_date_time_to_timezone (datetime, local);
2010   g_time_zone_unref (local);
2011
2012   return new;
2013 }
2014
2015 /**
2016  * g_date_time_to_utc:
2017  * @datetime: a #GDateTime
2018  *
2019  * Creates a new #GDateTime corresponding to the same instant in time as
2020  * @datetime, but in UTC.
2021  *
2022  * This call is equivalent to calling g_date_time_to_timezone() with the
2023  * time zone returned by g_time_zone_new_utc().
2024  *
2025  * Returns: the newly created #GDateTime
2026  *
2027  * Since: 2.26
2028  **/
2029 GDateTime *
2030 g_date_time_to_utc (GDateTime *datetime)
2031 {
2032   GDateTime *new;
2033   GTimeZone *utc;
2034
2035   utc = g_time_zone_new_utc ();
2036   new = g_date_time_to_timezone (datetime, utc);
2037   g_time_zone_unref (utc);
2038
2039   return new;
2040 }
2041
2042 /* Format {{{1 */
2043 /**
2044  * g_date_time_format:
2045  * @datetime: A #GDateTime
2046  * @format: a valid UTF-8 string, containing the format for the
2047  *          #GDateTime
2048  *
2049  * Creates a newly allocated string representing the requested @format.
2050  *
2051  * The following format specifiers are supported:
2052  *
2053  * <variablelist>
2054  *  <varlistentry><term>
2055  *    <literal>%%a</literal>:
2056  *   </term><listitem><simpara>
2057  *    the abbreviated weekday name according to the current locale
2058  *  </simpara></listitem></varlistentry>
2059  *  <varlistentry><term>
2060  *    <literal>%%A</literal>:
2061  *   </term><listitem><simpara>
2062  *    the full weekday name according to the current locale
2063  *  </simpara></listitem></varlistentry>
2064  *  <varlistentry><term>
2065  *    <literal>%%b</literal>:
2066  *   </term><listitem><simpara>
2067  *    the abbreviated month name according to the current locale
2068  *  </simpara></listitem></varlistentry>
2069  *  <varlistentry><term>
2070  *    <literal>%%B</literal>:
2071  *   </term><listitem><simpara>
2072  *    the full month name according to the current locale
2073  *  </simpara></listitem></varlistentry>
2074  *  <varlistentry><term>
2075  *    <literal>%%d</literal>:
2076  *   </term><listitem><simpara>
2077  *    the day of the month as a decimal number (range 01 to 31)
2078  *  </simpara></listitem></varlistentry>
2079  *  <varlistentry><term>
2080  *    <literal>%%e</literal>:
2081  *   </term><listitem><simpara>
2082  *    the day of the month as a decimal number (range  1 to 31)
2083  *  </simpara></listitem></varlistentry>
2084  *  <varlistentry><term>
2085  *    <literal>%%F</literal>:
2086  *   </term><listitem><simpara>
2087  *    equivalent to <literal>%%Y-%%m-%%d</literal> (the ISO 8601 date
2088  *    format)
2089  *  </simpara></listitem></varlistentry>
2090  *  <varlistentry><term>
2091  *    <literal>%%h</literal>:
2092  *   </term><listitem><simpara>
2093  *    equivalent to <literal>%%b</literal>
2094  *  </simpara></listitem></varlistentry>
2095  *  <varlistentry><term>
2096  *    <literal>%%H</literal>:
2097  *   </term><listitem><simpara>
2098  *    the hour as a decimal number using a 24-hour clock (range 00 to
2099  *    23)
2100  *  </simpara></listitem></varlistentry>
2101  *  <varlistentry><term>
2102  *    <literal>%%I</literal>:
2103  *   </term><listitem><simpara>
2104  *    the hour as a decimal number using a 12-hour clock (range 01 to
2105  *    12)
2106  *  </simpara></listitem></varlistentry>
2107  *  <varlistentry><term>
2108  *    <literal>%%j</literal>:
2109  *   </term><listitem><simpara>
2110  *    the day of the year as a decimal number (range 001 to 366)
2111  *  </simpara></listitem></varlistentry>
2112  *  <varlistentry><term>
2113  *    <literal>%%k</literal>:
2114  *   </term><listitem><simpara>
2115  *    the hour (24-hour clock) as a decimal number (range 0 to 23);
2116  *    single digits are preceded by a blank
2117  *  </simpara></listitem></varlistentry>
2118  *  <varlistentry><term>
2119  *    <literal>%%l</literal>:
2120  *   </term><listitem><simpara>
2121  *    the hour (12-hour clock) as a decimal number (range 1 to 12);
2122  *    single digits are preceded by a blank
2123  *  </simpara></listitem></varlistentry>
2124  *  <varlistentry><term>
2125  *    <literal>%%m</literal>:
2126  *   </term><listitem><simpara>
2127  *    the month as a decimal number (range 01 to 12)
2128  *  </simpara></listitem></varlistentry>
2129  *  <varlistentry><term>
2130  *    <literal>%%M</literal>:
2131  *   </term><listitem><simpara>
2132  *    the minute as a decimal number (range 00 to 59)
2133  *  </simpara></listitem></varlistentry>
2134  *  <varlistentry><term>
2135  *    <literal>%%N</literal>:
2136  *   </term><listitem><simpara>
2137  *    the micro-seconds as a decimal number
2138  *  </simpara></listitem></varlistentry>
2139  *  <varlistentry><term>
2140  *    <literal>%%p</literal>:
2141  *   </term><listitem><simpara>
2142  *    either "AM" or "PM" according to the given time value, or the
2143  *    corresponding  strings for the current locale.  Noon is treated as
2144  *    "PM" and midnight as "AM".
2145  *  </simpara></listitem></varlistentry>
2146  *  <varlistentry><term>
2147  *    <literal>%%P</literal>:
2148  *   </term><listitem><simpara>
2149  *    like %%p but lowercase: "am" or "pm" or a corresponding string for
2150  *    the current locale
2151  *  </simpara></listitem></varlistentry>
2152  *  <varlistentry><term>
2153  *    <literal>%%r</literal>:
2154  *   </term><listitem><simpara>
2155  *    the time in a.m. or p.m. notation
2156  *  </simpara></listitem></varlistentry>
2157  *  <varlistentry><term>
2158  *    <literal>%%R</literal>:
2159  *   </term><listitem><simpara>
2160  *    the time in 24-hour notation (<literal>%%H:%%M</literal>)
2161  *  </simpara></listitem></varlistentry>
2162  *  <varlistentry><term>
2163  *    <literal>%%s</literal>:
2164  *   </term><listitem><simpara>
2165  *    the number of seconds since the Epoch, that is, since 1970-01-01
2166  *    00:00:00 UTC
2167  *  </simpara></listitem></varlistentry>
2168  *  <varlistentry><term>
2169  *    <literal>%%S</literal>:
2170  *   </term><listitem><simpara>
2171  *    the second as a decimal number (range 00 to 60)
2172  *  </simpara></listitem></varlistentry>
2173  *  <varlistentry><term>
2174  *    <literal>%%t</literal>:
2175  *   </term><listitem><simpara>
2176  *    a tab character
2177  *  </simpara></listitem></varlistentry>
2178  *  <varlistentry><term>
2179  *    <literal>%%u</literal>:
2180  *   </term><listitem><simpara>
2181  *    the day of the week as a decimal, range 1 to 7, Monday being 1
2182  *  </simpara></listitem></varlistentry>
2183  *  <varlistentry><term>
2184  *    <literal>%%W</literal>:
2185  *   </term><listitem><simpara>
2186  *    the week number of the current year as a decimal number
2187  *  </simpara></listitem></varlistentry>
2188  *  <varlistentry><term>
2189  *    <literal>%%x</literal>:
2190  *   </term><listitem><simpara>
2191  *    the preferred date representation for the current locale without
2192  *    the time
2193  *  </simpara></listitem></varlistentry>
2194  *  <varlistentry><term>
2195  *    <literal>%%X</literal>:
2196  *   </term><listitem><simpara>
2197  *    the preferred time representation for the current locale without
2198  *    the date
2199  *  </simpara></listitem></varlistentry>
2200  *  <varlistentry><term>
2201  *    <literal>%%y</literal>:
2202  *   </term><listitem><simpara>
2203  *    the year as a decimal number without the century
2204  *  </simpara></listitem></varlistentry>
2205  *  <varlistentry><term>
2206  *    <literal>%%Y</literal>:
2207  *   </term><listitem><simpara>
2208  *    the year as a decimal number including the century
2209  *  </simpara></listitem></varlistentry>
2210  *  <varlistentry><term>
2211  *    <literal>%%z</literal>:
2212  *   </term><listitem><simpara>
2213  *    the time-zone as hour offset from UTC
2214  *  </simpara></listitem></varlistentry>
2215  *  <varlistentry><term>
2216  *    <literal>%%Z</literal>:
2217  *   </term><listitem><simpara>
2218  *    the time zone or name or abbreviation
2219  *  </simpara></listitem></varlistentry>
2220  *  <varlistentry><term>
2221  *    <literal>%%%</literal>:
2222  *   </term><listitem><simpara>
2223  *    a literal <literal>%%</literal> character
2224  *  </simpara></listitem></varlistentry>
2225  * </variablelist>
2226  *
2227  * Returns: a newly allocated string formatted to the requested format
2228  *          or %NULL in the case that there was an error.  The string
2229  *          should be freed with g_free().
2230  *
2231  * Since: 2.26
2232  */
2233 gchar *
2234 g_date_time_format (GDateTime *datetime,
2235                     const gchar     *format)
2236 {
2237   GString  *outstr;
2238   gchar    *tmp;
2239   gunichar  c;
2240   glong     utf8len;
2241   gboolean  in_mod;
2242
2243   g_return_val_if_fail (datetime != NULL, NULL);
2244   g_return_val_if_fail (format != NULL, NULL);
2245   g_return_val_if_fail (g_utf8_validate (format, -1, NULL), NULL);
2246
2247   outstr = g_string_sized_new (strlen (format) * 2);
2248   utf8len = g_utf8_strlen (format, -1);
2249   in_mod = FALSE;
2250
2251   for (; *format; format = g_utf8_next_char(format))
2252     {
2253       c = g_utf8_get_char (format);
2254
2255       switch (c)
2256         {
2257         case '%':
2258           if (!in_mod)
2259             {
2260               in_mod = TRUE;
2261               break;
2262             }
2263             /* Fall through */
2264         default:
2265           if (in_mod)
2266             {
2267               switch (c)
2268                 {
2269                 case 'a':
2270                   g_string_append (outstr, WEEKDAY_ABBR (datetime));
2271                   break;
2272                 case 'A':
2273                   g_string_append (outstr, WEEKDAY_FULL (datetime));
2274                   break;
2275                 case 'b':
2276                   g_string_append (outstr, MONTH_ABBR (datetime));
2277                   break;
2278                 case 'B':
2279                   g_string_append (outstr, MONTH_FULL (datetime));
2280                   break;
2281                 case 'd':
2282                   g_string_append_printf (outstr, "%02d", g_date_time_get_day_of_month (datetime));
2283                   break;
2284                 case 'e':
2285                   g_string_append_printf (outstr, "%2d", g_date_time_get_day_of_month (datetime));
2286                   break;
2287                 case 'F':
2288                   g_string_append_printf (outstr, "%d-%02d-%02d",
2289                                           g_date_time_get_year (datetime),
2290                                           g_date_time_get_month (datetime),
2291                                           g_date_time_get_day_of_month (datetime));
2292                   break;
2293                 case 'h':
2294                   g_string_append (outstr, MONTH_ABBR (datetime));
2295                   break;
2296                 case 'H':
2297                   g_string_append_printf (outstr, "%02d", g_date_time_get_hour (datetime));
2298                   break;
2299                 case 'I':
2300                   if (g_date_time_get_hour (datetime) == 0)
2301                     g_string_append (outstr, "12");
2302                   else
2303                     g_string_append_printf (outstr, "%02d", g_date_time_get_hour (datetime) % 12);
2304                   break;
2305                 case 'j':
2306                   g_string_append_printf (outstr, "%03d", g_date_time_get_day_of_year (datetime));
2307                   break;
2308                 case 'k':
2309                   g_string_append_printf (outstr, "%2d", g_date_time_get_hour (datetime));
2310                   break;
2311                 case 'l':
2312                   if (g_date_time_get_hour (datetime) == 0)
2313                     g_string_append (outstr, "12");
2314                   else
2315                     g_string_append_printf (outstr, "%2d", g_date_time_get_hour (datetime) % 12);
2316                   break;
2317                 case 'm':
2318                   g_string_append_printf (outstr, "%02d", g_date_time_get_month (datetime));
2319                   break;
2320                 case 'M':
2321                   g_string_append_printf (outstr, "%02d", g_date_time_get_minute (datetime));
2322                   break;
2323                 case 'N':
2324                   g_string_append_printf (outstr, "%"G_GUINT64_FORMAT, datetime->usec % USEC_PER_SECOND);
2325                   break;
2326                 case 'p':
2327                   g_string_append (outstr, GET_AMPM (datetime, FALSE));
2328                   break;
2329                 case 'P':
2330                   g_string_append (outstr, GET_AMPM (datetime, TRUE));
2331                   break;
2332                 case 'r':
2333                   {
2334                     gint hour = g_date_time_get_hour (datetime) % 12;
2335                     if (hour == 0)
2336                       hour = 12;
2337                     g_string_append_printf (outstr, "%02d:%02d:%02d %s",
2338                                             hour,
2339                                             g_date_time_get_minute (datetime),
2340                                             g_date_time_get_second (datetime),
2341                                             GET_AMPM (datetime, FALSE));
2342                   }
2343                   break;
2344                 case 'R':
2345                   g_string_append_printf (outstr, "%02d:%02d",
2346                                           g_date_time_get_hour (datetime),
2347                                           g_date_time_get_minute (datetime));
2348                   break;
2349                 case 's':
2350                   g_string_append_printf (outstr, "%" G_GINT64_FORMAT, g_date_time_to_unix (datetime));
2351                   break;
2352                 case 'S':
2353                   g_string_append_printf (outstr, "%02d", g_date_time_get_second (datetime));
2354                   break;
2355                 case 't':
2356                   g_string_append_c (outstr, '\t');
2357                   break;
2358                 case 'u':
2359                   g_string_append_printf (outstr, "%d", g_date_time_get_day_of_week (datetime));
2360                   break;
2361                 case 'W':
2362                   g_string_append_printf (outstr, "%d", g_date_time_get_day_of_year (datetime) / 7);
2363                   break;
2364                 case 'x':
2365                   {
2366                     tmp = GET_PREFERRED_DATE (datetime);
2367                     g_string_append (outstr, tmp);
2368                     g_free (tmp);
2369                   }
2370                   break;
2371                 case 'X':
2372                   {
2373                     tmp = GET_PREFERRED_TIME (datetime);
2374                     g_string_append (outstr, tmp);
2375                     g_free (tmp);
2376                   }
2377                   break;
2378                 case 'y':
2379                   g_string_append_printf (outstr, "%02d", g_date_time_get_year (datetime) % 100);
2380                   break;
2381                 case 'Y':
2382                   g_string_append_printf (outstr, "%d", g_date_time_get_year (datetime));
2383                   break;
2384                 case 'z':
2385                   if (datetime->tz != NULL)
2386                     {
2387                       gint64 offset = g_date_time_get_utc_offset (datetime)
2388                                     / USEC_PER_SECOND;
2389
2390                       g_string_append_printf (outstr, "%c%02d%02d",
2391                                               offset >= 0 ? '+' : '-',
2392                                               (int) offset / 3600,
2393                                               (int) offset / 60 % 60);
2394                     }
2395                   else
2396                     g_string_append (outstr, "+0000");
2397                   break;
2398                 case 'Z':
2399                   g_string_append (outstr, g_date_time_get_timezone_abbreviation (datetime));
2400                   break;
2401                 case '%':
2402                   g_string_append_c (outstr, '%');
2403                   break;
2404                 case 'n':
2405                   g_string_append_c (outstr, '\n');
2406                   break;
2407                 default:
2408                   goto bad_format;
2409                 }
2410               in_mod = FALSE;
2411             }
2412           else
2413             g_string_append_unichar (outstr, c);
2414         }
2415     }
2416
2417   return g_string_free (outstr, FALSE);
2418
2419 bad_format:
2420   g_string_free (outstr, TRUE);
2421   return NULL;
2422 }
2423
2424
2425 /* Epilogue {{{1 */
2426 /* vim:set foldmethod=marker: */