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