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