Fix getauxval error at qemu
[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  * Copyright © 2018 Tomasz Miąsko
8  *
9  * SPDX-License-Identifier: LGPL-2.1-or-later
10  *
11  * This library is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License as
13  * published by the Free Software Foundation; either version 2.1 of the
14  * licence, or (at your option) any later version.
15  *
16  * This is distributed in the hope that it will be useful, but WITHOUT
17  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
19  * License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * along with this library; if not, see <http://www.gnu.org/licenses/>.
23  *
24  * Authors: Christian Hergert <chris@dronelabs.com>
25  *          Thiago Santos <thiago.sousa.santos@collabora.co.uk>
26  *          Emmanuele Bassi <ebassi@linux.intel.com>
27  *          Ryan Lortie <desrt@desrt.ca>
28  *          Robert Ancell <robert.ancell@canonical.com>
29  */
30
31 /* Algorithms within this file are based on the Calendar FAQ by
32  * Claus Tondering.  It can be found at
33  * http://www.tondering.dk/claus/cal/calendar29.txt
34  *
35  * Copyright and disclaimer
36  * ------------------------
37  *   This document is Copyright (C) 2008 by Claus Tondering.
38  *   E-mail: claus@tondering.dk. (Please include the word
39  *   "calendar" in the subject line.)
40  *   The document may be freely distributed, provided this
41  *   copyright notice is included and no money is charged for
42  *   the document.
43  *
44  *   This document is provided "as is". No warranties are made as
45  *   to its correctness.
46  */
47
48 /* Prologue {{{1 */
49
50 #include "config.h"
51
52 /* langinfo.h in glibc 2.27 defines ALTMON_* only if _GNU_SOURCE is defined.  */
53 #ifndef _GNU_SOURCE
54 #define _GNU_SOURCE 1
55 #endif
56
57 #include <math.h>
58 #include <stdlib.h>
59 #include <string.h>
60
61 #ifdef HAVE_LANGINFO_TIME
62 #include <langinfo.h>
63 #endif
64
65 #include "gatomic.h"
66 #include "gcharset.h"
67 #include "gcharsetprivate.h"
68 #include "gconvert.h"
69 #include "gconvertprivate.h"
70 #include "gdatetime.h"
71 #include "gfileutils.h"
72 #include "ghash.h"
73 #include "glibintl.h"
74 #include "gmain.h"
75 #include "gmappedfile.h"
76 #include "gslice.h"
77 #include "gstrfuncs.h"
78 #include "gtestutils.h"
79 #include "gthread.h"
80 #include "gtimezone.h"
81
82 #ifndef G_OS_WIN32
83 #include <sys/time.h>
84 #include <time.h>
85 #else
86 #if defined (_MSC_VER) && (_MSC_VER < 1800)
87 /* fallback implementation for isnan() on VS2012 and earlier */
88 #define isnan _isnan
89 #endif
90 #endif /* !G_OS_WIN32 */
91
92 /**
93  * SECTION:date-time
94  * @title: GDateTime
95  * @short_description: a structure representing Date and Time
96  * @see_also: #GTimeZone
97  *
98  * #GDateTime is a structure that combines a Gregorian date and time
99  * into a single structure.  It provides many conversion and methods to
100  * manipulate dates and times.  Time precision is provided down to
101  * microseconds and the time can range (proleptically) from 0001-01-01
102  * 00:00:00 to 9999-12-31 23:59:59.999999.  #GDateTime follows POSIX
103  * time in the sense that it is oblivious to leap seconds.
104  *
105  * #GDateTime is an immutable object; once it has been created it cannot
106  * be modified further.  All modifiers will create a new #GDateTime.
107  * Nearly all such functions can fail due to the date or time going out
108  * of range, in which case %NULL will be returned.
109  *
110  * #GDateTime is reference counted: the reference count is increased by calling
111  * g_date_time_ref() and decreased by calling g_date_time_unref(). When the
112  * reference count drops to 0, the resources allocated by the #GDateTime
113  * structure are released.
114  *
115  * Many parts of the API may produce non-obvious results.  As an
116  * example, adding two months to January 31st will yield March 31st
117  * whereas adding one month and then one month again will yield either
118  * March 28th or March 29th.  Also note that adding 24 hours is not
119  * always the same as adding one day (since days containing daylight
120  * savings time transitions are either 23 or 25 hours in length).
121  *
122  * #GDateTime is available since GLib 2.26.
123  */
124
125 struct _GDateTime
126 {
127   /* Microsecond timekeeping within Day */
128   guint64 usec;
129
130   /* TimeZone information */
131   GTimeZone *tz;
132   gint interval;
133
134   /* 1 is 0001-01-01 in Proleptic Gregorian */
135   gint32 days;
136
137   gint ref_count;  /* (atomic) */
138 };
139
140 /* Time conversion {{{1 */
141
142 #define UNIX_EPOCH_START     719163
143 #define INSTANT_TO_UNIX(instant) \
144   ((instant)/USEC_PER_SECOND - UNIX_EPOCH_START * SEC_PER_DAY)
145 #define INSTANT_TO_UNIX_USECS(instant) \
146   ((instant) - UNIX_EPOCH_START * SEC_PER_DAY * USEC_PER_SECOND)
147 #define UNIX_TO_INSTANT(unix) \
148   (((gint64) (unix) + UNIX_EPOCH_START * SEC_PER_DAY) * USEC_PER_SECOND)
149 #define UNIX_USECS_TO_INSTANT(unix_usecs) \
150   ((gint64) (unix_usecs) + UNIX_EPOCH_START * SEC_PER_DAY * USEC_PER_SECOND)
151 #define UNIX_TO_INSTANT_IS_VALID(unix) \
152   ((gint64) (unix) <= INSTANT_TO_UNIX (G_MAXINT64))
153 #define UNIX_USECS_TO_INSTANT_IS_VALID(unix_usecs) \
154   ((gint64) (unix_usecs) <= INSTANT_TO_UNIX_USECS (G_MAXINT64))
155
156 #define DAYS_IN_4YEARS    1461    /* days in 4 years */
157 #define DAYS_IN_100YEARS  36524   /* days in 100 years */
158 #define DAYS_IN_400YEARS  146097  /* days in 400 years  */
159
160 #define USEC_PER_SECOND      (G_GINT64_CONSTANT (1000000))
161 #define USEC_PER_MINUTE      (G_GINT64_CONSTANT (60000000))
162 #define USEC_PER_HOUR        (G_GINT64_CONSTANT (3600000000))
163 #define USEC_PER_MILLISECOND (G_GINT64_CONSTANT (1000))
164 #define USEC_PER_DAY         (G_GINT64_CONSTANT (86400000000))
165 #define SEC_PER_DAY          (G_GINT64_CONSTANT (86400))
166
167 #define SECS_PER_MINUTE (60)
168 #define SECS_PER_HOUR   (60 * SECS_PER_MINUTE)
169 #define SECS_PER_DAY    (24 * SECS_PER_HOUR)
170 #define SECS_PER_YEAR   (365 * SECS_PER_DAY)
171 #define SECS_PER_JULIAN (DAYS_PER_PERIOD * SECS_PER_DAY)
172
173 #define GREGORIAN_LEAP(y)    ((((y) % 4) == 0) && (!((((y) % 100) == 0) && (((y) % 400) != 0))))
174 #define JULIAN_YEAR(d)       ((d)->julian / 365.25)
175 #define DAYS_PER_PERIOD      (G_GINT64_CONSTANT (2914695))
176
177 static const guint16 days_in_months[2][13] =
178 {
179   { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
180   { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
181 };
182
183 static const guint16 days_in_year[2][13] =
184 {
185   {  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
186   {  0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
187 };
188
189 #ifdef HAVE_LANGINFO_TIME
190
191 #define GET_AMPM(d) ((g_date_time_get_hour (d) < 12) ? \
192                      nl_langinfo (AM_STR) : \
193                      nl_langinfo (PM_STR))
194 #define GET_AMPM_IS_LOCALE TRUE
195
196 #define PREFERRED_DATE_TIME_FMT nl_langinfo (D_T_FMT)
197 #define PREFERRED_DATE_FMT nl_langinfo (D_FMT)
198 #define PREFERRED_TIME_FMT nl_langinfo (T_FMT)
199 #define PREFERRED_12HR_TIME_FMT nl_langinfo (T_FMT_AMPM)
200
201 static const gint weekday_item[2][7] =
202 {
203   { ABDAY_2, ABDAY_3, ABDAY_4, ABDAY_5, ABDAY_6, ABDAY_7, ABDAY_1 },
204   { DAY_2, DAY_3, DAY_4, DAY_5, DAY_6, DAY_7, DAY_1 }
205 };
206
207 static const gint month_item[2][12] =
208 {
209   { ABMON_1, ABMON_2, ABMON_3, ABMON_4, ABMON_5, ABMON_6, ABMON_7, ABMON_8, ABMON_9, ABMON_10, ABMON_11, ABMON_12 },
210   { MON_1, MON_2, MON_3, MON_4, MON_5, MON_6, MON_7, MON_8, MON_9, MON_10, MON_11, MON_12 },
211 };
212
213 #define WEEKDAY_ABBR(d) nl_langinfo (weekday_item[0][g_date_time_get_day_of_week (d) - 1])
214 #define WEEKDAY_ABBR_IS_LOCALE TRUE
215 #define WEEKDAY_FULL(d) nl_langinfo (weekday_item[1][g_date_time_get_day_of_week (d) - 1])
216 #define WEEKDAY_FULL_IS_LOCALE TRUE
217 #define MONTH_ABBR(d) nl_langinfo (month_item[0][g_date_time_get_month (d) - 1])
218 #define MONTH_ABBR_IS_LOCALE TRUE
219 #define MONTH_FULL(d) nl_langinfo (month_item[1][g_date_time_get_month (d) - 1])
220 #define MONTH_FULL_IS_LOCALE TRUE
221
222 #else
223
224 #define GET_AMPM(d)          (get_fallback_ampm (g_date_time_get_hour (d)))
225 #define GET_AMPM_IS_LOCALE   FALSE
226
227 /* Translators: this is the preferred format for expressing the date and the time */
228 #define PREFERRED_DATE_TIME_FMT C_("GDateTime", "%a %b %e %H:%M:%S %Y")
229
230 /* Translators: this is the preferred format for expressing the date */
231 #define PREFERRED_DATE_FMT C_("GDateTime", "%m/%d/%y")
232
233 /* Translators: this is the preferred format for expressing the time */
234 #define PREFERRED_TIME_FMT C_("GDateTime", "%H:%M:%S")
235
236 /* Translators: this is the preferred format for expressing 12 hour time */
237 #define PREFERRED_12HR_TIME_FMT C_("GDateTime", "%I:%M:%S %p")
238
239 #define WEEKDAY_ABBR(d)       (get_weekday_name_abbr (g_date_time_get_day_of_week (d)))
240 #define WEEKDAY_ABBR_IS_LOCALE FALSE
241 #define WEEKDAY_FULL(d)       (get_weekday_name (g_date_time_get_day_of_week (d)))
242 #define WEEKDAY_FULL_IS_LOCALE FALSE
243 /* We don't yet know if nl_langinfo (MON_n) returns standalone or complete-date
244  * format forms but if nl_langinfo (ALTMON_n) is not supported then we will
245  * have to use MONTH_FULL as standalone.  The same if nl_langinfo () does not
246  * exist at all.  MONTH_ABBR is similar: if nl_langinfo (_NL_ABALTMON_n) is not
247  * supported then we will use MONTH_ABBR as standalone.
248  */
249 #define MONTH_ABBR(d)         (get_month_name_abbr_standalone (g_date_time_get_month (d)))
250 #define MONTH_ABBR_IS_LOCALE  FALSE
251 #define MONTH_FULL(d)         (get_month_name_standalone (g_date_time_get_month (d)))
252 #define MONTH_FULL_IS_LOCALE  FALSE
253
254 static const gchar *
255 get_month_name_standalone (gint month)
256 {
257   switch (month)
258     {
259     case 1:
260       /* Translators: Some languages (Baltic, Slavic, Greek, and some more)
261        * need different grammatical forms of month names depending on whether
262        * they are standalone or in a complete date context, with the day
263        * number.  Some other languages may prefer starting with uppercase when
264        * they are standalone and with lowercase when they are in a complete
265        * date context.  Here are full month names in a form appropriate when
266        * they are used standalone.  If your system is Linux with the glibc
267        * version 2.27 (released Feb 1, 2018) or newer or if it is from the BSD
268        * family (which includes OS X) then you can refer to the date command
269        * line utility and see what the command `date +%OB' produces.  Also in
270        * the latest Linux the command `locale alt_mon' in your native locale
271        * produces a complete list of month names almost ready to copy and
272        * paste here.  Note that in most of the languages (western European,
273        * non-European) there is no difference between the standalone and
274        * complete date form.
275        */
276       return C_("full month name", "January");
277     case 2:
278       return C_("full month name", "February");
279     case 3:
280       return C_("full month name", "March");
281     case 4:
282       return C_("full month name", "April");
283     case 5:
284       return C_("full month name", "May");
285     case 6:
286       return C_("full month name", "June");
287     case 7:
288       return C_("full month name", "July");
289     case 8:
290       return C_("full month name", "August");
291     case 9:
292       return C_("full month name", "September");
293     case 10:
294       return C_("full month name", "October");
295     case 11:
296       return C_("full month name", "November");
297     case 12:
298       return C_("full month name", "December");
299
300     default:
301       g_warning ("Invalid month number %d", month);
302     }
303
304   return NULL;
305 }
306
307 static const gchar *
308 get_month_name_abbr_standalone (gint month)
309 {
310   switch (month)
311     {
312     case 1:
313       /* Translators: Some languages need different grammatical forms of
314        * month names depending on whether they are standalone or in a complete
315        * date context, with the day number.  Some may prefer starting with
316        * uppercase when they are standalone and with lowercase when they are
317        * in a full date context.  However, as these names are abbreviated
318        * the grammatical difference is visible probably only in Belarusian
319        * and Russian.  In other languages there is no difference between
320        * the standalone and complete date form when they are abbreviated.
321        * If your system is Linux with the glibc version 2.27 (released
322        * Feb 1, 2018) or newer then you can refer to the date command line
323        * utility and see what the command `date +%Ob' produces.  Also in
324        * the latest Linux the command `locale ab_alt_mon' in your native
325        * locale produces a complete list of month names almost ready to copy
326        * and paste here.  Note that this feature is not yet supported by any
327        * other platform.  Here are abbreviated month names in a form
328        * appropriate when they are used standalone.
329        */
330       return C_("abbreviated month name", "Jan");
331     case 2:
332       return C_("abbreviated month name", "Feb");
333     case 3:
334       return C_("abbreviated month name", "Mar");
335     case 4:
336       return C_("abbreviated month name", "Apr");
337     case 5:
338       return C_("abbreviated month name", "May");
339     case 6:
340       return C_("abbreviated month name", "Jun");
341     case 7:
342       return C_("abbreviated month name", "Jul");
343     case 8:
344       return C_("abbreviated month name", "Aug");
345     case 9:
346       return C_("abbreviated month name", "Sep");
347     case 10:
348       return C_("abbreviated month name", "Oct");
349     case 11:
350       return C_("abbreviated month name", "Nov");
351     case 12:
352       return C_("abbreviated month name", "Dec");
353
354     default:
355       g_warning ("Invalid month number %d", month);
356     }
357
358   return NULL;
359 }
360
361 static const gchar *
362 get_weekday_name (gint day)
363 {
364   switch (day)
365     {
366     case 1:
367       return C_("full weekday name", "Monday");
368     case 2:
369       return C_("full weekday name", "Tuesday");
370     case 3:
371       return C_("full weekday name", "Wednesday");
372     case 4:
373       return C_("full weekday name", "Thursday");
374     case 5:
375       return C_("full weekday name", "Friday");
376     case 6:
377       return C_("full weekday name", "Saturday");
378     case 7:
379       return C_("full weekday name", "Sunday");
380
381     default:
382       g_warning ("Invalid week day number %d", day);
383     }
384
385   return NULL;
386 }
387
388 static const gchar *
389 get_weekday_name_abbr (gint day)
390 {
391   switch (day)
392     {
393     case 1:
394       return C_("abbreviated weekday name", "Mon");
395     case 2:
396       return C_("abbreviated weekday name", "Tue");
397     case 3:
398       return C_("abbreviated weekday name", "Wed");
399     case 4:
400       return C_("abbreviated weekday name", "Thu");
401     case 5:
402       return C_("abbreviated weekday name", "Fri");
403     case 6:
404       return C_("abbreviated weekday name", "Sat");
405     case 7:
406       return C_("abbreviated weekday name", "Sun");
407
408     default:
409       g_warning ("Invalid week day number %d", day);
410     }
411
412   return NULL;
413 }
414
415 #endif  /* HAVE_LANGINFO_TIME */
416
417 #ifdef HAVE_LANGINFO_ALTMON
418
419 /* If nl_langinfo () supports ALTMON_n then MON_n returns full date format
420  * forms and ALTMON_n returns standalone forms.
421  */
422
423 #define MONTH_FULL_WITH_DAY(d) MONTH_FULL(d)
424 #define MONTH_FULL_WITH_DAY_IS_LOCALE MONTH_FULL_IS_LOCALE
425
426 static const gint alt_month_item[12] =
427 {
428   ALTMON_1, ALTMON_2, ALTMON_3, ALTMON_4, ALTMON_5, ALTMON_6,
429   ALTMON_7, ALTMON_8, ALTMON_9, ALTMON_10, ALTMON_11, ALTMON_12
430 };
431
432 #define MONTH_FULL_STANDALONE(d) nl_langinfo (alt_month_item[g_date_time_get_month (d) - 1])
433 #define MONTH_FULL_STANDALONE_IS_LOCALE TRUE
434
435 #else
436
437 /* If nl_langinfo () does not support ALTMON_n then either MON_n returns
438  * standalone forms or nl_langinfo (MON_n) does not work so we have defined
439  * it as standalone form.
440  */
441
442 #define MONTH_FULL_STANDALONE(d) MONTH_FULL(d)
443 #define MONTH_FULL_STANDALONE_IS_LOCALE MONTH_FULL_IS_LOCALE
444 #define MONTH_FULL_WITH_DAY(d) (get_month_name_with_day (g_date_time_get_month (d)))
445 #define MONTH_FULL_WITH_DAY_IS_LOCALE FALSE
446
447 static const gchar *
448 get_month_name_with_day (gint month)
449 {
450   switch (month)
451     {
452     case 1:
453       /* Translators: Some languages need different grammatical forms of
454        * month names depending on whether they are standalone or in a full
455        * date context, with the day number.  Some may prefer starting with
456        * uppercase when they are standalone and with lowercase when they are
457        * in a full date context.  Here are full month names in a form
458        * appropriate when they are used in a full date context, with the
459        * day number.  If your system is Linux with the glibc version 2.27
460        * (released Feb 1, 2018) or newer or if it is from the BSD family
461        * (which includes OS X) then you can refer to the date command line
462        * utility and see what the command `date +%B' produces.  Also in
463        * the latest Linux the command `locale mon' in your native locale
464        * produces a complete list of month names almost ready to copy and
465        * paste here.  In older Linux systems due to a bug the result is
466        * incorrect in some languages.  Note that in most of the languages
467        * (western European, non-European) there is no difference between the
468        * standalone and complete date form.
469        */
470       return C_("full month name with day", "January");
471     case 2:
472       return C_("full month name with day", "February");
473     case 3:
474       return C_("full month name with day", "March");
475     case 4:
476       return C_("full month name with day", "April");
477     case 5:
478       return C_("full month name with day", "May");
479     case 6:
480       return C_("full month name with day", "June");
481     case 7:
482       return C_("full month name with day", "July");
483     case 8:
484       return C_("full month name with day", "August");
485     case 9:
486       return C_("full month name with day", "September");
487     case 10:
488       return C_("full month name with day", "October");
489     case 11:
490       return C_("full month name with day", "November");
491     case 12:
492       return C_("full month name with day", "December");
493
494     default:
495       g_warning ("Invalid month number %d", month);
496     }
497
498   return NULL;
499 }
500
501 #endif  /* HAVE_LANGINFO_ALTMON */
502
503 #ifdef HAVE_LANGINFO_ABALTMON
504
505 /* If nl_langinfo () supports _NL_ABALTMON_n then ABMON_n returns full
506  * date format forms and _NL_ABALTMON_n returns standalone forms.
507  */
508
509 #define MONTH_ABBR_WITH_DAY(d) MONTH_ABBR(d)
510 #define MONTH_ABBR_WITH_DAY_IS_LOCALE MONTH_ABBR_IS_LOCALE
511
512 static const gint ab_alt_month_item[12] =
513 {
514   _NL_ABALTMON_1, _NL_ABALTMON_2, _NL_ABALTMON_3, _NL_ABALTMON_4,
515   _NL_ABALTMON_5, _NL_ABALTMON_6, _NL_ABALTMON_7, _NL_ABALTMON_8,
516   _NL_ABALTMON_9, _NL_ABALTMON_10, _NL_ABALTMON_11, _NL_ABALTMON_12
517 };
518
519 #define MONTH_ABBR_STANDALONE(d) nl_langinfo (ab_alt_month_item[g_date_time_get_month (d) - 1])
520 #define MONTH_ABBR_STANDALONE_IS_LOCALE TRUE
521
522 #else
523
524 /* If nl_langinfo () does not support _NL_ABALTMON_n then either ABMON_n
525  * returns standalone forms or nl_langinfo (ABMON_n) does not work so we
526  * have defined it as standalone form. Now it's time to swap.
527  */
528
529 #define MONTH_ABBR_STANDALONE(d) MONTH_ABBR(d)
530 #define MONTH_ABBR_STANDALONE_IS_LOCALE MONTH_ABBR_IS_LOCALE
531 #define MONTH_ABBR_WITH_DAY(d) (get_month_name_abbr_with_day (g_date_time_get_month (d)))
532 #define MONTH_ABBR_WITH_DAY_IS_LOCALE FALSE
533
534 static const gchar *
535 get_month_name_abbr_with_day (gint month)
536 {
537   switch (month)
538     {
539     case 1:
540       /* Translators: Some languages need different grammatical forms of
541        * month names depending on whether they are standalone or in a full
542        * date context, with the day number.  Some may prefer starting with
543        * uppercase when they are standalone and with lowercase when they are
544        * in a full date context.  Here are abbreviated month names in a form
545        * appropriate when they are used in a full date context, with the
546        * day number.  However, as these names are abbreviated the grammatical
547        * difference is visible probably only in Belarusian and Russian.
548        * In other languages there is no difference between the standalone
549        * and complete date form when they are abbreviated.  If your system
550        * is Linux with the glibc version 2.27 (released Feb 1, 2018) or newer
551        * then you can refer to the date command line utility and see what the
552        * command `date +%b' produces.  Also in the latest Linux the command
553        * `locale abmon' in your native locale produces a complete list of
554        * month names almost ready to copy and paste here.  In other systems
555        * due to a bug the result is incorrect in some languages.
556        */
557       return C_("abbreviated month name with day", "Jan");
558     case 2:
559       return C_("abbreviated month name with day", "Feb");
560     case 3:
561       return C_("abbreviated month name with day", "Mar");
562     case 4:
563       return C_("abbreviated month name with day", "Apr");
564     case 5:
565       return C_("abbreviated month name with day", "May");
566     case 6:
567       return C_("abbreviated month name with day", "Jun");
568     case 7:
569       return C_("abbreviated month name with day", "Jul");
570     case 8:
571       return C_("abbreviated month name with day", "Aug");
572     case 9:
573       return C_("abbreviated month name with day", "Sep");
574     case 10:
575       return C_("abbreviated month name with day", "Oct");
576     case 11:
577       return C_("abbreviated month name with day", "Nov");
578     case 12:
579       return C_("abbreviated month name with day", "Dec");
580
581     default:
582       g_warning ("Invalid month number %d", month);
583     }
584
585   return NULL;
586 }
587
588 #endif  /* HAVE_LANGINFO_ABALTMON */
589
590 /* Format AM/PM indicator if the locale does not have a localized version. */
591 static const gchar *
592 get_fallback_ampm (gint hour)
593 {
594   if (hour < 12)
595     /* Translators: 'before midday' indicator */
596     return C_("GDateTime", "AM");
597   else
598     /* Translators: 'after midday' indicator */
599     return C_("GDateTime", "PM");
600 }
601
602 static inline gint
603 ymd_to_days (gint year,
604              gint month,
605              gint day)
606 {
607   gint64 days;
608
609   days = ((gint64) year - 1) * 365 + ((year - 1) / 4) - ((year - 1) / 100)
610       + ((year - 1) / 400);
611
612   days += days_in_year[0][month - 1];
613   if (GREGORIAN_LEAP (year) && month > 2)
614     day++;
615
616   days += day;
617
618   return days;
619 }
620
621 static void
622 g_date_time_get_week_number (GDateTime *datetime,
623                              gint      *week_number,
624                              gint      *day_of_week,
625                              gint      *day_of_year)
626 {
627   gint a, b, c, d, e, f, g, n, s, month = -1, day = -1, year = -1;
628
629   g_date_time_get_ymd (datetime, &year, &month, &day);
630
631   if (month <= 2)
632     {
633       a = g_date_time_get_year (datetime) - 1;
634       b = (a / 4) - (a / 100) + (a / 400);
635       c = ((a - 1) / 4) - ((a - 1) / 100) + ((a - 1) / 400);
636       s = b - c;
637       e = 0;
638       f = day - 1 + (31 * (month - 1));
639     }
640   else
641     {
642       a = year;
643       b = (a / 4) - (a / 100) + (a / 400);
644       c = ((a - 1) / 4) - ((a - 1) / 100) + ((a - 1) / 400);
645       s = b - c;
646       e = s + 1;
647       f = day + (((153 * (month - 3)) + 2) / 5) + 58 + s;
648     }
649
650   g = (a + b) % 7;
651   d = (f + g - e) % 7;
652   n = f + 3 - d;
653
654   if (week_number)
655     {
656       if (n < 0)
657         *week_number = 53 - ((g - s) / 5);
658       else if (n > 364 + s)
659         *week_number = 1;
660       else
661         *week_number = (n / 7) + 1;
662     }
663
664   if (day_of_week)
665     *day_of_week = d + 1;
666
667   if (day_of_year)
668     *day_of_year = f + 1;
669 }
670
671 /* Lifecycle {{{1 */
672
673 static GDateTime *
674 g_date_time_alloc (GTimeZone *tz)
675 {
676   GDateTime *datetime;
677
678   datetime = g_slice_new0 (GDateTime);
679   datetime->tz = g_time_zone_ref (tz);
680   datetime->ref_count = 1;
681
682   return datetime;
683 }
684
685 /**
686  * g_date_time_ref:
687  * @datetime: a #GDateTime
688  *
689  * Atomically increments the reference count of @datetime by one.
690  *
691  * Returns: the #GDateTime with the reference count increased
692  *
693  * Since: 2.26
694  */
695 GDateTime *
696 g_date_time_ref (GDateTime *datetime)
697 {
698   g_return_val_if_fail (datetime != NULL, NULL);
699   g_return_val_if_fail (datetime->ref_count > 0, NULL);
700
701   g_atomic_int_inc (&datetime->ref_count);
702
703   return datetime;
704 }
705
706 /**
707  * g_date_time_unref:
708  * @datetime: a #GDateTime
709  *
710  * Atomically decrements the reference count of @datetime by one.
711  *
712  * When the reference count reaches zero, the resources allocated by
713  * @datetime are freed
714  *
715  * Since: 2.26
716  */
717 void
718 g_date_time_unref (GDateTime *datetime)
719 {
720   g_return_if_fail (datetime != NULL);
721   g_return_if_fail (datetime->ref_count > 0);
722
723   if (g_atomic_int_dec_and_test (&datetime->ref_count))
724     {
725       g_time_zone_unref (datetime->tz);
726       g_slice_free (GDateTime, datetime);
727     }
728 }
729
730 /* Internal state transformers {{{1 */
731 /*< internal >
732  * g_date_time_to_instant:
733  * @datetime: a #GDateTime
734  *
735  * Convert a @datetime into an instant.
736  *
737  * An instant is a number that uniquely describes a particular
738  * microsecond in time, taking time zone considerations into account.
739  * (ie: "03:00 -0400" is the same instant as "02:00 -0500").
740  *
741  * An instant is always positive but we use a signed return value to
742  * avoid troubles with C.
743  */
744 static gint64
745 g_date_time_to_instant (GDateTime *datetime)
746 {
747   gint64 offset;
748
749   offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
750   offset *= USEC_PER_SECOND;
751
752   return datetime->days * USEC_PER_DAY + datetime->usec - offset;
753 }
754
755 /*< internal >
756  * g_date_time_from_instant:
757  * @tz: a #GTimeZone
758  * @instant: an instant in time
759  *
760  * Creates a #GDateTime from a time zone and an instant.
761  *
762  * This might fail if the time ends up being out of range.
763  */
764 static GDateTime *
765 g_date_time_from_instant (GTimeZone *tz,
766                           gint64     instant)
767 {
768   GDateTime *datetime;
769   gint64 offset;
770
771   if (instant < 0 || instant > G_GINT64_CONSTANT (1000000000000000000))
772     return NULL;
773
774   datetime = g_date_time_alloc (tz);
775   datetime->interval = g_time_zone_find_interval (tz,
776                                                   G_TIME_TYPE_UNIVERSAL,
777                                                   INSTANT_TO_UNIX (instant));
778   offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
779   offset *= USEC_PER_SECOND;
780
781   instant += offset;
782
783   datetime->days = instant / USEC_PER_DAY;
784   datetime->usec = instant % USEC_PER_DAY;
785
786   if (datetime->days < 1 || 3652059 < datetime->days)
787     {
788       g_date_time_unref (datetime);
789       datetime = NULL;
790     }
791
792   return datetime;
793 }
794
795
796 /*< internal >
797  * g_date_time_deal_with_date_change:
798  * @datetime: a #GDateTime
799  *
800  * This function should be called whenever the date changes by adding
801  * days, months or years.  It does three things.
802  *
803  * First, we ensure that the date falls between 0001-01-01 and
804  * 9999-12-31 and return %FALSE if it does not.
805  *
806  * Next we update the ->interval field.
807  *
808  * Finally, we ensure that the resulting date and time pair exists (by
809  * ensuring that our time zone has an interval containing it) and
810  * adjusting as required.  For example, if we have the time 02:30:00 on
811  * March 13 2010 in Toronto and we add 1 day to it, we would end up with
812  * 2:30am on March 14th, which doesn't exist.  In that case, we bump the
813  * time up to 3:00am.
814  */
815 static gboolean
816 g_date_time_deal_with_date_change (GDateTime *datetime)
817 {
818   GTimeType was_dst;
819   gint64 full_time;
820   gint64 usec;
821
822   if (datetime->days < 1 || datetime->days > 3652059)
823     return FALSE;
824
825   was_dst = g_time_zone_is_dst (datetime->tz, datetime->interval);
826
827   full_time = datetime->days * USEC_PER_DAY + datetime->usec;
828
829
830   usec = full_time % USEC_PER_SECOND;
831   full_time /= USEC_PER_SECOND;
832   full_time -= UNIX_EPOCH_START * SEC_PER_DAY;
833
834   datetime->interval = g_time_zone_adjust_time (datetime->tz,
835                                                 was_dst,
836                                                 &full_time);
837   full_time += UNIX_EPOCH_START * SEC_PER_DAY;
838   full_time *= USEC_PER_SECOND;
839   full_time += usec;
840
841   datetime->days = full_time / USEC_PER_DAY;
842   datetime->usec = full_time % USEC_PER_DAY;
843
844   /* maybe daylight time caused us to shift to a different day,
845    * but it definitely didn't push us into a different year */
846   return TRUE;
847 }
848
849 static GDateTime *
850 g_date_time_replace_days (GDateTime *datetime,
851                           gint       days)
852 {
853   GDateTime *new;
854
855   new = g_date_time_alloc (datetime->tz);
856   new->interval = datetime->interval;
857   new->usec = datetime->usec;
858   new->days = days;
859
860   if (!g_date_time_deal_with_date_change (new))
861     {
862       g_date_time_unref (new);
863       new = NULL;
864     }
865
866   return new;
867 }
868
869 /* now/unix/timeval Constructors {{{1 */
870
871 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
872 /*< internal >
873  * g_date_time_new_from_timeval:
874  * @tz: a #GTimeZone
875  * @tv: a #GTimeVal
876  *
877  * Creates a #GDateTime corresponding to the given #GTimeVal @tv in the
878  * given time zone @tz.
879  *
880  * The time contained in a #GTimeVal is always stored in the form of
881  * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the
882  * given time zone.
883  *
884  * This call can fail (returning %NULL) if @tv represents a time outside
885  * of the supported range of #GDateTime.
886  *
887  * You should release the return value by calling g_date_time_unref()
888  * when you are done with it.
889  *
890  * Returns: a new #GDateTime, or %NULL
891  *
892  * Since: 2.26
893  **/
894 static GDateTime *
895 g_date_time_new_from_timeval (GTimeZone      *tz,
896                               const GTimeVal *tv)
897 {
898   gint64 tv_sec = tv->tv_sec;
899
900   if (tv_sec > G_MAXINT64 - 1 || !UNIX_TO_INSTANT_IS_VALID (tv_sec + 1))
901     return NULL;
902
903   return g_date_time_from_instant (tz, tv->tv_usec +
904                                    UNIX_TO_INSTANT (tv->tv_sec));
905 }
906 G_GNUC_END_IGNORE_DEPRECATIONS
907
908 /*< internal >
909  * g_date_time_new_from_unix:
910  * @tz: a #GTimeZone
911  * @usecs: the Unix time, in microseconds since the epoch
912  *
913  * Creates a #GDateTime corresponding to the given Unix time @t_us in the
914  * given time zone @tz.
915  *
916  * Unix time is the number of seconds that have elapsed since 1970-01-01
917  * 00:00:00 UTC, regardless of the time zone given.
918  *
919  * This call can fail (returning %NULL) if @t represents a time outside
920  * of the supported range of #GDateTime.
921  *
922  * You should release the return value by calling g_date_time_unref()
923  * when you are done with it.
924  *
925  * Returns: a new #GDateTime, or %NULL
926  *
927  * Since: 2.26
928  **/
929 static GDateTime *
930 g_date_time_new_from_unix (GTimeZone *tz,
931                            gint64     usecs)
932 {
933   if (!UNIX_USECS_TO_INSTANT_IS_VALID (usecs))
934     return NULL;
935
936   return g_date_time_from_instant (tz, UNIX_USECS_TO_INSTANT (usecs));
937 }
938
939 /**
940  * g_date_time_new_now: (constructor)
941  * @tz: a #GTimeZone
942  *
943  * Creates a #GDateTime corresponding to this exact instant in the given
944  * time zone @tz.  The time is as accurate as the system allows, to a
945  * maximum accuracy of 1 microsecond.
946  *
947  * This function will always succeed unless GLib is still being used after the
948  * year 9999.
949  *
950  * You should release the return value by calling g_date_time_unref()
951  * when you are done with it.
952  *
953  * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL
954  *
955  * Since: 2.26
956  **/
957 GDateTime *
958 g_date_time_new_now (GTimeZone *tz)
959 {
960   gint64 now_us;
961
962   g_return_val_if_fail (tz != NULL, NULL);
963
964   now_us = g_get_real_time ();
965
966   return g_date_time_new_from_unix (tz, now_us);
967 }
968
969 /**
970  * g_date_time_new_now_local: (constructor)
971  *
972  * Creates a #GDateTime corresponding to this exact instant in the local
973  * time zone.
974  *
975  * This is equivalent to calling g_date_time_new_now() with the time
976  * zone returned by g_time_zone_new_local().
977  *
978  * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL
979  *
980  * Since: 2.26
981  **/
982 GDateTime *
983 g_date_time_new_now_local (void)
984 {
985   GDateTime *datetime;
986   GTimeZone *local;
987
988   local = g_time_zone_new_local ();
989   datetime = g_date_time_new_now (local);
990   g_time_zone_unref (local);
991
992   return datetime;
993 }
994
995 /**
996  * g_date_time_new_now_utc: (constructor)
997  *
998  * Creates a #GDateTime corresponding to this exact instant in UTC.
999  *
1000  * This is equivalent to calling g_date_time_new_now() with the time
1001  * zone returned by g_time_zone_new_utc().
1002  *
1003  * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL
1004  *
1005  * Since: 2.26
1006  **/
1007 GDateTime *
1008 g_date_time_new_now_utc (void)
1009 {
1010   GDateTime *datetime;
1011   GTimeZone *utc;
1012
1013   utc = g_time_zone_new_utc ();
1014   datetime = g_date_time_new_now (utc);
1015   g_time_zone_unref (utc);
1016
1017   return datetime;
1018 }
1019
1020 /**
1021  * g_date_time_new_from_unix_local: (constructor)
1022  * @t: the Unix time
1023  *
1024  * Creates a #GDateTime corresponding to the given Unix time @t in the
1025  * local time zone.
1026  *
1027  * Unix time is the number of seconds that have elapsed since 1970-01-01
1028  * 00:00:00 UTC, regardless of the local time offset.
1029  *
1030  * This call can fail (returning %NULL) if @t represents a time outside
1031  * of the supported range of #GDateTime.
1032  *
1033  * You should release the return value by calling g_date_time_unref()
1034  * when you are done with it.
1035  *
1036  * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL
1037  *
1038  * Since: 2.26
1039  **/
1040 GDateTime *
1041 g_date_time_new_from_unix_local (gint64 t)
1042 {
1043   GDateTime *datetime;
1044   GTimeZone *local;
1045
1046   if (t > G_MAXINT64 / USEC_PER_SECOND ||
1047       t < G_MININT64 / USEC_PER_SECOND)
1048     return NULL;
1049
1050   local = g_time_zone_new_local ();
1051   datetime = g_date_time_new_from_unix (local, t * USEC_PER_SECOND);
1052   g_time_zone_unref (local);
1053
1054   return datetime;
1055 }
1056
1057 /**
1058  * g_date_time_new_from_unix_utc: (constructor)
1059  * @t: the Unix time
1060  *
1061  * Creates a #GDateTime corresponding to the given Unix time @t in UTC.
1062  *
1063  * Unix time is the number of seconds that have elapsed since 1970-01-01
1064  * 00:00:00 UTC.
1065  *
1066  * This call can fail (returning %NULL) if @t represents a time outside
1067  * of the supported range of #GDateTime.
1068  *
1069  * You should release the return value by calling g_date_time_unref()
1070  * when you are done with it.
1071  *
1072  * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL
1073  *
1074  * Since: 2.26
1075  **/
1076 GDateTime *
1077 g_date_time_new_from_unix_utc (gint64 t)
1078 {
1079   GDateTime *datetime;
1080   GTimeZone *utc;
1081
1082   if (t > G_MAXINT64 / USEC_PER_SECOND ||
1083       t < G_MININT64 / USEC_PER_SECOND)
1084     return NULL;
1085
1086   utc = g_time_zone_new_utc ();
1087   datetime = g_date_time_new_from_unix (utc, t * USEC_PER_SECOND);
1088   g_time_zone_unref (utc);
1089
1090   return datetime;
1091 }
1092
1093 /**
1094  * g_date_time_new_from_timeval_local: (constructor)
1095  * @tv: a #GTimeVal
1096  *
1097  * Creates a #GDateTime corresponding to the given #GTimeVal @tv in the
1098  * local time zone.
1099  *
1100  * The time contained in a #GTimeVal is always stored in the form of
1101  * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the
1102  * local time offset.
1103  *
1104  * This call can fail (returning %NULL) if @tv represents a time outside
1105  * of the supported range of #GDateTime.
1106  *
1107  * You should release the return value by calling g_date_time_unref()
1108  * when you are done with it.
1109  *
1110  * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL
1111  *
1112  * Since: 2.26
1113  * Deprecated: 2.62: #GTimeVal is not year-2038-safe. Use
1114  *    g_date_time_new_from_unix_local() instead.
1115  **/
1116 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1117 GDateTime *
1118 g_date_time_new_from_timeval_local (const GTimeVal *tv)
1119 {
1120   GDateTime *datetime;
1121   GTimeZone *local;
1122
1123   local = g_time_zone_new_local ();
1124   datetime = g_date_time_new_from_timeval (local, tv);
1125   g_time_zone_unref (local);
1126
1127   return datetime;
1128 }
1129 G_GNUC_END_IGNORE_DEPRECATIONS
1130
1131 /**
1132  * g_date_time_new_from_timeval_utc: (constructor)
1133  * @tv: a #GTimeVal
1134  *
1135  * Creates a #GDateTime corresponding to the given #GTimeVal @tv in UTC.
1136  *
1137  * The time contained in a #GTimeVal is always stored in the form of
1138  * seconds elapsed since 1970-01-01 00:00:00 UTC.
1139  *
1140  * This call can fail (returning %NULL) if @tv represents a time outside
1141  * of the supported range of #GDateTime.
1142  *
1143  * You should release the return value by calling g_date_time_unref()
1144  * when you are done with it.
1145  *
1146  * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL
1147  *
1148  * Since: 2.26
1149  * Deprecated: 2.62: #GTimeVal is not year-2038-safe. Use
1150  *    g_date_time_new_from_unix_utc() instead.
1151  **/
1152 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1153 GDateTime *
1154 g_date_time_new_from_timeval_utc (const GTimeVal *tv)
1155 {
1156   GDateTime *datetime;
1157   GTimeZone *utc;
1158
1159   utc = g_time_zone_new_utc ();
1160   datetime = g_date_time_new_from_timeval (utc, tv);
1161   g_time_zone_unref (utc);
1162
1163   return datetime;
1164 }
1165 G_GNUC_END_IGNORE_DEPRECATIONS
1166
1167 /* Parse integers in the form d (week days), dd (hours etc), ddd (ordinal days) or dddd (years) */
1168 static gboolean
1169 get_iso8601_int (const gchar *text, gsize length, gint *value)
1170 {
1171   gsize i;
1172   guint v = 0;
1173
1174   if (length < 1 || length > 4)
1175     return FALSE;
1176
1177   for (i = 0; i < length; i++)
1178     {
1179       const gchar c = text[i];
1180       if (c < '0' || c > '9')
1181         return FALSE;
1182       v = v * 10 + (c - '0');
1183     }
1184
1185   *value = v;
1186   return TRUE;
1187 }
1188
1189 /* Parse seconds in the form ss or ss.sss (variable length decimal) */
1190 static gboolean
1191 get_iso8601_seconds (const gchar *text, gsize length, gdouble *value)
1192 {
1193   gsize i;
1194   guint64 divisor = 1, v = 0;
1195
1196   if (length < 2)
1197     return FALSE;
1198
1199   for (i = 0; i < 2; i++)
1200     {
1201       const gchar c = text[i];
1202       if (c < '0' || c > '9')
1203         return FALSE;
1204       v = v * 10 + (c - '0');
1205     }
1206
1207   if (length > 2 && !(text[i] == '.' || text[i] == ','))
1208     return FALSE;
1209
1210   /* Ignore leap seconds, see g_date_time_new_from_iso8601() */
1211   if (v >= 60.0 && v <= 61.0)
1212     v = 59.0;
1213
1214   i++;
1215   if (i == length)
1216     return FALSE;
1217
1218   for (; i < length; i++)
1219     {
1220       const gchar c = text[i];
1221       if (c < '0' || c > '9' ||
1222           v > (G_MAXUINT64 - (c - '0')) / 10 ||
1223           divisor > G_MAXUINT64 / 10)
1224         return FALSE;
1225       v = v * 10 + (c - '0');
1226       divisor *= 10;
1227     }
1228
1229   *value = (gdouble) v / divisor;
1230   return TRUE;
1231 }
1232
1233 static GDateTime *
1234 g_date_time_new_ordinal (GTimeZone *tz, gint year, gint ordinal_day, gint hour, gint minute, gdouble seconds)
1235 {
1236   GDateTime *dt;
1237
1238   if (ordinal_day < 1 || ordinal_day > (GREGORIAN_LEAP (year) ? 366 : 365))
1239     return NULL;
1240
1241   dt = g_date_time_new (tz, year, 1, 1, hour, minute, seconds);
1242   if (dt == NULL)
1243     return NULL;
1244   dt->days += ordinal_day - 1;
1245
1246   return dt;
1247 }
1248
1249 static GDateTime *
1250 g_date_time_new_week (GTimeZone *tz, gint year, gint week, gint week_day, gint hour, gint minute, gdouble seconds)
1251 {
1252   gint64 p;
1253   gint max_week, jan4_week_day, ordinal_day;
1254   GDateTime *dt;
1255
1256   p = (year * 365 + (year / 4) - (year / 100) + (year / 400)) % 7;
1257   max_week = p == 4 ? 53 : 52;
1258
1259   if (week < 1 || week > max_week || week_day < 1 || week_day > 7)
1260     return NULL;
1261
1262   dt = g_date_time_new (tz, year, 1, 4, 0, 0, 0);
1263   if (dt == NULL)
1264     return NULL;
1265   g_date_time_get_week_number (dt, NULL, &jan4_week_day, NULL);
1266   g_date_time_unref (dt);
1267
1268   ordinal_day = (week * 7) + week_day - (jan4_week_day + 3);
1269   if (ordinal_day < 0)
1270     {
1271       year--;
1272       ordinal_day += GREGORIAN_LEAP (year) ? 366 : 365;
1273     }
1274   else if (ordinal_day > (GREGORIAN_LEAP (year) ? 366 : 365))
1275     {
1276       ordinal_day -= (GREGORIAN_LEAP (year) ? 366 : 365);
1277       year++;
1278     }
1279
1280   return g_date_time_new_ordinal (tz, year, ordinal_day, hour, minute, seconds);
1281 }
1282
1283 static GDateTime *
1284 parse_iso8601_date (const gchar *text, gsize length,
1285                     gint hour, gint minute, gdouble seconds, GTimeZone *tz)
1286 {
1287   /* YYYY-MM-DD */
1288   if (length == 10 && text[4] == '-' && text[7] == '-')
1289     {
1290       int year, month, day;
1291       if (!get_iso8601_int (text, 4, &year) ||
1292           !get_iso8601_int (text + 5, 2, &month) ||
1293           !get_iso8601_int (text + 8, 2, &day))
1294         return NULL;
1295       return g_date_time_new (tz, year, month, day, hour, minute, seconds);
1296     }
1297   /* YYYY-DDD */
1298   else if (length == 8 && text[4] == '-')
1299     {
1300       gint year, ordinal_day;
1301       if (!get_iso8601_int (text, 4, &year) ||
1302           !get_iso8601_int (text + 5, 3, &ordinal_day))
1303         return NULL;
1304       return g_date_time_new_ordinal (tz, year, ordinal_day, hour, minute, seconds);
1305     }
1306   /* YYYY-Www-D */
1307   else if (length == 10 && text[4] == '-' && text[5] == 'W' && text[8] == '-')
1308     {
1309       gint year, week, week_day;
1310       if (!get_iso8601_int (text, 4, &year) ||
1311           !get_iso8601_int (text + 6, 2, &week) ||
1312           !get_iso8601_int (text + 9, 1, &week_day))
1313         return NULL;
1314       return g_date_time_new_week (tz, year, week, week_day, hour, minute, seconds);
1315     }
1316   /* YYYYWwwD */
1317   else if (length == 8 && text[4] == 'W')
1318     {
1319       gint year, week, week_day;
1320       if (!get_iso8601_int (text, 4, &year) ||
1321           !get_iso8601_int (text + 5, 2, &week) ||
1322           !get_iso8601_int (text + 7, 1, &week_day))
1323         return NULL;
1324       return g_date_time_new_week (tz, year, week, week_day, hour, minute, seconds);
1325     }
1326   /* YYYYMMDD */
1327   else if (length == 8)
1328     {
1329       int year, month, day;
1330       if (!get_iso8601_int (text, 4, &year) ||
1331           !get_iso8601_int (text + 4, 2, &month) ||
1332           !get_iso8601_int (text + 6, 2, &day))
1333         return NULL;
1334       return g_date_time_new (tz, year, month, day, hour, minute, seconds);
1335     }
1336   /* YYYYDDD */
1337   else if (length == 7)
1338     {
1339       gint year, ordinal_day;
1340       if (!get_iso8601_int (text, 4, &year) ||
1341           !get_iso8601_int (text + 4, 3, &ordinal_day))
1342         return NULL;
1343       return g_date_time_new_ordinal (tz, year, ordinal_day, hour, minute, seconds);
1344     }
1345   else
1346     return FALSE;
1347 }
1348
1349 static GTimeZone *
1350 parse_iso8601_timezone (const gchar *text, gsize length, gssize *tz_offset)
1351 {
1352   gint i, tz_length, offset_hours, offset_minutes;
1353   gint offset_sign = 1;
1354   GTimeZone *tz;
1355
1356   /* UTC uses Z suffix  */
1357   if (length > 0 && text[length - 1] == 'Z')
1358     {
1359       *tz_offset = length - 1;
1360       return g_time_zone_new_utc ();
1361     }
1362
1363   /* Look for '+' or '-' of offset */
1364   for (i = length - 1; i >= 0; i--)
1365     if (text[i] == '+' || text[i] == '-')
1366       {
1367         offset_sign = text[i] == '-' ? -1 : 1;
1368         break;
1369       }
1370   if (i < 0)
1371     return NULL;
1372   tz_length = length - i;
1373
1374   /* +hh:mm or -hh:mm */
1375   if (tz_length == 6 && text[i+3] == ':')
1376     {
1377       if (!get_iso8601_int (text + i + 1, 2, &offset_hours) ||
1378           !get_iso8601_int (text + i + 4, 2, &offset_minutes))
1379         return NULL;
1380     }
1381   /* +hhmm or -hhmm */
1382   else if (tz_length == 5)
1383     {
1384       if (!get_iso8601_int (text + i + 1, 2, &offset_hours) ||
1385           !get_iso8601_int (text + i + 3, 2, &offset_minutes))
1386         return NULL;
1387     }
1388   /* +hh or -hh */
1389   else if (tz_length == 3)
1390     {
1391       if (!get_iso8601_int (text + i + 1, 2, &offset_hours))
1392         return NULL;
1393       offset_minutes = 0;
1394     }
1395   else
1396     return NULL;
1397
1398   *tz_offset = i;
1399   tz = g_time_zone_new_identifier (text + i);
1400
1401   /* Double-check that the GTimeZone matches our interpretation of the timezone.
1402    * This can fail because our interpretation is less strict than (for example)
1403    * parse_time() in gtimezone.c, which restricts the range of the parsed
1404    * integers. */
1405   if (tz == NULL || g_time_zone_get_offset (tz, 0) != offset_sign * (offset_hours * 3600 + offset_minutes * 60))
1406     {
1407       g_clear_pointer (&tz, g_time_zone_unref);
1408       return NULL;
1409     }
1410
1411   return tz;
1412 }
1413
1414 static gboolean
1415 parse_iso8601_time (const gchar *text, gsize length,
1416                     gint *hour, gint *minute, gdouble *seconds, GTimeZone **tz)
1417 {
1418   gssize tz_offset = -1;
1419
1420   /* Check for timezone suffix */
1421   *tz = parse_iso8601_timezone (text, length, &tz_offset);
1422   if (tz_offset >= 0)
1423     length = tz_offset;
1424
1425   /* hh:mm:ss(.sss) */
1426   if (length >= 8 && text[2] == ':' && text[5] == ':')
1427     {
1428       return get_iso8601_int (text, 2, hour) &&
1429              get_iso8601_int (text + 3, 2, minute) &&
1430              get_iso8601_seconds (text + 6, length - 6, seconds);
1431     }
1432   /* hhmmss(.sss) */
1433   else if (length >= 6)
1434     {
1435       return get_iso8601_int (text, 2, hour) &&
1436              get_iso8601_int (text + 2, 2, minute) &&
1437              get_iso8601_seconds (text + 4, length - 4, seconds);
1438     }
1439   else
1440     return FALSE;
1441 }
1442
1443 /**
1444  * g_date_time_new_from_iso8601: (constructor)
1445  * @text: an ISO 8601 formatted time string.
1446  * @default_tz: (nullable): a #GTimeZone to use if the text doesn't contain a
1447  *                          timezone, or %NULL.
1448  *
1449  * Creates a #GDateTime corresponding to the given
1450  * [ISO 8601 formatted string](https://en.wikipedia.org/wiki/ISO_8601)
1451  * @text. ISO 8601 strings of the form <date><sep><time><tz> are supported, with
1452  * some extensions from [RFC 3339](https://tools.ietf.org/html/rfc3339) as
1453  * mentioned below.
1454  *
1455  * Note that as #GDateTime "is oblivious to leap seconds", leap seconds information
1456  * in an ISO-8601 string will be ignored, so a `23:59:60` time would be parsed as
1457  * `23:59:59`.
1458  *
1459  * <sep> is the separator and can be either 'T', 't' or ' '. The latter two
1460  * separators are an extension from
1461  * [RFC 3339](https://tools.ietf.org/html/rfc3339#section-5.6).
1462  *
1463  * <date> is in the form:
1464  *
1465  * - `YYYY-MM-DD` - Year/month/day, e.g. 2016-08-24.
1466  * - `YYYYMMDD` - Same as above without dividers.
1467  * - `YYYY-DDD` - Ordinal day where DDD is from 001 to 366, e.g. 2016-237.
1468  * - `YYYYDDD` - Same as above without dividers.
1469  * - `YYYY-Www-D` - Week day where ww is from 01 to 52 and D from 1-7,
1470  *   e.g. 2016-W34-3.
1471  * - `YYYYWwwD` - Same as above without dividers.
1472  *
1473  * <time> is in the form:
1474  *
1475  * - `hh:mm:ss(.sss)` - Hours, minutes, seconds (subseconds), e.g. 22:10:42.123.
1476  * - `hhmmss(.sss)` - Same as above without dividers.
1477  *
1478  * <tz> is an optional timezone suffix of the form:
1479  *
1480  * - `Z` - UTC.
1481  * - `+hh:mm` or `-hh:mm` - Offset from UTC in hours and minutes, e.g. +12:00.
1482  * - `+hh` or `-hh` - Offset from UTC in hours, e.g. +12.
1483  *
1484  * If the timezone is not provided in @text it must be provided in @default_tz
1485  * (this field is otherwise ignored).
1486  *
1487  * This call can fail (returning %NULL) if @text is not a valid ISO 8601
1488  * formatted string.
1489  *
1490  * You should release the return value by calling g_date_time_unref()
1491  * when you are done with it.
1492  *
1493  * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL
1494  *
1495  * Since: 2.56
1496  */
1497 GDateTime *
1498 g_date_time_new_from_iso8601 (const gchar *text, GTimeZone *default_tz)
1499 {
1500   gint length, date_length = -1;
1501   gint hour = 0, minute = 0;
1502   gdouble seconds = 0.0;
1503   GTimeZone *tz = NULL;
1504   GDateTime *datetime = NULL;
1505
1506   g_return_val_if_fail (text != NULL, NULL);
1507
1508   /* Count length of string and find date / time separator ('T', 't', or ' ') */
1509   for (length = 0; text[length] != '\0'; length++)
1510     {
1511       if (date_length < 0 && (text[length] == 'T' || text[length] == 't' || text[length] == ' '))
1512         date_length = length;
1513     }
1514
1515   if (date_length < 0)
1516     return NULL;
1517
1518   if (!parse_iso8601_time (text + date_length + 1, length - (date_length + 1),
1519                            &hour, &minute, &seconds, &tz))
1520     goto out;
1521   if (tz == NULL && default_tz == NULL)
1522     return NULL;
1523
1524   datetime = parse_iso8601_date (text, date_length, hour, minute, seconds, tz ? tz : default_tz);
1525
1526 out:
1527     if (tz != NULL)
1528       g_time_zone_unref (tz);
1529     return datetime;
1530 }
1531
1532 /* full new functions {{{1 */
1533
1534 /**
1535  * g_date_time_new: (constructor)
1536  * @tz: a #GTimeZone
1537  * @year: the year component of the date
1538  * @month: the month component of the date
1539  * @day: the day component of the date
1540  * @hour: the hour component of the date
1541  * @minute: the minute component of the date
1542  * @seconds: the number of seconds past the minute
1543  *
1544  * Creates a new #GDateTime corresponding to the given date and time in
1545  * the time zone @tz.
1546  *
1547  * The @year must be between 1 and 9999, @month between 1 and 12 and @day
1548  * between 1 and 28, 29, 30 or 31 depending on the month and the year.
1549  *
1550  * @hour must be between 0 and 23 and @minute must be between 0 and 59.
1551  *
1552  * @seconds must be at least 0.0 and must be strictly less than 60.0.
1553  * It will be rounded down to the nearest microsecond.
1554  *
1555  * If the given time is not representable in the given time zone (for
1556  * example, 02:30 on March 14th 2010 in Toronto, due to daylight savings
1557  * time) then the time will be rounded up to the nearest existing time
1558  * (in this case, 03:00).  If this matters to you then you should verify
1559  * the return value for containing the same as the numbers you gave.
1560  *
1561  * In the case that the given time is ambiguous in the given time zone
1562  * (for example, 01:30 on November 7th 2010 in Toronto, due to daylight
1563  * savings time) then the time falling within standard (ie:
1564  * non-daylight) time is taken.
1565  *
1566  * It not considered a programmer error for the values to this function
1567  * to be out of range, but in the case that they are, the function will
1568  * return %NULL.
1569  *
1570  * You should release the return value by calling g_date_time_unref()
1571  * when you are done with it.
1572  *
1573  * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL
1574  *
1575  * Since: 2.26
1576  **/
1577 GDateTime *
1578 g_date_time_new (GTimeZone *tz,
1579                  gint       year,
1580                  gint       month,
1581                  gint       day,
1582                  gint       hour,
1583                  gint       minute,
1584                  gdouble    seconds)
1585 {
1586   GDateTime *datetime;
1587   gint64 full_time;
1588   /* keep these variables as volatile. We do not want them ending up in
1589    * registers - them doing so may cause us to hit precision problems on i386.
1590    * See: https://bugzilla.gnome.org/show_bug.cgi?id=792410 */
1591   volatile gint64 usec;
1592   volatile gdouble usecd;
1593
1594   g_return_val_if_fail (tz != NULL, NULL);
1595
1596   if (year < 1 || year > 9999 ||
1597       month < 1 || month > 12 ||
1598       day < 1 || day > days_in_months[GREGORIAN_LEAP (year)][month] ||
1599       hour < 0 || hour > 23 ||
1600       minute < 0 || minute > 59 ||
1601       isnan (seconds) ||
1602       seconds < 0.0 || seconds >= 60.0)
1603     return NULL;
1604
1605   datetime = g_date_time_alloc (tz);
1606   datetime->days = ymd_to_days (year, month, day);
1607   datetime->usec = (hour   * USEC_PER_HOUR)
1608                  + (minute * USEC_PER_MINUTE)
1609                  + (gint64) (seconds * USEC_PER_SECOND);
1610
1611   full_time = SEC_PER_DAY *
1612                 (ymd_to_days (year, month, day) - UNIX_EPOCH_START) +
1613               SECS_PER_HOUR * hour +
1614               SECS_PER_MINUTE * minute +
1615               (int) seconds;
1616
1617   datetime->interval = g_time_zone_adjust_time (datetime->tz,
1618                                                 G_TIME_TYPE_STANDARD,
1619                                                 &full_time);
1620
1621   /* This is the correct way to convert a scaled FP value to integer.
1622    * If this surprises you, please observe that (int)(1.000001 * 1e6)
1623    * is 1000000.  This is not a problem with precision, it's just how
1624    * FP numbers work.
1625    * See https://bugzilla.gnome.org/show_bug.cgi?id=697715. */
1626   usec = seconds * USEC_PER_SECOND;
1627   usecd = (usec + 1) * 1e-6;
1628   if (usecd <= seconds) {
1629     usec++;
1630   }
1631
1632   full_time += UNIX_EPOCH_START * SEC_PER_DAY;
1633   datetime->days = full_time / SEC_PER_DAY;
1634   datetime->usec = (full_time % SEC_PER_DAY) * USEC_PER_SECOND;
1635   datetime->usec += usec % USEC_PER_SECOND;
1636
1637   return datetime;
1638 }
1639
1640 /**
1641  * g_date_time_new_local: (constructor)
1642  * @year: the year component of the date
1643  * @month: the month component of the date
1644  * @day: the day component of the date
1645  * @hour: the hour component of the date
1646  * @minute: the minute component of the date
1647  * @seconds: the number of seconds past the minute
1648  *
1649  * Creates a new #GDateTime corresponding to the given date and time in
1650  * the local time zone.
1651  *
1652  * This call is equivalent to calling g_date_time_new() with the time
1653  * zone returned by g_time_zone_new_local().
1654  *
1655  * Returns: (transfer full) (nullable): a #GDateTime, or %NULL
1656  *
1657  * Since: 2.26
1658  **/
1659 GDateTime *
1660 g_date_time_new_local (gint    year,
1661                        gint    month,
1662                        gint    day,
1663                        gint    hour,
1664                        gint    minute,
1665                        gdouble seconds)
1666 {
1667   GDateTime *datetime;
1668   GTimeZone *local;
1669
1670   local = g_time_zone_new_local ();
1671   datetime = g_date_time_new (local, year, month, day, hour, minute, seconds);
1672   g_time_zone_unref (local);
1673
1674   return datetime;
1675 }
1676
1677 /**
1678  * g_date_time_new_utc: (constructor)
1679  * @year: the year component of the date
1680  * @month: the month component of the date
1681  * @day: the day component of the date
1682  * @hour: the hour component of the date
1683  * @minute: the minute component of the date
1684  * @seconds: the number of seconds past the minute
1685  *
1686  * Creates a new #GDateTime corresponding to the given date and time in
1687  * UTC.
1688  *
1689  * This call is equivalent to calling g_date_time_new() with the time
1690  * zone returned by g_time_zone_new_utc().
1691  *
1692  * Returns: (transfer full) (nullable): a #GDateTime, or %NULL
1693  *
1694  * Since: 2.26
1695  **/
1696 GDateTime *
1697 g_date_time_new_utc (gint    year,
1698                      gint    month,
1699                      gint    day,
1700                      gint    hour,
1701                      gint    minute,
1702                      gdouble seconds)
1703 {
1704   GDateTime *datetime;
1705   GTimeZone *utc;
1706
1707   utc = g_time_zone_new_utc ();
1708   datetime = g_date_time_new (utc, year, month, day, hour, minute, seconds);
1709   g_time_zone_unref (utc);
1710
1711   return datetime;
1712 }
1713
1714 /* Adders {{{1 */
1715
1716 /**
1717  * g_date_time_add:
1718  * @datetime: a #GDateTime
1719  * @timespan: a #GTimeSpan
1720  *
1721  * Creates a copy of @datetime and adds the specified timespan to the copy.
1722  *
1723  * Returns: (transfer full) (nullable): the newly created #GDateTime which
1724  *   should be freed with g_date_time_unref(), or %NULL
1725  *
1726  * Since: 2.26
1727  */
1728 GDateTime*
1729 g_date_time_add (GDateTime *datetime,
1730                  GTimeSpan  timespan)
1731 {
1732   g_return_val_if_fail (datetime != NULL, NULL);
1733
1734   return g_date_time_from_instant (datetime->tz, timespan +
1735                                    g_date_time_to_instant (datetime));
1736 }
1737
1738 /**
1739  * g_date_time_add_years:
1740  * @datetime: a #GDateTime
1741  * @years: the number of years
1742  *
1743  * Creates a copy of @datetime and adds the specified number of years to the
1744  * copy. Add negative values to subtract years.
1745  *
1746  * As with g_date_time_add_months(), if the resulting date would be 29th
1747  * February on a non-leap year, the day will be clamped to 28th February.
1748  *
1749  * Returns: (transfer full) (nullable): the newly created #GDateTime which
1750  *   should be freed with g_date_time_unref(), or %NULL
1751  *
1752  * Since: 2.26
1753  */
1754 GDateTime *
1755 g_date_time_add_years (GDateTime *datetime,
1756                        gint       years)
1757 {
1758   gint year, month, day;
1759
1760   g_return_val_if_fail (datetime != NULL, NULL);
1761
1762   if (years < -10000 || years > 10000)
1763     return NULL;
1764
1765   g_date_time_get_ymd (datetime, &year, &month, &day);
1766   year += years;
1767
1768   /* only possible issue is if we've entered a year with no February 29
1769    */
1770   if (month == 2 && day == 29 && !GREGORIAN_LEAP (year))
1771     day = 28;
1772
1773   return g_date_time_replace_days (datetime, ymd_to_days (year, month, day));
1774 }
1775
1776 /**
1777  * g_date_time_add_months:
1778  * @datetime: a #GDateTime
1779  * @months: the number of months
1780  *
1781  * Creates a copy of @datetime and adds the specified number of months to the
1782  * copy. Add negative values to subtract months.
1783  *
1784  * The day of the month of the resulting #GDateTime is clamped to the number
1785  * of days in the updated calendar month. For example, if adding 1 month to
1786  * 31st January 2018, the result would be 28th February 2018. In 2020 (a leap
1787  * year), the result would be 29th February.
1788  *
1789  * Returns: (transfer full) (nullable): the newly created #GDateTime which
1790  *   should be freed with g_date_time_unref(), or %NULL
1791  *
1792  * Since: 2.26
1793  */
1794 GDateTime*
1795 g_date_time_add_months (GDateTime *datetime,
1796                         gint       months)
1797 {
1798   gint year, month, day;
1799
1800   g_return_val_if_fail (datetime != NULL, NULL);
1801   g_date_time_get_ymd (datetime, &year, &month, &day);
1802
1803   if (months < -120000 || months > 120000)
1804     return NULL;
1805
1806   year += months / 12;
1807   month += months % 12;
1808   if (month < 1)
1809     {
1810       month += 12;
1811       year--;
1812     }
1813   else if (month > 12)
1814     {
1815       month -= 12;
1816       year++;
1817     }
1818
1819   day = MIN (day, days_in_months[GREGORIAN_LEAP (year)][month]);
1820
1821   return g_date_time_replace_days (datetime, ymd_to_days (year, month, day));
1822 }
1823
1824 /**
1825  * g_date_time_add_weeks:
1826  * @datetime: a #GDateTime
1827  * @weeks: the number of weeks
1828  *
1829  * Creates a copy of @datetime and adds the specified number of weeks to the
1830  * copy. Add negative values to subtract weeks.
1831  *
1832  * Returns: (transfer full) (nullable): the newly created #GDateTime which
1833  *   should be freed with g_date_time_unref(), or %NULL
1834  *
1835  * Since: 2.26
1836  */
1837 GDateTime*
1838 g_date_time_add_weeks (GDateTime *datetime,
1839                        gint             weeks)
1840 {
1841   g_return_val_if_fail (datetime != NULL, NULL);
1842
1843   return g_date_time_add_days (datetime, weeks * 7);
1844 }
1845
1846 /**
1847  * g_date_time_add_days:
1848  * @datetime: a #GDateTime
1849  * @days: the number of days
1850  *
1851  * Creates a copy of @datetime and adds the specified number of days to the
1852  * copy. Add negative values to subtract days.
1853  *
1854  * Returns: (transfer full) (nullable): the newly created #GDateTime which
1855  *   should be freed with g_date_time_unref(), or %NULL
1856  *
1857  * Since: 2.26
1858  */
1859 GDateTime*
1860 g_date_time_add_days (GDateTime *datetime,
1861                       gint       days)
1862 {
1863   g_return_val_if_fail (datetime != NULL, NULL);
1864
1865   if (days < -3660000 || days > 3660000)
1866     return NULL;
1867
1868   return g_date_time_replace_days (datetime, datetime->days + days);
1869 }
1870
1871 /**
1872  * g_date_time_add_hours:
1873  * @datetime: a #GDateTime
1874  * @hours: the number of hours to add
1875  *
1876  * Creates a copy of @datetime and adds the specified number of hours.
1877  * Add negative values to subtract hours.
1878  *
1879  * Returns: (transfer full) (nullable): the newly created #GDateTime which
1880  *   should be freed with g_date_time_unref(), or %NULL
1881  *
1882  * Since: 2.26
1883  */
1884 GDateTime*
1885 g_date_time_add_hours (GDateTime *datetime,
1886                        gint       hours)
1887 {
1888   return g_date_time_add (datetime, hours * USEC_PER_HOUR);
1889 }
1890
1891 /**
1892  * g_date_time_add_minutes:
1893  * @datetime: a #GDateTime
1894  * @minutes: the number of minutes to add
1895  *
1896  * Creates a copy of @datetime adding the specified number of minutes.
1897  * Add negative values to subtract minutes.
1898  *
1899  * Returns: (transfer full) (nullable): the newly created #GDateTime which
1900  *   should be freed with g_date_time_unref(), or %NULL
1901  *
1902  * Since: 2.26
1903  */
1904 GDateTime*
1905 g_date_time_add_minutes (GDateTime *datetime,
1906                          gint             minutes)
1907 {
1908   return g_date_time_add (datetime, minutes * USEC_PER_MINUTE);
1909 }
1910
1911
1912 /**
1913  * g_date_time_add_seconds:
1914  * @datetime: a #GDateTime
1915  * @seconds: the number of seconds to add
1916  *
1917  * Creates a copy of @datetime and adds the specified number of seconds.
1918  * Add negative values to subtract seconds.
1919  *
1920  * Returns: (transfer full) (nullable): the newly created #GDateTime which
1921  *   should be freed with g_date_time_unref(), or %NULL
1922  *
1923  * Since: 2.26
1924  */
1925 GDateTime*
1926 g_date_time_add_seconds (GDateTime *datetime,
1927                          gdouble    seconds)
1928 {
1929   return g_date_time_add (datetime, seconds * USEC_PER_SECOND);
1930 }
1931
1932 /**
1933  * g_date_time_add_full:
1934  * @datetime: a #GDateTime
1935  * @years: the number of years to add
1936  * @months: the number of months to add
1937  * @days: the number of days to add
1938  * @hours: the number of hours to add
1939  * @minutes: the number of minutes to add
1940  * @seconds: the number of seconds to add
1941  *
1942  * Creates a new #GDateTime adding the specified values to the current date and
1943  * time in @datetime. Add negative values to subtract.
1944  *
1945  * Returns: (transfer full) (nullable): the newly created #GDateTime which
1946  *   should be freed with g_date_time_unref(), or %NULL
1947  *
1948  * Since: 2.26
1949  */
1950 GDateTime *
1951 g_date_time_add_full (GDateTime *datetime,
1952                       gint       years,
1953                       gint       months,
1954                       gint       days,
1955                       gint       hours,
1956                       gint       minutes,
1957                       gdouble    seconds)
1958 {
1959   gint year, month, day;
1960   gint64 full_time;
1961   GDateTime *new;
1962   gint interval;
1963
1964   g_return_val_if_fail (datetime != NULL, NULL);
1965   g_date_time_get_ymd (datetime, &year, &month, &day);
1966
1967   months += years * 12;
1968
1969   if (months < -120000 || months > 120000)
1970     return NULL;
1971
1972   if (days < -3660000 || days > 3660000)
1973     return NULL;
1974
1975   year += months / 12;
1976   month += months % 12;
1977   if (month < 1)
1978     {
1979       month += 12;
1980       year--;
1981     }
1982   else if (month > 12)
1983     {
1984       month -= 12;
1985       year++;
1986     }
1987
1988   day = MIN (day, days_in_months[GREGORIAN_LEAP (year)][month]);
1989
1990   /* full_time is now in unix (local) time */
1991   full_time = datetime->usec / USEC_PER_SECOND + SEC_PER_DAY *
1992     (ymd_to_days (year, month, day) + days - UNIX_EPOCH_START);
1993
1994   interval = g_time_zone_adjust_time (datetime->tz,
1995                                       g_time_zone_is_dst (datetime->tz,
1996                                                           datetime->interval),
1997                                       &full_time);
1998
1999   /* move to UTC unix time */
2000   full_time -= g_time_zone_get_offset (datetime->tz, interval);
2001
2002   /* convert back to an instant, add back fractional seconds */
2003   full_time += UNIX_EPOCH_START * SEC_PER_DAY;
2004   full_time = full_time * USEC_PER_SECOND +
2005               datetime->usec % USEC_PER_SECOND;
2006
2007   /* do the actual addition now */
2008   full_time += (hours * USEC_PER_HOUR) +
2009                (minutes * USEC_PER_MINUTE) +
2010                (gint64) (seconds * USEC_PER_SECOND);
2011
2012   /* find the new interval */
2013   interval = g_time_zone_find_interval (datetime->tz,
2014                                         G_TIME_TYPE_UNIVERSAL,
2015                                         INSTANT_TO_UNIX (full_time));
2016
2017   /* convert back into local time */
2018   full_time += USEC_PER_SECOND *
2019                g_time_zone_get_offset (datetime->tz, interval);
2020
2021   /* split into days and usec of a new datetime */
2022   new = g_date_time_alloc (datetime->tz);
2023   new->interval = interval;
2024   new->days = full_time / USEC_PER_DAY;
2025   new->usec = full_time % USEC_PER_DAY;
2026
2027   /* XXX validate */
2028
2029   return new;
2030 }
2031
2032 /* Compare, difference, hash, equal {{{1 */
2033 /**
2034  * g_date_time_compare:
2035  * @dt1: (type GDateTime) (not nullable): first #GDateTime to compare
2036  * @dt2: (type GDateTime) (not nullable): second #GDateTime to compare
2037  *
2038  * A comparison function for #GDateTimes that is suitable
2039  * as a #GCompareFunc. Both #GDateTimes must be non-%NULL.
2040  *
2041  * Returns: -1, 0 or 1 if @dt1 is less than, equal to or greater
2042  *   than @dt2.
2043  *
2044  * Since: 2.26
2045  */
2046 gint
2047 g_date_time_compare (gconstpointer dt1,
2048                      gconstpointer dt2)
2049 {
2050   gint64 difference;
2051
2052   difference = g_date_time_difference ((GDateTime *) dt1, (GDateTime *) dt2);
2053
2054   if (difference < 0)
2055     return -1;
2056
2057   else if (difference > 0)
2058     return 1;
2059
2060   else
2061     return 0;
2062 }
2063
2064 /**
2065  * g_date_time_difference:
2066  * @end: a #GDateTime
2067  * @begin: a #GDateTime
2068  *
2069  * Calculates the difference in time between @end and @begin.  The
2070  * #GTimeSpan that is returned is effectively @end - @begin (ie:
2071  * positive if the first parameter is larger).
2072  *
2073  * Returns: the difference between the two #GDateTime, as a time
2074  *   span expressed in microseconds.
2075  *
2076  * Since: 2.26
2077  */
2078 GTimeSpan
2079 g_date_time_difference (GDateTime *end,
2080                         GDateTime *begin)
2081 {
2082   g_return_val_if_fail (begin != NULL, 0);
2083   g_return_val_if_fail (end != NULL, 0);
2084
2085   return g_date_time_to_instant (end) -
2086          g_date_time_to_instant (begin);
2087 }
2088
2089 /**
2090  * g_date_time_hash:
2091  * @datetime: (type GDateTime) (not nullable): a #GDateTime
2092  *
2093  * Hashes @datetime into a #guint, suitable for use within #GHashTable.
2094  *
2095  * Returns: a #guint containing the hash
2096  *
2097  * Since: 2.26
2098  */
2099 guint
2100 g_date_time_hash (gconstpointer datetime)
2101 {
2102   g_return_val_if_fail (datetime != NULL, 0);
2103
2104   return g_date_time_to_instant ((GDateTime *) datetime);
2105 }
2106
2107 /**
2108  * g_date_time_equal:
2109  * @dt1: (type GDateTime) (not nullable): a #GDateTime
2110  * @dt2: (type GDateTime) (not nullable): a #GDateTime
2111  *
2112  * Checks to see if @dt1 and @dt2 are equal.
2113  *
2114  * Equal here means that they represent the same moment after converting
2115  * them to the same time zone.
2116  *
2117  * Returns: %TRUE if @dt1 and @dt2 are equal
2118  *
2119  * Since: 2.26
2120  */
2121 gboolean
2122 g_date_time_equal (gconstpointer dt1,
2123                    gconstpointer dt2)
2124 {
2125   return g_date_time_difference ((GDateTime *) dt1, (GDateTime *) dt2) == 0;
2126 }
2127
2128 /* Year, Month, Day Getters {{{1 */
2129 /**
2130  * g_date_time_get_ymd:
2131  * @datetime: a #GDateTime.
2132  * @year: (out) (optional): the return location for the gregorian year, or %NULL.
2133  * @month: (out) (optional): the return location for the month of the year, or %NULL.
2134  * @day: (out) (optional): the return location for the day of the month, or %NULL.
2135  *
2136  * Retrieves the Gregorian day, month, and year of a given #GDateTime.
2137  *
2138  * Since: 2.26
2139  **/
2140 void
2141 g_date_time_get_ymd (GDateTime *datetime,
2142                      gint      *year,
2143                      gint      *month,
2144                      gint      *day)
2145 {
2146   gint the_year;
2147   gint the_month;
2148   gint the_day;
2149   gint remaining_days;
2150   gint y100_cycles;
2151   gint y4_cycles;
2152   gint y1_cycles;
2153   gint preceding;
2154   gboolean leap;
2155
2156   g_return_if_fail (datetime != NULL);
2157
2158   remaining_days = datetime->days;
2159
2160   /*
2161    * We need to convert an offset in days to its year/month/day representation.
2162    * Leap years makes this a little trickier than it should be, so we use
2163    * 400, 100 and 4 years cycles here to get to the correct year.
2164    */
2165
2166   /* Our days offset starts sets 0001-01-01 as day 1, if it was day 0 our
2167    * math would be simpler, so let's do it */
2168   remaining_days--;
2169
2170   the_year = (remaining_days / DAYS_IN_400YEARS) * 400 + 1;
2171   remaining_days = remaining_days % DAYS_IN_400YEARS;
2172
2173   y100_cycles = remaining_days / DAYS_IN_100YEARS;
2174   remaining_days = remaining_days % DAYS_IN_100YEARS;
2175   the_year += y100_cycles * 100;
2176
2177   y4_cycles = remaining_days / DAYS_IN_4YEARS;
2178   remaining_days = remaining_days % DAYS_IN_4YEARS;
2179   the_year += y4_cycles * 4;
2180
2181   y1_cycles = remaining_days / 365;
2182   the_year += y1_cycles;
2183   remaining_days = remaining_days % 365;
2184
2185   if (y1_cycles == 4 || y100_cycles == 4) {
2186     g_assert (remaining_days == 0);
2187
2188     /* special case that indicates that the date is actually one year before,
2189      * in the 31th of December */
2190     the_year--;
2191     the_month = 12;
2192     the_day = 31;
2193     goto end;
2194   }
2195
2196   /* now get the month and the day */
2197   leap = y1_cycles == 3 && (y4_cycles != 24 || y100_cycles == 3);
2198
2199   g_assert (leap == GREGORIAN_LEAP(the_year));
2200
2201   the_month = (remaining_days + 50) >> 5;
2202   preceding = (days_in_year[0][the_month - 1] + (the_month > 2 && leap));
2203   if (preceding > remaining_days)
2204     {
2205       /* estimate is too large */
2206       the_month -= 1;
2207       preceding -= leap ? days_in_months[1][the_month]
2208                         : days_in_months[0][the_month];
2209     }
2210
2211   remaining_days -= preceding;
2212   g_assert(0 <= remaining_days);
2213
2214   the_day = remaining_days + 1;
2215
2216 end:
2217   if (year)
2218     *year = the_year;
2219   if (month)
2220     *month = the_month;
2221   if (day)
2222     *day = the_day;
2223 }
2224
2225 /**
2226  * g_date_time_get_year:
2227  * @datetime: A #GDateTime
2228  *
2229  * Retrieves the year represented by @datetime in the Gregorian calendar.
2230  *
2231  * Returns: the year represented by @datetime
2232  *
2233  * Since: 2.26
2234  */
2235 gint
2236 g_date_time_get_year (GDateTime *datetime)
2237 {
2238   gint year;
2239
2240   g_return_val_if_fail (datetime != NULL, 0);
2241
2242   g_date_time_get_ymd (datetime, &year, NULL, NULL);
2243
2244   return year;
2245 }
2246
2247 /**
2248  * g_date_time_get_month:
2249  * @datetime: a #GDateTime
2250  *
2251  * Retrieves the month of the year represented by @datetime in the Gregorian
2252  * calendar.
2253  *
2254  * Returns: the month represented by @datetime
2255  *
2256  * Since: 2.26
2257  */
2258 gint
2259 g_date_time_get_month (GDateTime *datetime)
2260 {
2261   gint month;
2262
2263   g_return_val_if_fail (datetime != NULL, 0);
2264
2265   g_date_time_get_ymd (datetime, NULL, &month, NULL);
2266
2267   return month;
2268 }
2269
2270 /**
2271  * g_date_time_get_day_of_month:
2272  * @datetime: a #GDateTime
2273  *
2274  * Retrieves the day of the month represented by @datetime in the gregorian
2275  * calendar.
2276  *
2277  * Returns: the day of the month
2278  *
2279  * Since: 2.26
2280  */
2281 gint
2282 g_date_time_get_day_of_month (GDateTime *datetime)
2283 {
2284   gint           day_of_year,
2285                  i;
2286   guint          is_leap;
2287   guint16        last = 0;
2288
2289   g_return_val_if_fail (datetime != NULL, 0);
2290
2291   is_leap = GREGORIAN_LEAP (g_date_time_get_year (datetime)) ? 1 : 0;
2292   g_date_time_get_week_number (datetime, NULL, NULL, &day_of_year);
2293
2294   for (i = 1; i <= 12; i++)
2295     {
2296       if (days_in_year[is_leap][i] >= day_of_year)
2297         return day_of_year - last;
2298       last = days_in_year[is_leap][i];
2299     }
2300
2301   g_warn_if_reached ();
2302   return 0;
2303 }
2304
2305 /* Week of year / day of week getters {{{1 */
2306 /**
2307  * g_date_time_get_week_numbering_year:
2308  * @datetime: a #GDateTime
2309  *
2310  * Returns the ISO 8601 week-numbering year in which the week containing
2311  * @datetime falls.
2312  *
2313  * This function, taken together with g_date_time_get_week_of_year() and
2314  * g_date_time_get_day_of_week() can be used to determine the full ISO
2315  * week date on which @datetime falls.
2316  *
2317  * This is usually equal to the normal Gregorian year (as returned by
2318  * g_date_time_get_year()), except as detailed below:
2319  *
2320  * For Thursday, the week-numbering year is always equal to the usual
2321  * calendar year.  For other days, the number is such that every day
2322  * within a complete week (Monday to Sunday) is contained within the
2323  * same week-numbering year.
2324  *
2325  * For Monday, Tuesday and Wednesday occurring near the end of the year,
2326  * this may mean that the week-numbering year is one greater than the
2327  * calendar year (so that these days have the same week-numbering year
2328  * as the Thursday occurring early in the next year).
2329  *
2330  * For Friday, Saturday and Sunday occurring near the start of the year,
2331  * this may mean that the week-numbering year is one less than the
2332  * calendar year (so that these days have the same week-numbering year
2333  * as the Thursday occurring late in the previous year).
2334  *
2335  * An equivalent description is that the week-numbering year is equal to
2336  * the calendar year containing the majority of the days in the current
2337  * week (Monday to Sunday).
2338  *
2339  * Note that January 1 0001 in the proleptic Gregorian calendar is a
2340  * Monday, so this function never returns 0.
2341  *
2342  * Returns: the ISO 8601 week-numbering year for @datetime
2343  *
2344  * Since: 2.26
2345  **/
2346 gint
2347 g_date_time_get_week_numbering_year (GDateTime *datetime)
2348 {
2349   gint year = -1, month = -1, day = -1, weekday;
2350
2351   g_date_time_get_ymd (datetime, &year, &month, &day);
2352   weekday = g_date_time_get_day_of_week (datetime);
2353
2354   /* January 1, 2, 3 might be in the previous year if they occur after
2355    * Thursday.
2356    *
2357    *   Jan 1:  Friday, Saturday, Sunday    =>  day 1:  weekday 5, 6, 7
2358    *   Jan 2:  Saturday, Sunday            =>  day 2:  weekday 6, 7
2359    *   Jan 3:  Sunday                      =>  day 3:  weekday 7
2360    *
2361    * So we have a special case if (day - weekday) <= -4
2362    */
2363   if (month == 1 && (day - weekday) <= -4)
2364     return year - 1;
2365
2366   /* December 29, 30, 31 might be in the next year if they occur before
2367    * Thursday.
2368    *
2369    *   Dec 31: Monday, Tuesday, Wednesday  =>  day 31: weekday 1, 2, 3
2370    *   Dec 30: Monday, Tuesday             =>  day 30: weekday 1, 2
2371    *   Dec 29: Monday                      =>  day 29: weekday 1
2372    *
2373    * So we have a special case if (day - weekday) >= 28
2374    */
2375   else if (month == 12 && (day - weekday) >= 28)
2376     return year + 1;
2377
2378   else
2379     return year;
2380 }
2381
2382 /**
2383  * g_date_time_get_week_of_year:
2384  * @datetime: a #GDateTime
2385  *
2386  * Returns the ISO 8601 week number for the week containing @datetime.
2387  * The ISO 8601 week number is the same for every day of the week (from
2388  * Moday through Sunday).  That can produce some unusual results
2389  * (described below).
2390  *
2391  * The first week of the year is week 1.  This is the week that contains
2392  * the first Thursday of the year.  Equivalently, this is the first week
2393  * that has more than 4 of its days falling within the calendar year.
2394  *
2395  * The value 0 is never returned by this function.  Days contained
2396  * within a year but occurring before the first ISO 8601 week of that
2397  * year are considered as being contained in the last week of the
2398  * previous year.  Similarly, the final days of a calendar year may be
2399  * considered as being part of the first ISO 8601 week of the next year
2400  * if 4 or more days of that week are contained within the new year.
2401  *
2402  * Returns: the ISO 8601 week number for @datetime.
2403  *
2404  * Since: 2.26
2405  */
2406 gint
2407 g_date_time_get_week_of_year (GDateTime *datetime)
2408 {
2409   gint weeknum;
2410
2411   g_return_val_if_fail (datetime != NULL, 0);
2412
2413   g_date_time_get_week_number (datetime, &weeknum, NULL, NULL);
2414
2415   return weeknum;
2416 }
2417
2418 /**
2419  * g_date_time_get_day_of_week:
2420  * @datetime: a #GDateTime
2421  *
2422  * Retrieves the ISO 8601 day of the week on which @datetime falls (1 is
2423  * Monday, 2 is Tuesday... 7 is Sunday).
2424  *
2425  * Returns: the day of the week
2426  *
2427  * Since: 2.26
2428  */
2429 gint
2430 g_date_time_get_day_of_week (GDateTime *datetime)
2431 {
2432   g_return_val_if_fail (datetime != NULL, 0);
2433
2434   return (datetime->days - 1) % 7 + 1;
2435 }
2436
2437 /* Day of year getter {{{1 */
2438 /**
2439  * g_date_time_get_day_of_year:
2440  * @datetime: a #GDateTime
2441  *
2442  * Retrieves the day of the year represented by @datetime in the Gregorian
2443  * calendar.
2444  *
2445  * Returns: the day of the year
2446  *
2447  * Since: 2.26
2448  */
2449 gint
2450 g_date_time_get_day_of_year (GDateTime *datetime)
2451 {
2452   gint doy = 0;
2453
2454   g_return_val_if_fail (datetime != NULL, 0);
2455
2456   g_date_time_get_week_number (datetime, NULL, NULL, &doy);
2457   return doy;
2458 }
2459
2460 /* Time component getters {{{1 */
2461
2462 /**
2463  * g_date_time_get_hour:
2464  * @datetime: a #GDateTime
2465  *
2466  * Retrieves the hour of the day represented by @datetime
2467  *
2468  * Returns: the hour of the day
2469  *
2470  * Since: 2.26
2471  */
2472 gint
2473 g_date_time_get_hour (GDateTime *datetime)
2474 {
2475   g_return_val_if_fail (datetime != NULL, 0);
2476
2477   return (datetime->usec / USEC_PER_HOUR);
2478 }
2479
2480 /**
2481  * g_date_time_get_minute:
2482  * @datetime: a #GDateTime
2483  *
2484  * Retrieves the minute of the hour represented by @datetime
2485  *
2486  * Returns: the minute of the hour
2487  *
2488  * Since: 2.26
2489  */
2490 gint
2491 g_date_time_get_minute (GDateTime *datetime)
2492 {
2493   g_return_val_if_fail (datetime != NULL, 0);
2494
2495   return (datetime->usec % USEC_PER_HOUR) / USEC_PER_MINUTE;
2496 }
2497
2498 /**
2499  * g_date_time_get_second:
2500  * @datetime: a #GDateTime
2501  *
2502  * Retrieves the second of the minute represented by @datetime
2503  *
2504  * Returns: the second represented by @datetime
2505  *
2506  * Since: 2.26
2507  */
2508 gint
2509 g_date_time_get_second (GDateTime *datetime)
2510 {
2511   g_return_val_if_fail (datetime != NULL, 0);
2512
2513   return (datetime->usec % USEC_PER_MINUTE) / USEC_PER_SECOND;
2514 }
2515
2516 /**
2517  * g_date_time_get_microsecond:
2518  * @datetime: a #GDateTime
2519  *
2520  * Retrieves the microsecond of the date represented by @datetime
2521  *
2522  * Returns: the microsecond of the second
2523  *
2524  * Since: 2.26
2525  */
2526 gint
2527 g_date_time_get_microsecond (GDateTime *datetime)
2528 {
2529   g_return_val_if_fail (datetime != NULL, 0);
2530
2531   return (datetime->usec % USEC_PER_SECOND);
2532 }
2533
2534 /**
2535  * g_date_time_get_seconds:
2536  * @datetime: a #GDateTime
2537  *
2538  * Retrieves the number of seconds since the start of the last minute,
2539  * including the fractional part.
2540  *
2541  * Returns: the number of seconds
2542  *
2543  * Since: 2.26
2544  **/
2545 gdouble
2546 g_date_time_get_seconds (GDateTime *datetime)
2547 {
2548   g_return_val_if_fail (datetime != NULL, 0);
2549
2550   return (datetime->usec % USEC_PER_MINUTE) / 1000000.0;
2551 }
2552
2553 /* Exporters {{{1 */
2554 /**
2555  * g_date_time_to_unix:
2556  * @datetime: a #GDateTime
2557  *
2558  * Gives the Unix time corresponding to @datetime, rounding down to the
2559  * nearest second.
2560  *
2561  * Unix time is the number of seconds that have elapsed since 1970-01-01
2562  * 00:00:00 UTC, regardless of the time zone associated with @datetime.
2563  *
2564  * Returns: the Unix time corresponding to @datetime
2565  *
2566  * Since: 2.26
2567  **/
2568 gint64
2569 g_date_time_to_unix (GDateTime *datetime)
2570 {
2571   g_return_val_if_fail (datetime != NULL, 0);
2572
2573   return INSTANT_TO_UNIX (g_date_time_to_instant (datetime));
2574 }
2575
2576 /**
2577  * g_date_time_to_timeval:
2578  * @datetime: a #GDateTime
2579  * @tv: a #GTimeVal to modify
2580  *
2581  * Stores the instant in time that @datetime represents into @tv.
2582  *
2583  * The time contained in a #GTimeVal is always stored in the form of
2584  * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the time
2585  * zone associated with @datetime.
2586  *
2587  * On systems where 'long' is 32bit (ie: all 32bit systems and all
2588  * Windows systems), a #GTimeVal is incapable of storing the entire
2589  * range of values that #GDateTime is capable of expressing.  On those
2590  * systems, this function returns %FALSE to indicate that the time is
2591  * out of range.
2592  *
2593  * On systems where 'long' is 64bit, this function never fails.
2594  *
2595  * Returns: %TRUE if successful, else %FALSE
2596  *
2597  * Since: 2.26
2598  * Deprecated: 2.62: #GTimeVal is not year-2038-safe. Use
2599  *    g_date_time_to_unix() instead.
2600  **/
2601 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2602 gboolean
2603 g_date_time_to_timeval (GDateTime *datetime,
2604                         GTimeVal  *tv)
2605 {
2606   g_return_val_if_fail (datetime != NULL, FALSE);
2607
2608   tv->tv_sec = INSTANT_TO_UNIX (g_date_time_to_instant (datetime));
2609   tv->tv_usec = datetime->usec % USEC_PER_SECOND;
2610
2611   return TRUE;
2612 }
2613 G_GNUC_END_IGNORE_DEPRECATIONS
2614
2615 /* Timezone queries {{{1 */
2616 /**
2617  * g_date_time_get_utc_offset:
2618  * @datetime: a #GDateTime
2619  *
2620  * Determines the offset to UTC in effect at the time and in the time
2621  * zone of @datetime.
2622  *
2623  * The offset is the number of microseconds that you add to UTC time to
2624  * arrive at local time for the time zone (ie: negative numbers for time
2625  * zones west of GMT, positive numbers for east).
2626  *
2627  * If @datetime represents UTC time, then the offset is always zero.
2628  *
2629  * Returns: the number of microseconds that should be added to UTC to
2630  *          get the local time
2631  *
2632  * Since: 2.26
2633  **/
2634 GTimeSpan
2635 g_date_time_get_utc_offset (GDateTime *datetime)
2636 {
2637   gint offset;
2638
2639   g_return_val_if_fail (datetime != NULL, 0);
2640
2641   offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
2642
2643   return (gint64) offset * USEC_PER_SECOND;
2644 }
2645
2646 /**
2647  * g_date_time_get_timezone:
2648  * @datetime: a #GDateTime
2649  *
2650  * Get the time zone for this @datetime.
2651  *
2652  * Returns: (transfer none): the time zone
2653  * Since: 2.58
2654  */
2655 GTimeZone *
2656 g_date_time_get_timezone (GDateTime *datetime)
2657 {
2658   g_return_val_if_fail (datetime != NULL, NULL);
2659
2660   g_assert (datetime->tz != NULL);
2661   return datetime->tz;
2662 }
2663
2664 /**
2665  * g_date_time_get_timezone_abbreviation:
2666  * @datetime: a #GDateTime
2667  *
2668  * Determines the time zone abbreviation to be used at the time and in
2669  * the time zone of @datetime.
2670  *
2671  * For example, in Toronto this is currently "EST" during the winter
2672  * months and "EDT" during the summer months when daylight savings
2673  * time is in effect.
2674  *
2675  * Returns: (transfer none): the time zone abbreviation. The returned
2676  *          string is owned by the #GDateTime and it should not be
2677  *          modified or freed
2678  *
2679  * Since: 2.26
2680  **/
2681 const gchar *
2682 g_date_time_get_timezone_abbreviation (GDateTime *datetime)
2683 {
2684   g_return_val_if_fail (datetime != NULL, NULL);
2685
2686   return g_time_zone_get_abbreviation (datetime->tz, datetime->interval);
2687 }
2688
2689 /**
2690  * g_date_time_is_daylight_savings:
2691  * @datetime: a #GDateTime
2692  *
2693  * Determines if daylight savings time is in effect at the time and in
2694  * the time zone of @datetime.
2695  *
2696  * Returns: %TRUE if daylight savings time is in effect
2697  *
2698  * Since: 2.26
2699  **/
2700 gboolean
2701 g_date_time_is_daylight_savings (GDateTime *datetime)
2702 {
2703   g_return_val_if_fail (datetime != NULL, FALSE);
2704
2705   return g_time_zone_is_dst (datetime->tz, datetime->interval);
2706 }
2707
2708 /* Timezone convert {{{1 */
2709 /**
2710  * g_date_time_to_timezone:
2711  * @datetime: a #GDateTime
2712  * @tz: the new #GTimeZone
2713  *
2714  * Create a new #GDateTime corresponding to the same instant in time as
2715  * @datetime, but in the time zone @tz.
2716  *
2717  * This call can fail in the case that the time goes out of bounds.  For
2718  * example, converting 0001-01-01 00:00:00 UTC to a time zone west of
2719  * Greenwich will fail (due to the year 0 being out of range).
2720  *
2721  * Returns: (transfer full) (nullable): the newly created #GDateTime which
2722  *   should be freed with g_date_time_unref(), or %NULL
2723  *
2724  * Since: 2.26
2725  **/
2726 GDateTime *
2727 g_date_time_to_timezone (GDateTime *datetime,
2728                          GTimeZone *tz)
2729 {
2730   g_return_val_if_fail (datetime != NULL, NULL);
2731   g_return_val_if_fail (tz != NULL, NULL);
2732
2733   return g_date_time_from_instant (tz, g_date_time_to_instant (datetime));
2734 }
2735
2736 /**
2737  * g_date_time_to_local:
2738  * @datetime: a #GDateTime
2739  *
2740  * Creates a new #GDateTime corresponding to the same instant in time as
2741  * @datetime, but in the local time zone.
2742  *
2743  * This call is equivalent to calling g_date_time_to_timezone() with the
2744  * time zone returned by g_time_zone_new_local().
2745  *
2746  * Returns: (transfer full) (nullable): the newly created #GDateTime which
2747  *   should be freed with g_date_time_unref(), or %NULL
2748  *
2749  * Since: 2.26
2750  **/
2751 GDateTime *
2752 g_date_time_to_local (GDateTime *datetime)
2753 {
2754   GDateTime *new;
2755   GTimeZone *local;
2756
2757   local = g_time_zone_new_local ();
2758   new = g_date_time_to_timezone (datetime, local);
2759   g_time_zone_unref (local);
2760
2761   return new;
2762 }
2763
2764 /**
2765  * g_date_time_to_utc:
2766  * @datetime: a #GDateTime
2767  *
2768  * Creates a new #GDateTime corresponding to the same instant in time as
2769  * @datetime, but in UTC.
2770  *
2771  * This call is equivalent to calling g_date_time_to_timezone() with the
2772  * time zone returned by g_time_zone_new_utc().
2773  *
2774  * Returns: (transfer full) (nullable): the newly created #GDateTime which
2775  *   should be freed with g_date_time_unref(), or %NULL
2776  *
2777  * Since: 2.26
2778  **/
2779 GDateTime *
2780 g_date_time_to_utc (GDateTime *datetime)
2781 {
2782   GDateTime *new;
2783   GTimeZone *utc;
2784
2785   utc = g_time_zone_new_utc ();
2786   new = g_date_time_to_timezone (datetime, utc);
2787   g_time_zone_unref (utc);
2788
2789   return new;
2790 }
2791
2792 /* Format {{{1 */
2793
2794 static gboolean
2795 format_z (GString *outstr,
2796           gint     offset,
2797           guint    colons)
2798 {
2799   gint hours;
2800   gint minutes;
2801   gint seconds;
2802   gchar sign = offset >= 0 ? '+' : '-';
2803
2804   offset = ABS (offset);
2805   hours = offset / 3600;
2806   minutes = offset / 60 % 60;
2807   seconds = offset % 60;
2808
2809   switch (colons)
2810     {
2811     case 0:
2812       g_string_append_printf (outstr, "%c%02d%02d",
2813                               sign,
2814                               hours,
2815                               minutes);
2816       break;
2817
2818     case 1:
2819       g_string_append_printf (outstr, "%c%02d:%02d",
2820                               sign,
2821                               hours,
2822                               minutes);
2823       break;
2824
2825     case 2:
2826       g_string_append_printf (outstr, "%c%02d:%02d:%02d",
2827                               sign,
2828                               hours,
2829                               minutes,
2830                               seconds);
2831       break;
2832
2833     case 3:
2834       g_string_append_printf (outstr, "%c%02d", sign, hours);
2835
2836       if (minutes != 0 || seconds != 0)
2837         {
2838           g_string_append_printf (outstr, ":%02d", minutes);
2839
2840           if (seconds != 0)
2841             g_string_append_printf (outstr, ":%02d", seconds);
2842         }
2843       break;
2844
2845     default:
2846       return FALSE;
2847     }
2848
2849   return TRUE;
2850 }
2851
2852 #ifdef HAVE_LANGINFO_OUTDIGIT
2853 /* Initializes the array with UTF-8 encoded alternate digits suitable for use
2854  * in current locale. Returns NULL when current locale does not use alternate
2855  * digits or there was an error converting them to UTF-8.
2856  */
2857 static const gchar * const *
2858 initialize_alt_digits (void)
2859 {
2860   guint i;
2861   gsize digit_len;
2862   gchar *digit;
2863   const gchar *locale_digit;
2864 #define N_DIGITS 10
2865 #define MAX_UTF8_ENCODING_LEN 4
2866   static gchar buffer[N_DIGITS * (MAX_UTF8_ENCODING_LEN + 1 /* null separator */)];
2867 #undef N_DIGITS
2868 #undef MAX_UTF8_ENCODING_LEN
2869   gchar *buffer_end = buffer;
2870   static const gchar *alt_digits[10];
2871
2872   for (i = 0; i != 10; ++i)
2873     {
2874       locale_digit = nl_langinfo (_NL_CTYPE_OUTDIGIT0_MB + i);
2875
2876       if (g_strcmp0 (locale_digit, "") == 0)
2877         return NULL;
2878
2879       digit = _g_ctype_locale_to_utf8 (locale_digit, -1, NULL, &digit_len, NULL);
2880       if (digit == NULL)
2881         return NULL;
2882
2883       g_assert (digit_len < (gsize) (buffer + sizeof (buffer) - buffer_end));
2884
2885       alt_digits[i] = buffer_end;
2886       buffer_end = g_stpcpy (buffer_end, digit);
2887       /* skip trailing null byte */
2888       buffer_end += 1;
2889
2890       g_free (digit);
2891     }
2892
2893   return alt_digits;
2894 }
2895 #endif /* HAVE_LANGINFO_OUTDIGIT */
2896
2897 static void
2898 format_number (GString     *str,
2899                gboolean     use_alt_digits,
2900                const gchar *pad,
2901                gint         width,
2902                guint32      number)
2903 {
2904   const gchar *ascii_digits[10] = {
2905     "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
2906   };
2907   const gchar * const *digits = ascii_digits;
2908   const gchar *tmp[10];
2909   gint i = 0;
2910
2911   g_return_if_fail (width <= 10);
2912
2913 #ifdef HAVE_LANGINFO_OUTDIGIT
2914   if (use_alt_digits)
2915     {
2916       static const gchar * const *alt_digits = NULL;
2917       static gsize initialised;
2918
2919       if G_UNLIKELY (g_once_init_enter (&initialised))
2920         {
2921           alt_digits = initialize_alt_digits ();
2922
2923           if (alt_digits == NULL)
2924             alt_digits = ascii_digits;
2925
2926           g_once_init_leave (&initialised, TRUE);
2927         }
2928
2929       digits = alt_digits;
2930     }
2931 #endif /* HAVE_LANGINFO_OUTDIGIT */
2932
2933   do
2934     {
2935       tmp[i++] = digits[number % 10];
2936       number /= 10;
2937     }
2938   while (number);
2939
2940   while (pad && i < width)
2941     tmp[i++] = *pad == '0' ? digits[0] : pad;
2942
2943   /* should really be impossible */
2944   g_assert (i <= 10);
2945
2946   while (i)
2947     g_string_append (str, tmp[--i]);
2948 }
2949
2950 static gboolean
2951 format_ampm (GDateTime *datetime,
2952              GString   *outstr,
2953              gboolean   locale_is_utf8,
2954              gboolean   uppercase)
2955 {
2956   const gchar *ampm;
2957   gchar       *tmp = NULL, *ampm_dup;
2958
2959   ampm = GET_AMPM (datetime);
2960
2961   if (!ampm || ampm[0] == '\0')
2962     ampm = get_fallback_ampm (g_date_time_get_hour (datetime));
2963
2964   if (!locale_is_utf8 && GET_AMPM_IS_LOCALE)
2965     {
2966       /* This assumes that locale encoding can't have embedded NULs */
2967       ampm = tmp = g_locale_to_utf8 (ampm, -1, NULL, NULL, NULL);
2968       if (tmp == NULL)
2969         return FALSE;
2970     }
2971   if (uppercase)
2972     ampm_dup = g_utf8_strup (ampm, -1);
2973   else
2974     ampm_dup = g_utf8_strdown (ampm, -1);
2975   g_free (tmp);
2976
2977   g_string_append (outstr, ampm_dup);
2978   g_free (ampm_dup);
2979
2980   return TRUE;
2981 }
2982
2983 static gboolean g_date_time_format_utf8 (GDateTime   *datetime,
2984                                          const gchar *format,
2985                                          GString     *outstr,
2986                                          gboolean     locale_is_utf8);
2987
2988 /* g_date_time_format() subroutine that takes a locale-encoded format
2989  * string and produces a UTF-8 encoded date/time string.
2990  */
2991 static gboolean
2992 g_date_time_format_locale (GDateTime   *datetime,
2993                            const gchar *locale_format,
2994                            GString     *outstr,
2995                            gboolean     locale_is_utf8)
2996 {
2997   gchar *utf8_format;
2998   gboolean success;
2999
3000   if (locale_is_utf8)
3001     return g_date_time_format_utf8 (datetime, locale_format, outstr, locale_is_utf8);
3002
3003   utf8_format = _g_time_locale_to_utf8 (locale_format, -1, NULL, NULL, NULL);
3004   if (utf8_format == NULL)
3005     return FALSE;
3006
3007   success = g_date_time_format_utf8 (datetime, utf8_format, outstr,
3008                                      locale_is_utf8);
3009   g_free (utf8_format);
3010   return success;
3011 }
3012
3013 static inline gboolean
3014 string_append (GString     *string,
3015                const gchar *s,
3016                gboolean     s_is_utf8)
3017 {
3018   gchar *utf8;
3019   gsize  utf8_len;
3020
3021   if (s_is_utf8)
3022     {
3023       g_string_append (string, s);
3024     }
3025   else
3026     {
3027       utf8 = _g_time_locale_to_utf8 (s, -1, NULL, &utf8_len, NULL);
3028       if (utf8 == NULL)
3029         return FALSE;
3030       g_string_append_len (string, utf8, utf8_len);
3031       g_free (utf8);
3032     }
3033
3034   return TRUE;
3035 }
3036
3037 /* g_date_time_format() subroutine that takes a UTF-8 encoded format
3038  * string and produces a UTF-8 encoded date/time string.
3039  */
3040 static gboolean
3041 g_date_time_format_utf8 (GDateTime   *datetime,
3042                          const gchar *utf8_format,
3043                          GString     *outstr,
3044                          gboolean     locale_is_utf8)
3045 {
3046   guint     len;
3047   guint     colons;
3048   gunichar  c;
3049   gboolean  alt_digits = FALSE;
3050   gboolean  pad_set = FALSE;
3051   gboolean  name_is_utf8;
3052   const gchar *pad = "";
3053   const gchar *name;
3054   const gchar *tz;
3055
3056   while (*utf8_format)
3057     {
3058       len = strcspn (utf8_format, "%");
3059       if (len)
3060         g_string_append_len (outstr, utf8_format, len);
3061
3062       utf8_format += len;
3063       if (!*utf8_format)
3064         break;
3065
3066       g_assert (*utf8_format == '%');
3067       utf8_format++;
3068       if (!*utf8_format)
3069         break;
3070
3071       colons = 0;
3072       alt_digits = FALSE;
3073       pad_set = FALSE;
3074
3075     next_mod:
3076       c = g_utf8_get_char (utf8_format);
3077       utf8_format = g_utf8_next_char (utf8_format);
3078       switch (c)
3079         {
3080         case 'a':
3081           name = WEEKDAY_ABBR (datetime);
3082           if (g_strcmp0 (name, "") == 0)
3083             return FALSE;
3084
3085           name_is_utf8 = locale_is_utf8 || !WEEKDAY_ABBR_IS_LOCALE;
3086
3087           if (!string_append (outstr, name, name_is_utf8))
3088             return FALSE;
3089
3090           break;
3091         case 'A':
3092           name = WEEKDAY_FULL (datetime);
3093           if (g_strcmp0 (name, "") == 0)
3094             return FALSE;
3095
3096           name_is_utf8 = locale_is_utf8 || !WEEKDAY_FULL_IS_LOCALE;
3097
3098           if (!string_append (outstr, name, name_is_utf8))
3099             return FALSE;
3100
3101           break;
3102         case 'b':
3103           name = alt_digits ? MONTH_ABBR_STANDALONE (datetime)
3104                             : MONTH_ABBR_WITH_DAY (datetime);
3105           if (g_strcmp0 (name, "") == 0)
3106             return FALSE;
3107
3108           name_is_utf8 = locale_is_utf8 ||
3109             ((alt_digits && !MONTH_ABBR_STANDALONE_IS_LOCALE) ||
3110              (!alt_digits && !MONTH_ABBR_WITH_DAY_IS_LOCALE));
3111
3112           if (!string_append (outstr, name, name_is_utf8))
3113             return FALSE;
3114
3115           break;
3116         case 'B':
3117           name = alt_digits ? MONTH_FULL_STANDALONE (datetime)
3118                             : MONTH_FULL_WITH_DAY (datetime);
3119           if (g_strcmp0 (name, "") == 0)
3120             return FALSE;
3121
3122           name_is_utf8 = locale_is_utf8 ||
3123             ((alt_digits && !MONTH_FULL_STANDALONE_IS_LOCALE) ||
3124              (!alt_digits && !MONTH_FULL_WITH_DAY_IS_LOCALE));
3125
3126           if (!string_append (outstr, name, name_is_utf8))
3127               return FALSE;
3128
3129           break;
3130         case 'c':
3131           {
3132             if (g_strcmp0 (PREFERRED_DATE_TIME_FMT, "") == 0)
3133               return FALSE;
3134             if (!g_date_time_format_locale (datetime, PREFERRED_DATE_TIME_FMT,
3135                                             outstr, locale_is_utf8))
3136               return FALSE;
3137           }
3138           break;
3139         case 'C':
3140           format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
3141                          g_date_time_get_year (datetime) / 100);
3142           break;
3143         case 'd':
3144           format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
3145                          g_date_time_get_day_of_month (datetime));
3146           break;
3147         case 'e':
3148           format_number (outstr, alt_digits, pad_set ? pad : "\u2007", 2,
3149                          g_date_time_get_day_of_month (datetime));
3150           break;
3151         case 'f':
3152           g_string_append_printf (outstr, "%06" G_GUINT64_FORMAT,
3153                         datetime->usec % G_TIME_SPAN_SECOND);
3154           break;
3155         case 'F':
3156           g_string_append_printf (outstr, "%d-%02d-%02d",
3157                                   g_date_time_get_year (datetime),
3158                                   g_date_time_get_month (datetime),
3159                                   g_date_time_get_day_of_month (datetime));
3160           break;
3161         case 'g':
3162           format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
3163                          g_date_time_get_week_numbering_year (datetime) % 100);
3164           break;
3165         case 'G':
3166           format_number (outstr, alt_digits, pad_set ? pad : 0, 0,
3167                          g_date_time_get_week_numbering_year (datetime));
3168           break;
3169         case 'h':
3170           name = alt_digits ? MONTH_ABBR_STANDALONE (datetime)
3171                             : MONTH_ABBR_WITH_DAY (datetime);
3172           if (g_strcmp0 (name, "") == 0)
3173             return FALSE;
3174
3175           name_is_utf8 = locale_is_utf8 ||
3176             ((alt_digits && !MONTH_ABBR_STANDALONE_IS_LOCALE) ||
3177              (!alt_digits && !MONTH_ABBR_WITH_DAY_IS_LOCALE));
3178
3179           if (!string_append (outstr, name, name_is_utf8))
3180             return FALSE;
3181
3182           break;
3183         case 'H':
3184           format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
3185                          g_date_time_get_hour (datetime));
3186           break;
3187         case 'I':
3188           format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
3189                          (g_date_time_get_hour (datetime) + 11) % 12 + 1);
3190           break;
3191         case 'j':
3192           format_number (outstr, alt_digits, pad_set ? pad : "0", 3,
3193                          g_date_time_get_day_of_year (datetime));
3194           break;
3195         case 'k':
3196           format_number (outstr, alt_digits, pad_set ? pad : "\u2007", 2,
3197                          g_date_time_get_hour (datetime));
3198           break;
3199         case 'l':
3200           format_number (outstr, alt_digits, pad_set ? pad : "\u2007", 2,
3201                          (g_date_time_get_hour (datetime) + 11) % 12 + 1);
3202           break;
3203         case 'm':
3204           format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
3205                          g_date_time_get_month (datetime));
3206           break;
3207         case 'M':
3208           format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
3209                          g_date_time_get_minute (datetime));
3210           break;
3211         case 'n':
3212           g_string_append_c (outstr, '\n');
3213           break;
3214         case 'O':
3215           alt_digits = TRUE;
3216           goto next_mod;
3217         case 'p':
3218           if (!format_ampm (datetime, outstr, locale_is_utf8, TRUE))
3219             return FALSE;
3220           break;
3221         case 'P':
3222           if (!format_ampm (datetime, outstr, locale_is_utf8, FALSE))
3223             return FALSE;
3224           break;
3225         case 'r':
3226           {
3227             if (g_strcmp0 (PREFERRED_12HR_TIME_FMT, "") == 0)
3228               return FALSE;
3229             if (!g_date_time_format_locale (datetime, PREFERRED_12HR_TIME_FMT,
3230                                             outstr, locale_is_utf8))
3231               return FALSE;
3232           }
3233           break;
3234         case 'R':
3235           g_string_append_printf (outstr, "%02d:%02d",
3236                                   g_date_time_get_hour (datetime),
3237                                   g_date_time_get_minute (datetime));
3238           break;
3239         case 's':
3240           g_string_append_printf (outstr, "%" G_GINT64_FORMAT, g_date_time_to_unix (datetime));
3241           break;
3242         case 'S':
3243           format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
3244                          g_date_time_get_second (datetime));
3245           break;
3246         case 't':
3247           g_string_append_c (outstr, '\t');
3248           break;
3249         case 'T':
3250           g_string_append_printf (outstr, "%02d:%02d:%02d",
3251                                   g_date_time_get_hour (datetime),
3252                                   g_date_time_get_minute (datetime),
3253                                   g_date_time_get_second (datetime));
3254           break;
3255         case 'u':
3256           format_number (outstr, alt_digits, 0, 0,
3257                          g_date_time_get_day_of_week (datetime));
3258           break;
3259         case 'V':
3260           format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
3261                          g_date_time_get_week_of_year (datetime));
3262           break;
3263         case 'w':
3264           format_number (outstr, alt_digits, 0, 0,
3265                          g_date_time_get_day_of_week (datetime) % 7);
3266           break;
3267         case 'x':
3268           {
3269             if (g_strcmp0 (PREFERRED_DATE_FMT, "") == 0)
3270               return FALSE;
3271             if (!g_date_time_format_locale (datetime, PREFERRED_DATE_FMT,
3272                                             outstr, locale_is_utf8))
3273               return FALSE;
3274           }
3275           break;
3276         case 'X':
3277           {
3278             if (g_strcmp0 (PREFERRED_TIME_FMT, "") == 0)
3279               return FALSE;
3280             if (!g_date_time_format_locale (datetime, PREFERRED_TIME_FMT,
3281                                             outstr, locale_is_utf8))
3282               return FALSE;
3283           }
3284           break;
3285         case 'y':
3286           format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
3287                          g_date_time_get_year (datetime) % 100);
3288           break;
3289         case 'Y':
3290           format_number (outstr, alt_digits, 0, 0,
3291                          g_date_time_get_year (datetime));
3292           break;
3293         case 'z':
3294           {
3295             gint64 offset;
3296             offset = g_date_time_get_utc_offset (datetime) / USEC_PER_SECOND;
3297             if (!format_z (outstr, (int) offset, colons))
3298               return FALSE;
3299           }
3300           break;
3301         case 'Z':
3302           tz = g_date_time_get_timezone_abbreviation (datetime);
3303           g_string_append (outstr, tz);
3304           break;
3305         case '%':
3306           g_string_append_c (outstr, '%');
3307           break;
3308         case '-':
3309           pad_set = TRUE;
3310           pad = "";
3311           goto next_mod;
3312         case '_':
3313           pad_set = TRUE;
3314           pad = " ";
3315           goto next_mod;
3316         case '0':
3317           pad_set = TRUE;
3318           pad = "0";
3319           goto next_mod;
3320         case ':':
3321           /* Colons are only allowed before 'z' */
3322           if (*utf8_format && *utf8_format != 'z' && *utf8_format != ':')
3323             return FALSE;
3324           colons++;
3325           goto next_mod;
3326         default:
3327           return FALSE;
3328         }
3329     }
3330
3331   return TRUE;
3332 }
3333
3334 /**
3335  * g_date_time_format:
3336  * @datetime: A #GDateTime
3337  * @format: a valid UTF-8 string, containing the format for the
3338  *          #GDateTime
3339  *
3340  * Creates a newly allocated string representing the requested @format.
3341  *
3342  * The format strings understood by this function are a subset of the
3343  * `strftime()` format language as specified by C99.  The `%D`, `%U` and `%W`
3344  * conversions are not supported, nor is the `E` modifier.  The GNU
3345  * extensions `%k`, `%l`, `%s` and `%P` are supported, however, as are the
3346  * `0`, `_` and `-` modifiers. The Python extension `%f` is also supported.
3347  *
3348  * In contrast to `strftime()`, this function always produces a UTF-8
3349  * string, regardless of the current locale.  Note that the rendering of
3350  * many formats is locale-dependent and may not match the `strftime()`
3351  * output exactly.
3352  *
3353  * The following format specifiers are supported:
3354  *
3355  * - `%a`: the abbreviated weekday name according to the current locale
3356  * - `%A`: the full weekday name according to the current locale
3357  * - `%b`: the abbreviated month name according to the current locale
3358  * - `%B`: the full month name according to the current locale
3359  * - `%c`: the preferred date and time representation for the current locale
3360  * - `%C`: the century number (year/100) as a 2-digit integer (00-99)
3361  * - `%d`: the day of the month as a decimal number (range 01 to 31)
3362  * - `%e`: the day of the month as a decimal number (range 1 to 31);
3363  *   single digits are preceded by a figure space (U+2007)
3364  * - `%F`: equivalent to `%Y-%m-%d` (the ISO 8601 date format)
3365  * - `%g`: the last two digits of the ISO 8601 week-based year as a
3366  *   decimal number (00-99). This works well with `%V` and `%u`.
3367  * - `%G`: the ISO 8601 week-based year as a decimal number. This works
3368  *   well with `%V` and `%u`.
3369  * - `%h`: equivalent to `%b`
3370  * - `%H`: the hour as a decimal number using a 24-hour clock (range 00 to 23)
3371  * - `%I`: the hour as a decimal number using a 12-hour clock (range 01 to 12)
3372  * - `%j`: the day of the year as a decimal number (range 001 to 366)
3373  * - `%k`: the hour (24-hour clock) as a decimal number (range 0 to 23);
3374  *   single digits are preceded by a figure space (U+2007)
3375  * - `%l`: the hour (12-hour clock) as a decimal number (range 1 to 12);
3376  *   single digits are preceded by a figure space (U+2007)
3377  * - `%m`: the month as a decimal number (range 01 to 12)
3378  * - `%M`: the minute as a decimal number (range 00 to 59)
3379  * - `%f`: the microsecond as a decimal number (range 000000 to 999999)
3380  * - `%p`: either ‘AM’ or ‘PM’ according to the given time value, or the
3381  *   corresponding  strings for the current locale.  Noon is treated as
3382  *   ‘PM’ and midnight as ‘AM’. Use of this format specifier is discouraged, as
3383  *   many locales have no concept of AM/PM formatting. Use `%c` or `%X` instead.
3384  * - `%P`: like `%p` but lowercase: ‘am’ or ‘pm’ or a corresponding string for
3385  *   the current locale. Use of this format specifier is discouraged, as
3386  *   many locales have no concept of AM/PM formatting. Use `%c` or `%X` instead.
3387  * - `%r`: the time in a.m. or p.m. notation. Use of this format specifier is
3388  *   discouraged, as many locales have no concept of AM/PM formatting. Use `%c`
3389  *   or `%X` instead.
3390  * - `%R`: the time in 24-hour notation (`%H:%M`)
3391  * - `%s`: the number of seconds since the Epoch, that is, since 1970-01-01
3392  *   00:00:00 UTC
3393  * - `%S`: the second as a decimal number (range 00 to 60)
3394  * - `%t`: a tab character
3395  * - `%T`: the time in 24-hour notation with seconds (`%H:%M:%S`)
3396  * - `%u`: the ISO 8601 standard day of the week as a decimal, range 1 to 7,
3397  *    Monday being 1. This works well with `%G` and `%V`.
3398  * - `%V`: the ISO 8601 standard week number of the current year as a decimal
3399  *   number, range 01 to 53, where week 1 is the first week that has at
3400  *   least 4 days in the new year. See g_date_time_get_week_of_year().
3401  *   This works well with `%G` and `%u`.
3402  * - `%w`: the day of the week as a decimal, range 0 to 6, Sunday being 0.
3403  *   This is not the ISO 8601 standard format — use `%u` instead.
3404  * - `%x`: the preferred date representation for the current locale without
3405  *   the time
3406  * - `%X`: the preferred time representation for the current locale without
3407  *   the date
3408  * - `%y`: the year as a decimal number without the century
3409  * - `%Y`: the year as a decimal number including the century
3410  * - `%z`: the time zone as an offset from UTC (`+hhmm`)
3411  * - `%:z`: the time zone as an offset from UTC (`+hh:mm`).
3412  *   This is a gnulib `strftime()` extension. Since: 2.38
3413  * - `%::z`: the time zone as an offset from UTC (`+hh:mm:ss`). This is a
3414  *   gnulib `strftime()` extension. Since: 2.38
3415  * - `%:::z`: the time zone as an offset from UTC, with `:` to necessary
3416  *   precision (e.g., `-04`, `+05:30`). This is a gnulib `strftime()` extension. Since: 2.38
3417  * - `%Z`: the time zone or name or abbreviation
3418  * - `%%`: a literal `%` character
3419  *
3420  * Some conversion specifications can be modified by preceding the
3421  * conversion specifier by one or more modifier characters. The
3422  * following modifiers are supported for many of the numeric
3423  * conversions:
3424  *
3425  * - `O`: Use alternative numeric symbols, if the current locale supports those.
3426  * - `_`: Pad a numeric result with spaces. This overrides the default padding
3427  *   for the specifier.
3428  * - `-`: Do not pad a numeric result. This overrides the default padding
3429  *   for the specifier.
3430  * - `0`: Pad a numeric result with zeros. This overrides the default padding
3431  *   for the specifier.
3432  *
3433  * Additionally, when `O` is used with `B`, `b`, or `h`, it produces the alternative
3434  * form of a month name. The alternative form should be used when the month
3435  * name is used without a day number (e.g., standalone). It is required in
3436  * some languages (Baltic, Slavic, Greek, and more) due to their grammatical
3437  * rules. For other languages there is no difference. `%OB` is a GNU and BSD
3438  * `strftime()` extension expected to be added to the future POSIX specification,
3439  * `%Ob` and `%Oh` are GNU `strftime()` extensions. Since: 2.56
3440  *
3441  * Returns: (transfer full) (nullable): a newly allocated string formatted to
3442  *    the requested format or %NULL in the case that there was an error (such
3443  *    as a format specifier not being supported in the current locale). The
3444  *    string should be freed with g_free().
3445  *
3446  * Since: 2.26
3447  */
3448 gchar *
3449 g_date_time_format (GDateTime   *datetime,
3450                     const gchar *format)
3451 {
3452   GString  *outstr;
3453   const gchar *charset;
3454   /* Avoid conversions from locale (for LC_TIME and not for LC_MESSAGES unless
3455    * specified otherwise) charset to UTF-8 if charset is compatible
3456    * with UTF-8 already. Check for UTF-8 and synonymous canonical names of
3457    * ASCII. */
3458   gboolean time_is_utf8_compatible = _g_get_time_charset (&charset) ||
3459     g_strcmp0 ("ASCII", charset) == 0 ||
3460     g_strcmp0 ("ANSI_X3.4-1968", charset) == 0;
3461
3462   g_return_val_if_fail (datetime != NULL, NULL);
3463   g_return_val_if_fail (format != NULL, NULL);
3464   g_return_val_if_fail (g_utf8_validate (format, -1, NULL), NULL);
3465
3466   outstr = g_string_sized_new (strlen (format) * 2);
3467
3468   if (!g_date_time_format_utf8 (datetime, format, outstr,
3469                                 time_is_utf8_compatible))
3470     {
3471       g_string_free (outstr, TRUE);
3472       return NULL;
3473     }
3474
3475   return g_string_free (outstr, FALSE);
3476 }
3477
3478 /**
3479  * g_date_time_format_iso8601:
3480  * @datetime: A #GDateTime
3481  *
3482  * Format @datetime in [ISO 8601 format](https://en.wikipedia.org/wiki/ISO_8601),
3483  * including the date, time and time zone, and return that as a UTF-8 encoded
3484  * string.
3485  *
3486  * Since GLib 2.66, this will output to sub-second precision if needed.
3487  *
3488  * Returns: (transfer full) (nullable): a newly allocated string formatted in
3489  *   ISO 8601 format or %NULL in the case that there was an error. The string
3490  *   should be freed with g_free().
3491  *
3492  * Since: 2.62
3493  */
3494 gchar *
3495 g_date_time_format_iso8601 (GDateTime *datetime)
3496 {
3497   GString *outstr = NULL;
3498   gchar *main_date = NULL;
3499   gint64 offset;
3500   gchar *format = "%C%y-%m-%dT%H:%M:%S";
3501
3502   g_return_val_if_fail (datetime != NULL, NULL);
3503
3504   /* if datetime has sub-second non-zero values below the second precision we
3505    * should print them as well */
3506   if (datetime->usec % G_TIME_SPAN_SECOND != 0)
3507     format = "%C%y-%m-%dT%H:%M:%S.%f";
3508
3509   /* Main date and time. */
3510   main_date = g_date_time_format (datetime, format);
3511   outstr = g_string_new (main_date);
3512   g_free (main_date);
3513
3514   /* Timezone. Format it as `%:::z` unless the offset is zero, in which case
3515    * we can simply use `Z`. */
3516   offset = g_date_time_get_utc_offset (datetime);
3517
3518   if (offset == 0)
3519     {
3520       g_string_append_c (outstr, 'Z');
3521     }
3522   else
3523     {
3524       gchar *time_zone = g_date_time_format (datetime, "%:::z");
3525       g_string_append (outstr, time_zone);
3526       g_free (time_zone);
3527     }
3528
3529   return g_string_free (outstr, FALSE);
3530 }
3531
3532
3533 /* Epilogue {{{1 */
3534 /* vim:set foldmethod=marker: */