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