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