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