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