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