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