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