GDateTime test: 1970 doesn't exist on Windows
[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 #include "gdatetime.h"
58
59 #include "gatomic.h"
60 #include "gfileutils.h"
61 #include "ghash.h"
62 #include "gmain.h"
63 #include "gmappedfile.h"
64 #include "gstrfuncs.h"
65 #include "gtestutils.h"
66 #include "gthread.h"
67 #include "gtimezone.h"
68
69 #include "glibintl.h"
70
71 #ifndef G_OS_WIN32
72 #include <sys/time.h>
73 #include <time.h>
74 #endif /* !G_OS_WIN32 */
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 > G_GINT64_CONSTANT (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  * A comparison function for #GDateTimes that is suitable
1320  * as a #GCompareFunc. Both #GDateTimes must be non-%NULL.
1321  *
1322  * Return value: -1, 0 or 1 if @dt1 is less than, equal to or greater
1323  *   than @dt2.
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 month 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_numbering_year:
1587  * @datetime: a #GDateTime
1588  *
1589  * Returns the ISO 8601 week-numbering year in which the week containing
1590  * @datetime falls.
1591  *
1592  * This function, taken together with g_date_time_get_week_of_year() and
1593  * g_date_time_get_day_of_week() can be used to determine the full ISO
1594  * week date on which @datetime falls.
1595  *
1596  * This is usually equal to the normal Gregorian year (as returned by
1597  * g_date_time_get_year()), except as detailed below:
1598  *
1599  * For Thursday, the week-numbering year is always equal to the usual
1600  * calendar year.  For other days, the number is such that every day
1601  * within a complete week (Monday to Sunday) is contained within the
1602  * same week-numbering year.
1603  *
1604  * For Monday, Tuesday and Wednesday occuring near the end of the year,
1605  * this may mean that the week-numbering year is one greater than the
1606  * calendar year (so that these days have the same week-numbering year
1607  * as the Thursday occuring early in the next year).
1608  *
1609  * For Friday, Saturaday and Sunday occuring near the start of the year,
1610  * this may mean that the week-numbering year is one less than the
1611  * calendar year (so that these days have the same week-numbering year
1612  * as the Thursday occuring late in the previous year).
1613  *
1614  * An equivalent description is that the week-numbering year is equal to
1615  * the calendar year containing the majority of the days in the current
1616  * week (Monday to Sunday).
1617  *
1618  * Note that January 1 0001 in the proleptic Gregorian calendar is a
1619  * Monday, so this function never returns 0.
1620  *
1621  * Returns: the ISO 8601 week-numbering year for @datetime
1622  *
1623  * Since: 2.26
1624  **/
1625 gint
1626 g_date_time_get_week_numbering_year (GDateTime *datetime)
1627 {
1628   gint year, month, day, weekday;
1629
1630   g_date_time_get_ymd (datetime, &year, &month, &day);
1631   weekday = g_date_time_get_day_of_week (datetime);
1632
1633   /* January 1, 2, 3 might be in the previous year if they occur after
1634    * Thursday.
1635    *
1636    *   Jan 1:  Friday, Saturday, Sunday    =>  day 1:  weekday 5, 6, 7
1637    *   Jan 2:  Saturday, Sunday            =>  day 2:  weekday 6, 7
1638    *   Jan 3:  Sunday                      =>  day 3:  weekday 7
1639    *
1640    * So we have a special case if (day - weekday) <= -4
1641    */
1642   if (month == 1 && (day - weekday) <= -4)
1643     return year - 1;
1644
1645   /* December 29, 30, 31 might be in the next year if they occur before
1646    * Thursday.
1647    *
1648    *   Dec 31: Monday, Tuesday, Wednesday  =>  day 31: weekday 1, 2, 3
1649    *   Dec 30: Monday, Tuesday             =>  day 30: weekday 1, 2
1650    *   Dec 29: Monday                      =>  day 29: weekday 1
1651    *
1652    * So we have a special case if (day - weekday) >= 28
1653    */
1654   else if (month == 12 && (day - weekday) >= 28)
1655     return year + 1;
1656
1657   else
1658     return year;
1659 }
1660
1661 /**
1662  * g_date_time_get_week_of_year:
1663  * @datetime: a #GDateTime
1664  *
1665  * Returns the ISO 8601 week number for the week containing @datetime.
1666  * The ISO 8601 week number is the same for every day of the week (from
1667  * Moday through Sunday).  That can produce some unusual results
1668  * (described below).
1669  *
1670  * The first week of the year is week 1.  This is the week that contains
1671  * the first Thursday of the year.  Equivalently, this is the first week
1672  * that has more than 4 of its days falling within the calendar year.
1673  *
1674  * The value 0 is never returned by this function.  Days contained
1675  * within a year but occuring before the first ISO 8601 week of that
1676  * year are considered as being contained in the last week of the
1677  * previous year.  Similarly, the final days of a calendar year may be
1678  * considered as being part of the first ISO 8601 week of the next year
1679  * if 4 or more days of that week are contained within the new year.
1680  *
1681  * Returns: the ISO 8601 week number for @datetime.
1682  *
1683  * Since: 2.26
1684  */
1685 gint
1686 g_date_time_get_week_of_year (GDateTime *datetime)
1687 {
1688   gint weeknum;
1689
1690   g_return_val_if_fail (datetime != NULL, 0);
1691
1692   g_date_time_get_week_number (datetime, &weeknum, NULL, NULL);
1693
1694   return weeknum;
1695 }
1696
1697 /**
1698  * g_date_time_get_day_of_week:
1699  * @datetime: a #GDateTime
1700  *
1701  * Retrieves the ISO 8601 day of the week on which @datetime falls (1 is
1702  * Monday, 2 is Tuesday... 7 is Sunday).
1703  *
1704  * Return value: the day of the week
1705  *
1706  * Since: 2.26
1707  */
1708 gint
1709 g_date_time_get_day_of_week (GDateTime *datetime)
1710 {
1711   g_return_val_if_fail (datetime != NULL, 0);
1712
1713   return (datetime->days - 1) % 7 + 1;
1714 }
1715
1716 /* Day of year getter {{{1 */
1717 /**
1718  * g_date_time_get_day_of_year:
1719  * @datetime: a #GDateTime
1720  *
1721  * Retrieves the day of the year represented by @datetime in the Gregorian
1722  * calendar.
1723  *
1724  * Return value: the day of the year
1725  *
1726  * Since: 2.26
1727  */
1728 gint
1729 g_date_time_get_day_of_year (GDateTime *datetime)
1730 {
1731   gint doy = 0;
1732
1733   g_return_val_if_fail (datetime != NULL, 0);
1734
1735   g_date_time_get_week_number (datetime, NULL, NULL, &doy);
1736   return doy;
1737 }
1738
1739 /* Time component getters {{{1 */
1740
1741 /**
1742  * g_date_time_get_hour:
1743  * @datetime: a #GDateTime
1744  *
1745  * Retrieves the hour of the day represented by @datetime
1746  *
1747  * Return value: the hour of the day
1748  *
1749  * Since: 2.26
1750  */
1751 gint
1752 g_date_time_get_hour (GDateTime *datetime)
1753 {
1754   g_return_val_if_fail (datetime != NULL, 0);
1755
1756   return (datetime->usec / USEC_PER_HOUR);
1757 }
1758
1759 /**
1760  * g_date_time_get_minute:
1761  * @datetime: a #GDateTime
1762  *
1763  * Retrieves the minute of the hour represented by @datetime
1764  *
1765  * Return value: the minute of the hour
1766  *
1767  * Since: 2.26
1768  */
1769 gint
1770 g_date_time_get_minute (GDateTime *datetime)
1771 {
1772   g_return_val_if_fail (datetime != NULL, 0);
1773
1774   return (datetime->usec % USEC_PER_HOUR) / USEC_PER_MINUTE;
1775 }
1776
1777 /**
1778  * g_date_time_get_second:
1779  * @datetime: a #GDateTime
1780  *
1781  * Retrieves the second of the minute represented by @datetime
1782  *
1783  * Return value: the second represented by @datetime
1784  *
1785  * Since: 2.26
1786  */
1787 gint
1788 g_date_time_get_second (GDateTime *datetime)
1789 {
1790   g_return_val_if_fail (datetime != NULL, 0);
1791
1792   return (datetime->usec % USEC_PER_MINUTE) / USEC_PER_SECOND;
1793 }
1794
1795 /**
1796  * g_date_time_get_microsecond:
1797  * @datetime: a #GDateTime
1798  *
1799  * Retrieves the microsecond of the date represented by @datetime
1800  *
1801  * Return value: the microsecond of the second
1802  *
1803  * Since: 2.26
1804  */
1805 gint
1806 g_date_time_get_microsecond (GDateTime *datetime)
1807 {
1808   g_return_val_if_fail (datetime != NULL, 0);
1809
1810   return (datetime->usec % USEC_PER_SECOND);
1811 }
1812
1813 /**
1814  * g_date_time_get_seconds:
1815  * @datetime: a #GDateTime
1816  *
1817  * Retrieves the number of seconds since the start of the last minute,
1818  * including the fractional part.
1819  *
1820  * Returns: the number of seconds
1821  *
1822  * Since: 2.26
1823  **/
1824 gdouble
1825 g_date_time_get_seconds (GDateTime *datetime)
1826 {
1827   g_return_val_if_fail (datetime != NULL, 0);
1828
1829   return (datetime->usec % USEC_PER_MINUTE) / 1000000.0;
1830 }
1831
1832 /* Exporters {{{1 */
1833 /**
1834  * g_date_time_to_unix:
1835  * @datetime: a #GDateTime
1836  *
1837  * Gives the Unix time corresponding to @datetime, rounding down to the
1838  * nearest second.
1839  *
1840  * Unix time is the number of seconds that have elapsed since 1970-01-01
1841  * 00:00:00 UTC, regardless of the time zone associated with @datetime.
1842  *
1843  * Returns: the Unix time corresponding to @datetime
1844  *
1845  * Since: 2.26
1846  **/
1847 gint64
1848 g_date_time_to_unix (GDateTime *datetime)
1849 {
1850   return INSTANT_TO_UNIX (g_date_time_to_instant (datetime));
1851 }
1852
1853 /**
1854  * g_date_time_to_timeval:
1855  * @datetime: a #GDateTime
1856  * @tv: a #GTimeVal to modify
1857  *
1858  * Stores the instant in time that @datetime represents into @tv.
1859  *
1860  * The time contained in a #GTimeVal is always stored in the form of
1861  * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the time
1862  * zone associated with @datetime.
1863  *
1864  * On systems where 'long' is 32bit (ie: all 32bit systems and all
1865  * Windows systems), a #GTimeVal is incapable of storing the entire
1866  * range of values that #GDateTime is capable of expressing.  On those
1867  * systems, this function returns %FALSE to indicate that the time is
1868  * out of range.
1869  *
1870  * On systems where 'long' is 64bit, this function never fails.
1871  *
1872  * Returns: %TRUE if successful, else %FALSE
1873  *
1874  * Since: 2.26
1875  **/
1876 gboolean
1877 g_date_time_to_timeval (GDateTime *datetime,
1878                         GTimeVal  *tv)
1879 {
1880   tv->tv_sec = INSTANT_TO_UNIX (g_date_time_to_instant (datetime));
1881   tv->tv_usec = datetime->usec % USEC_PER_SECOND;
1882
1883   return TRUE;
1884 }
1885
1886 /* Timezone queries {{{1 */
1887 /**
1888  * g_date_time_get_utc_offset:
1889  * @datetime: a #GDateTime
1890  *
1891  * Determines the offset to UTC in effect at the time and in the time
1892  * zone of @datetime.
1893  *
1894  * The offset is the number of microseconds that you add to UTC time to
1895  * arrive at local time for the time zone (ie: negative numbers for time
1896  * zones west of GMT, positive numbers for east).
1897  *
1898  * If @datetime represents UTC time, then the offset is always zero.
1899  *
1900  * Returns: the number of microseconds that should be added to UTC to
1901  *          get the local time
1902  *
1903  * Since: 2.26
1904  **/
1905 GTimeSpan
1906 g_date_time_get_utc_offset (GDateTime *datetime)
1907 {
1908   gint offset;
1909
1910   g_return_val_if_fail (datetime != NULL, 0);
1911
1912   offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
1913
1914   return (gint64) offset * USEC_PER_SECOND;
1915 }
1916
1917 /**
1918  * g_date_time_get_timezone_abbreviation:
1919  * @datetime: a #GDateTime
1920  *
1921  * Determines the time zone abbreviation to be used at the time and in
1922  * the time zone of @datetime.
1923  *
1924  * For example, in Toronto this is currently "EST" during the winter
1925  * months and "EDT" during the summer months when daylight savings
1926  * time is in effect.
1927  *
1928  * Returns: (transfer none): the time zone abbreviation. The returned
1929  *          string is owned by the #GDateTime and it should not be
1930  *          modified or freed
1931  *
1932  * Since: 2.26
1933  **/
1934 const gchar *
1935 g_date_time_get_timezone_abbreviation (GDateTime *datetime)
1936 {
1937   g_return_val_if_fail (datetime != NULL, NULL);
1938
1939   return g_time_zone_get_abbreviation (datetime->tz, datetime->interval);
1940 }
1941
1942 /**
1943  * g_date_time_is_daylight_savings:
1944  * @datetime: a #GDateTime
1945  *
1946  * Determines if daylight savings time is in effect at the time and in
1947  * the time zone of @datetime.
1948  *
1949  * Returns: %TRUE if daylight savings time is in effect
1950  *
1951  * Since: 2.26
1952  **/
1953 gboolean
1954 g_date_time_is_daylight_savings (GDateTime *datetime)
1955 {
1956   g_return_val_if_fail (datetime != NULL, FALSE);
1957
1958   return g_time_zone_is_dst (datetime->tz, datetime->interval);
1959 }
1960
1961 /* Timezone convert {{{1 */
1962 /**
1963  * g_date_time_to_timezone:
1964  * @datetime: a #GDateTime
1965  * @tz: the new #GTimeZone
1966  *
1967  * Create a new #GDateTime corresponding to the same instant in time as
1968  * @datetime, but in the time zone @tz.
1969  *
1970  * This call can fail in the case that the time goes out of bounds.  For
1971  * example, converting 0001-01-01 00:00:00 UTC to a time zone west of
1972  * Greenwich will fail (due to the year 0 being out of range).
1973  *
1974  * You should release the return value by calling g_date_time_unref()
1975  * when you are done with it.
1976  *
1977  * Returns: a new #GDateTime, or %NULL
1978  *
1979  * Since: 2.26
1980  **/
1981 GDateTime *
1982 g_date_time_to_timezone (GDateTime *datetime,
1983                          GTimeZone *tz)
1984 {
1985   return g_date_time_from_instant (tz, g_date_time_to_instant (datetime));
1986 }
1987
1988 /**
1989  * g_date_time_to_local:
1990  * @datetime: a #GDateTime
1991  *
1992  * Creates a new #GDateTime corresponding to the same instant in time as
1993  * @datetime, but in the local time zone.
1994  *
1995  * This call is equivalent to calling g_date_time_to_timezone() with the
1996  * time zone returned by g_time_zone_new_local().
1997  *
1998  * Returns: the newly created #GDateTime
1999  *
2000  * Since: 2.26
2001  **/
2002 GDateTime *
2003 g_date_time_to_local (GDateTime *datetime)
2004 {
2005   GDateTime *new;
2006   GTimeZone *local;
2007
2008   local = g_time_zone_new_local ();
2009   new = g_date_time_to_timezone (datetime, local);
2010   g_time_zone_unref (local);
2011
2012   return new;
2013 }
2014
2015 /**
2016  * g_date_time_to_utc:
2017  * @datetime: a #GDateTime
2018  *
2019  * Creates a new #GDateTime corresponding to the same instant in time as
2020  * @datetime, but in UTC.
2021  *
2022  * This call is equivalent to calling g_date_time_to_timezone() with the
2023  * time zone returned by g_time_zone_new_utc().
2024  *
2025  * Returns: the newly created #GDateTime
2026  *
2027  * Since: 2.26
2028  **/
2029 GDateTime *
2030 g_date_time_to_utc (GDateTime *datetime)
2031 {
2032   GDateTime *new;
2033   GTimeZone *utc;
2034
2035   utc = g_time_zone_new_utc ();
2036   new = g_date_time_to_timezone (datetime, utc);
2037   g_time_zone_unref (utc);
2038
2039   return new;
2040 }
2041
2042 /* Format {{{1 */
2043
2044 static void
2045 get_numeric_format (gchar    *fmt,
2046                     gsize     len,
2047                     gboolean  alt_digits,
2048                     gchar     pad,
2049                     gint      width)
2050 {
2051   const gchar *width_str;
2052
2053   if (pad == 0)
2054     width_str = "";
2055   else
2056     {
2057       switch (width)
2058         {
2059         case 0:
2060           width_str = "";
2061           break;
2062         default:
2063           g_warning ("get_numeric_format: width %d not handled", width);
2064           /* fall thru */
2065         case 2:
2066           if (pad == '0')
2067             width_str = "02";
2068           else
2069             width_str = "2";
2070           break;
2071         case 3:
2072           if (pad == '0')
2073             width_str = "03";
2074           else
2075             width_str = "3";
2076           break;
2077         }
2078     }
2079
2080   g_snprintf (fmt, len, "%%%s%sd", alt_digits ? "I": "", width_str);
2081 }
2082
2083 /**
2084  * g_date_time_format:
2085  * @datetime: A #GDateTime
2086  * @format: a valid UTF-8 string, containing the format for the
2087  *          #GDateTime
2088  *
2089  * Creates a newly allocated string representing the requested @format.
2090  *
2091  * The format strings understood by this function are a subset of the
2092  * strftime() format language. In contrast to strftime(), this function
2093  * always produces a UTF-8 string, regardless of the current locale.
2094  * Note that the rendering of many formats is locale-dependent and may
2095  * not match the strftime() output exactly.
2096  *
2097  * The following format specifiers are supported:
2098  *
2099  * <variablelist>
2100  *  <varlistentry><term>
2101  *    <literal>%%a</literal>:
2102  *   </term><listitem><simpara>
2103  *    the abbreviated weekday name according to the current locale
2104  *  </simpara></listitem></varlistentry>
2105  *  <varlistentry><term>
2106  *    <literal>%%A</literal>:
2107  *   </term><listitem><simpara>
2108  *    the full weekday name according to the current locale
2109  *  </simpara></listitem></varlistentry>
2110  *  <varlistentry><term>
2111  *    <literal>%%b</literal>:
2112  *   </term><listitem><simpara>
2113  *    the abbreviated month name according to the current locale
2114  *  </simpara></listitem></varlistentry>
2115  *  <varlistentry><term>
2116  *    <literal>%%B</literal>:
2117  *   </term><listitem><simpara>
2118  *    the full month name according to the current locale
2119  *  </simpara></listitem></varlistentry>
2120  *  <varlistentry><term>
2121  *    <literal>%%d</literal>:
2122  *   </term><listitem><simpara>
2123  *    the day of the month as a decimal number (range 01 to 31)
2124  *  </simpara></listitem></varlistentry>
2125  *  <varlistentry><term>
2126  *    <literal>%%e</literal>:
2127  *   </term><listitem><simpara>
2128  *    the day of the month as a decimal number (range  1 to 31)
2129  *  </simpara></listitem></varlistentry>
2130  *  <varlistentry><term>
2131  *    <literal>%%F</literal>:
2132  *   </term><listitem><simpara>
2133  *    equivalent to <literal>%%Y-%%m-%%d</literal> (the ISO 8601 date
2134  *    format)
2135  *  </simpara></listitem></varlistentry>
2136  *  <varlistentry><term>
2137  *    <literal>%%h</literal>:
2138  *   </term><listitem><simpara>
2139  *    equivalent to <literal>%%b</literal>
2140  *  </simpara></listitem></varlistentry>
2141  *  <varlistentry><term>
2142  *    <literal>%%H</literal>:
2143  *   </term><listitem><simpara>
2144  *    the hour as a decimal number using a 24-hour clock (range 00 to
2145  *    23)
2146  *  </simpara></listitem></varlistentry>
2147  *  <varlistentry><term>
2148  *    <literal>%%I</literal>:
2149  *   </term><listitem><simpara>
2150  *    the hour as a decimal number using a 12-hour clock (range 01 to
2151  *    12)
2152  *  </simpara></listitem></varlistentry>
2153  *  <varlistentry><term>
2154  *    <literal>%%j</literal>:
2155  *   </term><listitem><simpara>
2156  *    the day of the year as a decimal number (range 001 to 366)
2157  *  </simpara></listitem></varlistentry>
2158  *  <varlistentry><term>
2159  *    <literal>%%k</literal>:
2160  *   </term><listitem><simpara>
2161  *    the hour (24-hour clock) as a decimal number (range 0 to 23);
2162  *    single digits are preceded by a blank
2163  *  </simpara></listitem></varlistentry>
2164  *  <varlistentry><term>
2165  *    <literal>%%l</literal>:
2166  *   </term><listitem><simpara>
2167  *    the hour (12-hour clock) as a decimal number (range 1 to 12);
2168  *    single digits are preceded by a blank
2169  *  </simpara></listitem></varlistentry>
2170  *  <varlistentry><term>
2171  *    <literal>%%m</literal>:
2172  *   </term><listitem><simpara>
2173  *    the month as a decimal number (range 01 to 12)
2174  *  </simpara></listitem></varlistentry>
2175  *  <varlistentry><term>
2176  *    <literal>%%M</literal>:
2177  *   </term><listitem><simpara>
2178  *    the minute as a decimal number (range 00 to 59)
2179  *  </simpara></listitem></varlistentry>
2180  *  <varlistentry><term>
2181  *    <literal>%%N</literal>:
2182  *   </term><listitem><simpara>
2183  *    the micro-seconds as a decimal number
2184  *  </simpara></listitem></varlistentry>
2185  *  <varlistentry><term>
2186  *    <literal>%%p</literal>:
2187  *   </term><listitem><simpara>
2188  *    either "AM" or "PM" according to the given time value, or the
2189  *    corresponding  strings for the current locale.  Noon is treated as
2190  *    "PM" and midnight as "AM".
2191  *  </simpara></listitem></varlistentry>
2192  *  <varlistentry><term>
2193  *    <literal>%%P</literal>:
2194  *   </term><listitem><simpara>
2195  *    like %%p but lowercase: "am" or "pm" or a corresponding string for
2196  *    the current locale
2197  *  </simpara></listitem></varlistentry>
2198  *  <varlistentry><term>
2199  *    <literal>%%r</literal>:
2200  *   </term><listitem><simpara>
2201  *    the time in a.m. or p.m. notation
2202  *  </simpara></listitem></varlistentry>
2203  *  <varlistentry><term>
2204  *    <literal>%%R</literal>:
2205  *   </term><listitem><simpara>
2206  *    the time in 24-hour notation (<literal>%%H:%%M</literal>)
2207  *  </simpara></listitem></varlistentry>
2208  *  <varlistentry><term>
2209  *    <literal>%%s</literal>:
2210  *   </term><listitem><simpara>
2211  *    the number of seconds since the Epoch, that is, since 1970-01-01
2212  *    00:00:00 UTC
2213  *  </simpara></listitem></varlistentry>
2214  *  <varlistentry><term>
2215  *    <literal>%%S</literal>:
2216  *   </term><listitem><simpara>
2217  *    the second as a decimal number (range 00 to 60)
2218  *  </simpara></listitem></varlistentry>
2219  *  <varlistentry><term>
2220  *    <literal>%%t</literal>:
2221  *   </term><listitem><simpara>
2222  *    a tab character
2223  *  </simpara></listitem></varlistentry>
2224  *  <varlistentry><term>
2225  *    <literal>%%u</literal>:
2226  *   </term><listitem><simpara>
2227  *    the day of the week as a decimal, range 1 to 7, Monday being 1
2228  *  </simpara></listitem></varlistentry>
2229  *  <varlistentry><term>
2230  *    <literal>%%W</literal>:
2231  *   </term><listitem><simpara>
2232  *    the week number of the current year as a decimal number
2233  *  </simpara></listitem></varlistentry>
2234  *  <varlistentry><term>
2235  *    <literal>%%x</literal>:
2236  *   </term><listitem><simpara>
2237  *    the preferred date representation for the current locale without
2238  *    the time
2239  *  </simpara></listitem></varlistentry>
2240  *  <varlistentry><term>
2241  *    <literal>%%X</literal>:
2242  *   </term><listitem><simpara>
2243  *    the preferred time representation for the current locale without
2244  *    the date
2245  *  </simpara></listitem></varlistentry>
2246  *  <varlistentry><term>
2247  *    <literal>%%y</literal>:
2248  *   </term><listitem><simpara>
2249  *    the year as a decimal number without the century
2250  *  </simpara></listitem></varlistentry>
2251  *  <varlistentry><term>
2252  *    <literal>%%Y</literal>:
2253  *   </term><listitem><simpara>
2254  *    the year as a decimal number including the century
2255  *  </simpara></listitem></varlistentry>
2256  *  <varlistentry><term>
2257  *    <literal>%%z</literal>:
2258  *   </term><listitem><simpara>
2259  *    the time-zone as hour offset from UTC
2260  *  </simpara></listitem></varlistentry>
2261  *  <varlistentry><term>
2262  *    <literal>%%Z</literal>:
2263  *   </term><listitem><simpara>
2264  *    the time zone or name or abbreviation
2265  *  </simpara></listitem></varlistentry>
2266  *  <varlistentry><term>
2267  *    <literal>%%%</literal>:
2268  *   </term><listitem><simpara>
2269  *    a literal <literal>%%</literal> character
2270  *  </simpara></listitem></varlistentry>
2271  * </variablelist>
2272  *
2273  * Some conversion specifications can be modified by preceding the
2274  * conversion specifier by one or more modifier characters. The
2275  * following modifiers are supported for many of the numeric
2276  * conversions:
2277  * <variablelist>
2278  *   <varlistentry>
2279  *     <term>O</term>
2280  *     <listitem>
2281  *       Use alternative numeric symbols, if the current locale
2282  *       supports those.
2283  *     </listitem>
2284  *   </varlistentry>
2285  *   <varlistentry>
2286  *     <term>_</term>
2287  *     <listitem>
2288  *       Pad a numeric result with spaces.
2289  *       This overrides the default padding for the specifier.
2290  *     </listitem>
2291  *   </varlistentry>
2292  *   <varlistentry>
2293  *     <term>-</term>
2294  *     <listitem>
2295  *       Do not pad a numeric result.
2296  *       This overrides the default padding for the specifier.
2297  *     </listitem>
2298  *   </varlistentry>
2299  *   <varlistentry>
2300  *     <term>0</term>
2301  *     <listitem>
2302  *       Pad a numeric result with zeros.
2303  *       This overrides the default padding for the specifier.
2304  *     </listitem>
2305  *   </varlistentry>
2306  * </variablelist>
2307  *
2308  * Returns: a newly allocated string formatted to the requested format
2309  *          or %NULL in the case that there was an error.  The string
2310  *          should be freed with g_free().
2311  *
2312  * Since: 2.26
2313  */
2314 gchar *
2315 g_date_time_format (GDateTime *datetime,
2316                     const gchar     *format)
2317 {
2318   GString  *outstr;
2319   gchar    *tmp;
2320   gunichar  c;
2321   gboolean  in_mod = FALSE;
2322   gboolean  alt_digits = FALSE;
2323   gboolean  pad_set = FALSE;
2324   gchar     pad = '\0';
2325   gchar     fmt[20];
2326
2327   g_return_val_if_fail (datetime != NULL, NULL);
2328   g_return_val_if_fail (format != NULL, NULL);
2329   g_return_val_if_fail (g_utf8_validate (format, -1, NULL), NULL);
2330
2331   outstr = g_string_sized_new (strlen (format) * 2);
2332   in_mod = FALSE;
2333
2334   for (; *format; format = g_utf8_next_char (format))
2335     {
2336       c = g_utf8_get_char (format);
2337
2338       switch (c)
2339         {
2340         case '%':
2341           if (!in_mod)
2342             {
2343               in_mod = TRUE;
2344               alt_digits = FALSE;
2345               pad_set = FALSE;
2346               break;
2347             }
2348             /* Fall through */
2349         default:
2350           if (in_mod)
2351             {
2352               switch (c)
2353                 {
2354                 case 'a':
2355                   g_string_append (outstr, WEEKDAY_ABBR (datetime));
2356                   break;
2357                 case 'A':
2358                   g_string_append (outstr, WEEKDAY_FULL (datetime));
2359                   break;
2360                 case 'b':
2361                   g_string_append (outstr, MONTH_ABBR (datetime));
2362                   break;
2363                 case 'B':
2364                   g_string_append (outstr, MONTH_FULL (datetime));
2365                   break;
2366                 case 'd':
2367                   get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : '0', 2);
2368                   g_string_append_printf (outstr, fmt, g_date_time_get_day_of_month (datetime));
2369                   break;
2370                 case 'e':
2371                   get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : 0, 2);
2372                   g_string_append_printf (outstr, fmt, g_date_time_get_day_of_month (datetime));
2373                   break;
2374                 case 'F':
2375                   g_string_append_printf (outstr, "%d-%02d-%02d",
2376                                           g_date_time_get_year (datetime),
2377                                           g_date_time_get_month (datetime),
2378                                           g_date_time_get_day_of_month (datetime));
2379                   break;
2380                 case 'h':
2381                   g_string_append (outstr, MONTH_ABBR (datetime));
2382                   break;
2383                 case 'H':
2384                   get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : '0', 2);
2385                   g_string_append_printf (outstr, fmt, g_date_time_get_hour (datetime));
2386                   break;
2387                 case 'I':
2388                   {
2389                     gint hour = g_date_time_get_hour (datetime) % 12;
2390                     if (hour == 0)
2391                       hour = 12;
2392                     get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : '0', 2);
2393                     g_string_append_printf (outstr, fmt, hour);
2394                   }
2395                   break;
2396                 case 'j':
2397                   get_numeric_format (fmt, sizeof(fmt), FALSE, pad_set ? pad : '0', 3);
2398                   g_string_append_printf (outstr, fmt, g_date_time_get_day_of_year (datetime));
2399                   break;
2400                 case 'k':
2401                   get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : ' ', 2);
2402                   g_string_append_printf (outstr, fmt, g_date_time_get_hour (datetime));
2403                   break;
2404                 case 'l':
2405                   {
2406                     gint hour = g_date_time_get_hour (datetime) % 12;
2407                     if (hour == 0)
2408                       hour = 12;
2409                     get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : ' ', 2);
2410                     g_string_append_printf (outstr, fmt, hour);
2411                   }
2412                   break;
2413                 case 'm':
2414                   get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : '0', 2);
2415                   g_string_append_printf (outstr, fmt, g_date_time_get_month (datetime));
2416                   break;
2417                 case 'M':
2418                   get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : '0', 2);
2419                   g_string_append_printf (outstr, fmt, g_date_time_get_minute (datetime));
2420                   break;
2421                 case 'N':
2422                   g_string_append_printf (outstr, "%"G_GUINT64_FORMAT, datetime->usec % USEC_PER_SECOND);
2423                   break;
2424                 case 'O':
2425                   alt_digits = TRUE;
2426                   goto next_mod;
2427                 case 'p':
2428                   g_string_append (outstr, GET_AMPM (datetime, FALSE));
2429                   break;
2430                 case 'P':
2431                   g_string_append (outstr, GET_AMPM (datetime, TRUE));
2432                   break;
2433                 case 'r':
2434                   {
2435                     gint hour = g_date_time_get_hour (datetime) % 12;
2436                     if (hour == 0)
2437                       hour = 12;
2438                     g_string_append_printf (outstr, "%02d:%02d:%02d %s",
2439                                             hour,
2440                                             g_date_time_get_minute (datetime),
2441                                             g_date_time_get_second (datetime),
2442                                             GET_AMPM (datetime, FALSE));
2443                   }
2444                   break;
2445                 case 'R':
2446                   g_string_append_printf (outstr, "%02d:%02d",
2447                                           g_date_time_get_hour (datetime),
2448                                           g_date_time_get_minute (datetime));
2449                   break;
2450                 case 's':
2451                   g_string_append_printf (outstr, "%" G_GINT64_FORMAT, g_date_time_to_unix (datetime));
2452                   break;
2453                 case 'S':
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_second (datetime));
2456                   break;
2457                 case 't':
2458                   g_string_append_c (outstr, '\t');
2459                   break;
2460                 case 'u':
2461                   get_numeric_format (fmt, sizeof(fmt), alt_digits, 0, 0);
2462                   g_string_append_printf (outstr, fmt, g_date_time_get_day_of_week (datetime));
2463                   break;
2464                 case 'W':
2465                   get_numeric_format (fmt, sizeof(fmt), alt_digits, 0, 0);
2466                   g_string_append_printf (outstr, fmt, g_date_time_get_day_of_year (datetime) / 7);
2467                   break;
2468                 case 'x':
2469                   {
2470                     tmp = GET_PREFERRED_DATE (datetime);
2471                     g_string_append (outstr, tmp);
2472                     g_free (tmp);
2473                   }
2474                   break;
2475                 case 'X':
2476                   {
2477                     tmp = GET_PREFERRED_TIME (datetime);
2478                     g_string_append (outstr, tmp);
2479                     g_free (tmp);
2480                   }
2481                   break;
2482                 case 'y':
2483                   get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : '0', 2);
2484                   g_string_append_printf (outstr, fmt, g_date_time_get_year (datetime) % 100);
2485                   break;
2486                 case 'Y':
2487                   get_numeric_format (fmt, sizeof(fmt), alt_digits, 0, 0);
2488                   g_string_append_printf (outstr, fmt, g_date_time_get_year (datetime));
2489                   break;
2490                 case 'z':
2491                   if (datetime->tz != NULL)
2492                     {
2493                       gint64 offset = g_date_time_get_utc_offset (datetime)
2494                                     / USEC_PER_SECOND;
2495
2496                       g_string_append_printf (outstr, "%+03d%02d",
2497                                               (int) offset / 3600,
2498                                               (int) abs(offset) / 60 % 60);
2499                     }
2500                   else
2501                     g_string_append (outstr, "+0000");
2502                   break;
2503                 case 'Z':
2504                   g_string_append (outstr, g_date_time_get_timezone_abbreviation (datetime));
2505                   break;
2506                 case '%':
2507                   g_string_append_c (outstr, '%');
2508                   break;
2509                 case 'n':
2510                   g_string_append_c (outstr, '\n');
2511                   break;
2512                 case '-':
2513                   pad_set = TRUE;
2514                   pad = 0;
2515                   goto next_mod;
2516                 case '_':
2517                   pad_set = TRUE;
2518                   pad = ' ';
2519                   goto next_mod;
2520                 case '0':
2521                   pad_set = TRUE;
2522                   pad = '0';
2523                   goto next_mod;
2524                 default:
2525                   goto bad_format;
2526                 }
2527               in_mod = FALSE;
2528             }
2529           else
2530             g_string_append_unichar (outstr, c);
2531         }
2532 next_mod: ;
2533     }
2534
2535   return g_string_free (outstr, FALSE);
2536
2537 bad_format:
2538   g_string_free (outstr, TRUE);
2539   return NULL;
2540 }
2541
2542
2543 /* Epilogue {{{1 */
2544 /* vim:set foldmethod=marker: */