Make --enable-man and --enable-gtk-doc independent
[glib.git] / glib / gdatetime.c
blob4bd0e797a068e509ffc0327eb43b4a123116168a
1 /* gdatetime.c
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
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.
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.
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.
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>
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
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.
42 * This document is provided "as is". No warranties are made as
43 * to its correctness.
46 /* Prologue {{{1 */
48 #include "config.h"
50 #include <stdlib.h>
51 #include <string.h>
53 #ifdef HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
57 #ifdef HAVE_LANGINFO_TIME
58 #include <langinfo.h>
59 #endif
61 #include "gdatetime.h"
63 #include "gslice.h"
64 #include "gatomic.h"
65 #include "gcharset.h"
66 #include "gconvert.h"
67 #include "gfileutils.h"
68 #include "ghash.h"
69 #include "gmain.h"
70 #include "gmappedfile.h"
71 #include "gstrfuncs.h"
72 #include "gtestutils.h"
73 #include "gthread.h"
74 #include "gtimezone.h"
76 #include "glibintl.h"
78 #ifndef G_OS_WIN32
79 #include <sys/time.h>
80 #include <time.h>
81 #endif /* !G_OS_WIN32 */
83 /**
84 * SECTION:date-time
85 * @title: GDateTime
86 * @short_description: a structure representing Date and Time
87 * @see_also: #GTimeZone
89 * #GDateTime is a structure that combines a Gregorian date and time
90 * into a single structure. It provides many conversion and methods to
91 * manipulate dates and times. Time precision is provided down to
92 * microseconds and the time can range (proleptically) from 0001-01-01
93 * 00:00:00 to 9999-12-31 23:59:59.999999. #GDateTime follows POSIX
94 * time in the sense that it is oblivious to leap seconds.
96 * #GDateTime is an immutable object; once it has been created it cannot
97 * be modified further. All modifiers will create a new #GDateTime.
98 * Nearly all such functions can fail due to the date or time going out
99 * of range, in which case %NULL will be returned.
101 * #GDateTime is reference counted: the reference count is increased by calling
102 * g_date_time_ref() and decreased by calling g_date_time_unref(). When the
103 * reference count drops to 0, the resources allocated by the #GDateTime
104 * structure are released.
106 * Many parts of the API may produce non-obvious results. As an
107 * example, adding two months to January 31st will yield March 31st
108 * whereas adding one month and then one month again will yield either
109 * March 28th or March 29th. Also note that adding 24 hours is not
110 * always the same as adding one day (since days containing daylight
111 * savings time transitions are either 23 or 25 hours in length).
113 * #GDateTime is available since GLib 2.26.
116 struct _GDateTime
118 /* 1 is 0001-01-01 in Proleptic Gregorian */
119 gint32 days;
121 /* Microsecond timekeeping within Day */
122 guint64 usec;
124 /* TimeZone information */
125 GTimeZone *tz;
126 gint interval;
128 volatile gint ref_count;
131 /* Time conversion {{{1 */
133 #define UNIX_EPOCH_START 719163
134 #define INSTANT_TO_UNIX(instant) \
135 ((instant)/USEC_PER_SECOND - UNIX_EPOCH_START * SEC_PER_DAY)
136 #define UNIX_TO_INSTANT(unix) \
137 (((unix) + UNIX_EPOCH_START * SEC_PER_DAY) * USEC_PER_SECOND)
139 #define DAYS_IN_4YEARS 1461 /* days in 4 years */
140 #define DAYS_IN_100YEARS 36524 /* days in 100 years */
141 #define DAYS_IN_400YEARS 146097 /* days in 400 years */
143 #define USEC_PER_SECOND (G_GINT64_CONSTANT (1000000))
144 #define USEC_PER_MINUTE (G_GINT64_CONSTANT (60000000))
145 #define USEC_PER_HOUR (G_GINT64_CONSTANT (3600000000))
146 #define USEC_PER_MILLISECOND (G_GINT64_CONSTANT (1000))
147 #define USEC_PER_DAY (G_GINT64_CONSTANT (86400000000))
148 #define SEC_PER_DAY (G_GINT64_CONSTANT (86400))
150 #define SECS_PER_MINUTE (60)
151 #define SECS_PER_HOUR (60 * SECS_PER_MINUTE)
152 #define SECS_PER_DAY (24 * SECS_PER_HOUR)
153 #define SECS_PER_YEAR (365 * SECS_PER_DAY)
154 #define SECS_PER_JULIAN (DAYS_PER_PERIOD * SECS_PER_DAY)
156 #define GREGORIAN_LEAP(y) ((((y) % 4) == 0) && (!((((y) % 100) == 0) && (((y) % 400) != 0))))
157 #define JULIAN_YEAR(d) ((d)->julian / 365.25)
158 #define DAYS_PER_PERIOD (G_GINT64_CONSTANT (2914695))
160 static const guint16 days_in_months[2][13] =
162 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
163 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
166 static const guint16 days_in_year[2][13] =
168 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
169 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
172 #ifdef HAVE_LANGINFO_TIME
174 #define GET_AMPM(d) ((g_date_time_get_hour (d) < 12) ? \
175 nl_langinfo (AM_STR) : \
176 nl_langinfo (PM_STR))
178 #define PREFERRED_DATE_TIME_FMT nl_langinfo (D_T_FMT)
179 #define PREFERRED_DATE_FMT nl_langinfo (D_FMT)
180 #define PREFERRED_TIME_FMT nl_langinfo (T_FMT)
181 #define PREFERRED_TIME_FMT nl_langinfo (T_FMT)
182 #define PREFERRED_12HR_TIME_FMT nl_langinfo (T_FMT_AMPM)
184 static const gint weekday_item[2][7] =
186 { ABDAY_2, ABDAY_3, ABDAY_4, ABDAY_5, ABDAY_6, ABDAY_7, ABDAY_1 },
187 { DAY_2, DAY_3, DAY_4, DAY_5, DAY_6, DAY_7, DAY_1 }
190 static const gint month_item[2][12] =
192 { ABMON_1, ABMON_2, ABMON_3, ABMON_4, ABMON_5, ABMON_6, ABMON_7, ABMON_8, ABMON_9, ABMON_10, ABMON_11, ABMON_12 },
193 { MON_1, MON_2, MON_3, MON_4, MON_5, MON_6, MON_7, MON_8, MON_9, MON_10, MON_11, MON_12 },
196 #define WEEKDAY_ABBR(d) nl_langinfo (weekday_item[0][g_date_time_get_day_of_week (d) - 1])
197 #define WEEKDAY_FULL(d) nl_langinfo (weekday_item[1][g_date_time_get_day_of_week (d) - 1])
198 #define MONTH_ABBR(d) nl_langinfo (month_item[0][g_date_time_get_month (d) - 1])
199 #define MONTH_FULL(d) nl_langinfo (month_item[1][g_date_time_get_month (d) - 1])
201 #else
203 #define GET_AMPM(d) ((g_date_time_get_hour (d) < 12) \
204 /* Translators: 'before midday' indicator */ \
205 ? C_("GDateTime", "AM") \
206 /* Translators: 'after midday' indicator */ \
207 : C_("GDateTime", "PM"))
209 /* Translators: this is the preferred format for expressing the date and the time */
210 #define PREFERRED_DATE_TIME_FMT C_("GDateTime", "%a %b %e %H:%M:%S %Y")
212 /* Translators: this is the preferred format for expressing the date */
213 #define PREFERRED_DATE_FMT C_("GDateTime", "%m/%d/%y")
215 /* Translators: this is the preferred format for expressing the time */
216 #define PREFERRED_TIME_FMT C_("GDateTime", "%H:%M:%S")
218 /* Translators: this is the preferred format for expressing 12 hour time */
219 #define PREFERRED_12HR_TIME_FMT C_("GDateTime", "%I:%M:%S %p")
221 #define WEEKDAY_ABBR(d) (get_weekday_name_abbr (g_date_time_get_day_of_week (d)))
222 #define WEEKDAY_FULL(d) (get_weekday_name (g_date_time_get_day_of_week (d)))
223 #define MONTH_ABBR(d) (get_month_name_abbr (g_date_time_get_month (d)))
224 #define MONTH_FULL(d) (get_month_name (g_date_time_get_month (d)))
226 static const gchar *
227 get_month_name (gint month)
229 switch (month)
231 case 1:
232 return C_("full month name", "January");
233 case 2:
234 return C_("full month name", "February");
235 case 3:
236 return C_("full month name", "March");
237 case 4:
238 return C_("full month name", "April");
239 case 5:
240 return C_("full month name", "May");
241 case 6:
242 return C_("full month name", "June");
243 case 7:
244 return C_("full month name", "July");
245 case 8:
246 return C_("full month name", "August");
247 case 9:
248 return C_("full month name", "September");
249 case 10:
250 return C_("full month name", "October");
251 case 11:
252 return C_("full month name", "November");
253 case 12:
254 return C_("full month name", "December");
256 default:
257 g_warning ("Invalid month number %d", month);
260 return NULL;
263 static const gchar *
264 get_month_name_abbr (gint month)
266 switch (month)
268 case 1:
269 return C_("abbreviated month name", "Jan");
270 case 2:
271 return C_("abbreviated month name", "Feb");
272 case 3:
273 return C_("abbreviated month name", "Mar");
274 case 4:
275 return C_("abbreviated month name", "Apr");
276 case 5:
277 return C_("abbreviated month name", "May");
278 case 6:
279 return C_("abbreviated month name", "Jun");
280 case 7:
281 return C_("abbreviated month name", "Jul");
282 case 8:
283 return C_("abbreviated month name", "Aug");
284 case 9:
285 return C_("abbreviated month name", "Sep");
286 case 10:
287 return C_("abbreviated month name", "Oct");
288 case 11:
289 return C_("abbreviated month name", "Nov");
290 case 12:
291 return C_("abbreviated month name", "Dec");
293 default:
294 g_warning ("Invalid month number %d", month);
297 return NULL;
300 static const gchar *
301 get_weekday_name (gint day)
303 switch (day)
305 case 1:
306 return C_("full weekday name", "Monday");
307 case 2:
308 return C_("full weekday name", "Tuesday");
309 case 3:
310 return C_("full weekday name", "Wednesday");
311 case 4:
312 return C_("full weekday name", "Thursday");
313 case 5:
314 return C_("full weekday name", "Friday");
315 case 6:
316 return C_("full weekday name", "Saturday");
317 case 7:
318 return C_("full weekday name", "Sunday");
320 default:
321 g_warning ("Invalid week day number %d", day);
324 return NULL;
327 static const gchar *
328 get_weekday_name_abbr (gint day)
330 switch (day)
332 case 1:
333 return C_("abbreviated weekday name", "Mon");
334 case 2:
335 return C_("abbreviated weekday name", "Tue");
336 case 3:
337 return C_("abbreviated weekday name", "Wed");
338 case 4:
339 return C_("abbreviated weekday name", "Thu");
340 case 5:
341 return C_("abbreviated weekday name", "Fri");
342 case 6:
343 return C_("abbreviated weekday name", "Sat");
344 case 7:
345 return C_("abbreviated weekday name", "Sun");
347 default:
348 g_warning ("Invalid week day number %d", day);
351 return NULL;
354 #endif /* HAVE_LANGINFO_TIME */
356 static inline gint
357 ymd_to_days (gint year,
358 gint month,
359 gint day)
361 gint64 days;
363 days = (year - 1) * 365 + ((year - 1) / 4) - ((year - 1) / 100)
364 + ((year - 1) / 400);
366 days += days_in_year[0][month - 1];
367 if (GREGORIAN_LEAP (year) && month > 2)
368 day++;
370 days += day;
372 return days;
375 static void
376 g_date_time_get_week_number (GDateTime *datetime,
377 gint *week_number,
378 gint *day_of_week,
379 gint *day_of_year)
381 gint a, b, c, d, e, f, g, n, s, month, day, year;
383 g_date_time_get_ymd (datetime, &year, &month, &day);
385 if (month <= 2)
387 a = g_date_time_get_year (datetime) - 1;
388 b = (a / 4) - (a / 100) + (a / 400);
389 c = ((a - 1) / 4) - ((a - 1) / 100) + ((a - 1) / 400);
390 s = b - c;
391 e = 0;
392 f = day - 1 + (31 * (month - 1));
394 else
396 a = year;
397 b = (a / 4) - (a / 100) + (a / 400);
398 c = ((a - 1) / 4) - ((a - 1) / 100) + ((a - 1) / 400);
399 s = b - c;
400 e = s + 1;
401 f = day + (((153 * (month - 3)) + 2) / 5) + 58 + s;
404 g = (a + b) % 7;
405 d = (f + g - e) % 7;
406 n = f + 3 - d;
408 if (week_number)
410 if (n < 0)
411 *week_number = 53 - ((g - s) / 5);
412 else if (n > 364 + s)
413 *week_number = 1;
414 else
415 *week_number = (n / 7) + 1;
418 if (day_of_week)
419 *day_of_week = d + 1;
421 if (day_of_year)
422 *day_of_year = f + 1;
425 /* Lifecycle {{{1 */
427 static GDateTime *
428 g_date_time_alloc (GTimeZone *tz)
430 GDateTime *datetime;
432 datetime = g_slice_new0 (GDateTime);
433 datetime->tz = g_time_zone_ref (tz);
434 datetime->ref_count = 1;
436 return datetime;
440 * g_date_time_ref:
441 * @datetime: a #GDateTime
443 * Atomically increments the reference count of @datetime by one.
445 * Return value: the #GDateTime with the reference count increased
447 * Since: 2.26
449 GDateTime *
450 g_date_time_ref (GDateTime *datetime)
452 g_return_val_if_fail (datetime != NULL, NULL);
453 g_return_val_if_fail (datetime->ref_count > 0, NULL);
455 g_atomic_int_inc (&datetime->ref_count);
457 return datetime;
461 * g_date_time_unref:
462 * @datetime: a #GDateTime
464 * Atomically decrements the reference count of @datetime by one.
466 * When the reference count reaches zero, the resources allocated by
467 * @datetime are freed
469 * Since: 2.26
471 void
472 g_date_time_unref (GDateTime *datetime)
474 g_return_if_fail (datetime != NULL);
475 g_return_if_fail (datetime->ref_count > 0);
477 if (g_atomic_int_dec_and_test (&datetime->ref_count))
479 g_time_zone_unref (datetime->tz);
480 g_slice_free (GDateTime, datetime);
484 /* Internal state transformers {{{1 */
485 /*< internal >
486 * g_date_time_to_instant:
487 * @datetime: a #GDateTime
489 * Convert a @datetime into an instant.
491 * An instant is a number that uniquely describes a particular
492 * microsecond in time, taking time zone considerations into account.
493 * (ie: "03:00 -0400" is the same instant as "02:00 -0500").
495 * An instant is always positive but we use a signed return value to
496 * avoid troubles with C.
498 static gint64
499 g_date_time_to_instant (GDateTime *datetime)
501 gint64 offset;
503 offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
504 offset *= USEC_PER_SECOND;
506 return datetime->days * USEC_PER_DAY + datetime->usec - offset;
509 /*< internal >
510 * g_date_time_from_instant:
511 * @tz: a #GTimeZone
512 * @instant: a instant in time
514 * Creates a #GDateTime from a time zone and an instant.
516 * This might fail if the time ends up being out of range.
518 static GDateTime *
519 g_date_time_from_instant (GTimeZone *tz,
520 gint64 instant)
522 GDateTime *datetime;
523 gint64 offset;
525 if (instant < 0 || instant > G_GINT64_CONSTANT (1000000000000000000))
526 return NULL;
528 datetime = g_date_time_alloc (tz);
529 datetime->interval = g_time_zone_find_interval (tz,
530 G_TIME_TYPE_UNIVERSAL,
531 INSTANT_TO_UNIX (instant));
532 offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
533 offset *= USEC_PER_SECOND;
535 instant += offset;
537 datetime->days = instant / USEC_PER_DAY;
538 datetime->usec = instant % USEC_PER_DAY;
540 if (datetime->days < 1 || 3652059 < datetime->days)
542 g_date_time_unref (datetime);
543 datetime = NULL;
546 return datetime;
550 /*< internal >
551 * g_date_time_deal_with_date_change:
552 * @datetime: a #GDateTime
554 * This function should be called whenever the date changes by adding
555 * days, months or years. It does three things.
557 * First, we ensure that the date falls between 0001-01-01 and
558 * 9999-12-31 and return %FALSE if it does not.
560 * Next we update the ->interval field.
562 * Finally, we ensure that the resulting date and time pair exists (by
563 * ensuring that our time zone has an interval containing it) and
564 * adjusting as required. For example, if we have the time 02:30:00 on
565 * March 13 2010 in Toronto and we add 1 day to it, we would end up with
566 * 2:30am on March 14th, which doesn't exist. In that case, we bump the
567 * time up to 3:00am.
569 static gboolean
570 g_date_time_deal_with_date_change (GDateTime *datetime)
572 GTimeType was_dst;
573 gint64 full_time;
574 gint64 usec;
576 if (datetime->days < 1 || datetime->days > 3652059)
577 return FALSE;
579 was_dst = g_time_zone_is_dst (datetime->tz, datetime->interval);
581 full_time = datetime->days * USEC_PER_DAY + datetime->usec;
584 usec = full_time % USEC_PER_SECOND;
585 full_time /= USEC_PER_SECOND;
586 full_time -= UNIX_EPOCH_START * SEC_PER_DAY;
588 datetime->interval = g_time_zone_adjust_time (datetime->tz,
589 was_dst,
590 &full_time);
591 full_time += UNIX_EPOCH_START * SEC_PER_DAY;
592 full_time *= USEC_PER_SECOND;
593 full_time += usec;
595 datetime->days = full_time / USEC_PER_DAY;
596 datetime->usec = full_time % USEC_PER_DAY;
598 /* maybe daylight time caused us to shift to a different day,
599 * but it definitely didn't push us into a different year */
600 return TRUE;
603 static GDateTime *
604 g_date_time_replace_days (GDateTime *datetime,
605 gint days)
607 GDateTime *new;
609 new = g_date_time_alloc (datetime->tz);
610 new->interval = datetime->interval;
611 new->usec = datetime->usec;
612 new->days = days;
614 if (!g_date_time_deal_with_date_change (new))
616 g_date_time_unref (new);
617 new = NULL;
620 return new;
623 /* now/unix/timeval Constructors {{{1 */
625 /*< internal >
626 * g_date_time_new_from_timeval:
627 * @tz: a #GTimeZone
628 * @tv: a #GTimeVal
630 * Creates a #GDateTime corresponding to the given #GTimeVal @tv in the
631 * given time zone @tz.
633 * The time contained in a #GTimeVal is always stored in the form of
634 * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the
635 * given time zone.
637 * This call can fail (returning %NULL) if @tv represents a time outside
638 * of the supported range of #GDateTime.
640 * You should release the return value by calling g_date_time_unref()
641 * when you are done with it.
643 * Returns: a new #GDateTime, or %NULL
645 * Since: 2.26
647 static GDateTime *
648 g_date_time_new_from_timeval (GTimeZone *tz,
649 const GTimeVal *tv)
651 return g_date_time_from_instant (tz, tv->tv_usec +
652 UNIX_TO_INSTANT (tv->tv_sec));
655 /*< internal >
656 * g_date_time_new_from_unix:
657 * @tz: a #GTimeZone
658 * @t: the Unix time
660 * Creates a #GDateTime corresponding to the given Unix time @t in the
661 * given time zone @tz.
663 * Unix time is the number of seconds that have elapsed since 1970-01-01
664 * 00:00:00 UTC, regardless of the time zone given.
666 * This call can fail (returning %NULL) if @t represents a time outside
667 * of the supported range of #GDateTime.
669 * You should release the return value by calling g_date_time_unref()
670 * when you are done with it.
672 * Returns: a new #GDateTime, or %NULL
674 * Since: 2.26
676 static GDateTime *
677 g_date_time_new_from_unix (GTimeZone *tz,
678 gint64 secs)
680 return g_date_time_from_instant (tz, UNIX_TO_INSTANT (secs));
684 * g_date_time_new_now:
685 * @tz: a #GTimeZone
687 * Creates a #GDateTime corresponding to this exact instant in the given
688 * time zone @tz. The time is as accurate as the system allows, to a
689 * maximum accuracy of 1 microsecond.
691 * This function will always succeed unless the system clock is set to
692 * truly insane values (or unless GLib is still being used after the
693 * year 9999).
695 * You should release the return value by calling g_date_time_unref()
696 * when you are done with it.
698 * Returns: a new #GDateTime, or %NULL
700 * Since: 2.26
702 GDateTime *
703 g_date_time_new_now (GTimeZone *tz)
705 GTimeVal tv;
707 g_get_current_time (&tv);
709 return g_date_time_new_from_timeval (tz, &tv);
713 * g_date_time_new_now_local:
715 * Creates a #GDateTime corresponding to this exact instant in the local
716 * time zone.
718 * This is equivalent to calling g_date_time_new_now() with the time
719 * zone returned by g_time_zone_new_local().
721 * Returns: a new #GDateTime, or %NULL
723 * Since: 2.26
725 GDateTime *
726 g_date_time_new_now_local (void)
728 GDateTime *datetime;
729 GTimeZone *local;
731 local = g_time_zone_new_local ();
732 datetime = g_date_time_new_now (local);
733 g_time_zone_unref (local);
735 return datetime;
739 * g_date_time_new_now_utc:
741 * Creates a #GDateTime corresponding to this exact instant in UTC.
743 * This is equivalent to calling g_date_time_new_now() with the time
744 * zone returned by g_time_zone_new_utc().
746 * Returns: a new #GDateTime, or %NULL
748 * Since: 2.26
750 GDateTime *
751 g_date_time_new_now_utc (void)
753 GDateTime *datetime;
754 GTimeZone *utc;
756 utc = g_time_zone_new_utc ();
757 datetime = g_date_time_new_now (utc);
758 g_time_zone_unref (utc);
760 return datetime;
764 * g_date_time_new_from_unix_local:
765 * @t: the Unix time
767 * Creates a #GDateTime corresponding to the given Unix time @t in the
768 * local time zone.
770 * Unix time is the number of seconds that have elapsed since 1970-01-01
771 * 00:00:00 UTC, regardless of the local time offset.
773 * This call can fail (returning %NULL) if @t represents a time outside
774 * of the supported range of #GDateTime.
776 * You should release the return value by calling g_date_time_unref()
777 * when you are done with it.
779 * Returns: a new #GDateTime, or %NULL
781 * Since: 2.26
783 GDateTime *
784 g_date_time_new_from_unix_local (gint64 t)
786 GDateTime *datetime;
787 GTimeZone *local;
789 local = g_time_zone_new_local ();
790 datetime = g_date_time_new_from_unix (local, t);
791 g_time_zone_unref (local);
793 return datetime;
797 * g_date_time_new_from_unix_utc:
798 * @t: the Unix time
800 * Creates a #GDateTime corresponding to the given Unix time @t in UTC.
802 * Unix time is the number of seconds that have elapsed since 1970-01-01
803 * 00:00:00 UTC.
805 * This call can fail (returning %NULL) if @t represents a time outside
806 * of the supported range of #GDateTime.
808 * You should release the return value by calling g_date_time_unref()
809 * when you are done with it.
811 * Returns: a new #GDateTime, or %NULL
813 * Since: 2.26
815 GDateTime *
816 g_date_time_new_from_unix_utc (gint64 t)
818 GDateTime *datetime;
819 GTimeZone *utc;
821 utc = g_time_zone_new_utc ();
822 datetime = g_date_time_new_from_unix (utc, t);
823 g_time_zone_unref (utc);
825 return datetime;
829 * g_date_time_new_from_timeval_local:
830 * @tv: a #GTimeVal
832 * Creates a #GDateTime corresponding to the given #GTimeVal @tv in the
833 * local time zone.
835 * The time contained in a #GTimeVal is always stored in the form of
836 * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the
837 * local time offset.
839 * This call can fail (returning %NULL) if @tv represents a time outside
840 * of the supported range of #GDateTime.
842 * You should release the return value by calling g_date_time_unref()
843 * when you are done with it.
845 * Returns: a new #GDateTime, or %NULL
847 * Since: 2.26
849 GDateTime *
850 g_date_time_new_from_timeval_local (const GTimeVal *tv)
852 GDateTime *datetime;
853 GTimeZone *local;
855 local = g_time_zone_new_local ();
856 datetime = g_date_time_new_from_timeval (local, tv);
857 g_time_zone_unref (local);
859 return datetime;
863 * g_date_time_new_from_timeval_utc:
864 * @tv: a #GTimeVal
866 * Creates a #GDateTime corresponding to the given #GTimeVal @tv in UTC.
868 * The time contained in a #GTimeVal is always stored in the form of
869 * seconds elapsed since 1970-01-01 00:00:00 UTC.
871 * This call can fail (returning %NULL) if @tv represents a time outside
872 * of the supported range of #GDateTime.
874 * You should release the return value by calling g_date_time_unref()
875 * when you are done with it.
877 * Returns: a new #GDateTime, or %NULL
879 * Since: 2.26
881 GDateTime *
882 g_date_time_new_from_timeval_utc (const GTimeVal *tv)
884 GDateTime *datetime;
885 GTimeZone *utc;
887 utc = g_time_zone_new_utc ();
888 datetime = g_date_time_new_from_timeval (utc, tv);
889 g_time_zone_unref (utc);
891 return datetime;
894 /* full new functions {{{1 */
897 * g_date_time_new:
898 * @tz: a #GTimeZone
899 * @year: the year component of the date
900 * @month: the month component of the date
901 * @day: the day component of the date
902 * @hour: the hour component of the date
903 * @minute: the minute component of the date
904 * @seconds: the number of seconds past the minute
906 * Creates a new #GDateTime corresponding to the given date and time in
907 * the time zone @tz.
909 * The @year must be between 1 and 9999, @month between 1 and 12 and @day
910 * between 1 and 28, 29, 30 or 31 depending on the month and the year.
912 * @hour must be between 0 and 23 and @minute must be between 0 and 59.
914 * @seconds must be at least 0.0 and must be strictly less than 60.0.
915 * It will be rounded down to the nearest microsecond.
917 * If the given time is not representable in the given time zone (for
918 * example, 02:30 on March 14th 2010 in Toronto, due to daylight savings
919 * time) then the time will be rounded up to the nearest existing time
920 * (in this case, 03:00). If this matters to you then you should verify
921 * the return value for containing the same as the numbers you gave.
923 * In the case that the given time is ambiguous in the given time zone
924 * (for example, 01:30 on November 7th 2010 in Toronto, due to daylight
925 * savings time) then the time falling within standard (ie:
926 * non-daylight) time is taken.
928 * It not considered a programmer error for the values to this function
929 * to be out of range, but in the case that they are, the function will
930 * return %NULL.
932 * You should release the return value by calling g_date_time_unref()
933 * when you are done with it.
935 * Returns: a new #GDateTime, or %NULL
937 * Since: 2.26
939 GDateTime *
940 g_date_time_new (GTimeZone *tz,
941 gint year,
942 gint month,
943 gint day,
944 gint hour,
945 gint minute,
946 gdouble seconds)
948 GDateTime *datetime;
949 gint64 full_time;
951 datetime = g_date_time_alloc (tz);
952 datetime->days = ymd_to_days (year, month, day);
953 datetime->usec = (hour * USEC_PER_HOUR)
954 + (minute * USEC_PER_MINUTE)
955 + (gint64) (seconds * USEC_PER_SECOND);
957 full_time = SEC_PER_DAY *
958 (ymd_to_days (year, month, day) - UNIX_EPOCH_START) +
959 SECS_PER_HOUR * hour +
960 SECS_PER_MINUTE * minute +
961 (int) seconds;
963 datetime->interval = g_time_zone_adjust_time (datetime->tz,
964 G_TIME_TYPE_STANDARD,
965 &full_time);
967 full_time += UNIX_EPOCH_START * SEC_PER_DAY;
968 datetime->days = full_time / SEC_PER_DAY;
969 datetime->usec = (full_time % SEC_PER_DAY) * USEC_PER_SECOND;
970 datetime->usec += ((int) (seconds * USEC_PER_SECOND)) % USEC_PER_SECOND;
972 return datetime;
976 * g_date_time_new_local:
977 * @year: the year component of the date
978 * @month: the month component of the date
979 * @day: the day component of the date
980 * @hour: the hour component of the date
981 * @minute: the minute component of the date
982 * @seconds: the number of seconds past the minute
984 * Creates a new #GDateTime corresponding to the given date and time in
985 * the local time zone.
987 * This call is equivalent to calling g_date_time_new() with the time
988 * zone returned by g_time_zone_new_local().
990 * Returns: a #GDateTime, or %NULL
992 * Since: 2.26
994 GDateTime *
995 g_date_time_new_local (gint year,
996 gint month,
997 gint day,
998 gint hour,
999 gint minute,
1000 gdouble seconds)
1002 GDateTime *datetime;
1003 GTimeZone *local;
1005 local = g_time_zone_new_local ();
1006 datetime = g_date_time_new (local, year, month, day, hour, minute, seconds);
1007 g_time_zone_unref (local);
1009 return datetime;
1013 * g_date_time_new_utc:
1014 * @year: the year component of the date
1015 * @month: the month component of the date
1016 * @day: the day component of the date
1017 * @hour: the hour component of the date
1018 * @minute: the minute component of the date
1019 * @seconds: the number of seconds past the minute
1021 * Creates a new #GDateTime corresponding to the given date and time in
1022 * UTC.
1024 * This call is equivalent to calling g_date_time_new() with the time
1025 * zone returned by g_time_zone_new_utc().
1027 * Returns: a #GDateTime, or %NULL
1029 * Since: 2.26
1031 GDateTime *
1032 g_date_time_new_utc (gint year,
1033 gint month,
1034 gint day,
1035 gint hour,
1036 gint minute,
1037 gdouble seconds)
1039 GDateTime *datetime;
1040 GTimeZone *utc;
1042 utc = g_time_zone_new_utc ();
1043 datetime = g_date_time_new (utc, year, month, day, hour, minute, seconds);
1044 g_time_zone_unref (utc);
1046 return datetime;
1049 /* Adders {{{1 */
1052 * g_date_time_add:
1053 * @datetime: a #GDateTime
1054 * @timespan: a #GTimeSpan
1056 * Creates a copy of @datetime and adds the specified timespan to the copy.
1058 * Return value: the newly created #GDateTime which should be freed with
1059 * g_date_time_unref().
1061 * Since: 2.26
1063 GDateTime*
1064 g_date_time_add (GDateTime *datetime,
1065 GTimeSpan timespan)
1067 return g_date_time_from_instant (datetime->tz, timespan +
1068 g_date_time_to_instant (datetime));
1072 * g_date_time_add_years:
1073 * @datetime: a #GDateTime
1074 * @years: the number of years
1076 * Creates a copy of @datetime and adds the specified number of years to the
1077 * copy.
1079 * Return value: the newly created #GDateTime which should be freed with
1080 * g_date_time_unref().
1082 * Since: 2.26
1084 GDateTime *
1085 g_date_time_add_years (GDateTime *datetime,
1086 gint years)
1088 gint year, month, day;
1090 g_return_val_if_fail (datetime != NULL, NULL);
1092 if (years < -10000 || years > 10000)
1093 return NULL;
1095 g_date_time_get_ymd (datetime, &year, &month, &day);
1096 year += years;
1098 /* only possible issue is if we've entered a year with no February 29
1100 if (month == 2 && day == 29 && !GREGORIAN_LEAP (year))
1101 day = 28;
1103 return g_date_time_replace_days (datetime, ymd_to_days (year, month, day));
1107 * g_date_time_add_months:
1108 * @datetime: a #GDateTime
1109 * @months: the number of months
1111 * Creates a copy of @datetime and adds the specified number of months to the
1112 * copy.
1114 * Return value: the newly created #GDateTime which should be freed with
1115 * g_date_time_unref().
1117 * Since: 2.26
1119 GDateTime*
1120 g_date_time_add_months (GDateTime *datetime,
1121 gint months)
1123 gint year, month, day;
1125 g_return_val_if_fail (datetime != NULL, NULL);
1126 g_date_time_get_ymd (datetime, &year, &month, &day);
1128 if (months < -120000 || months > 120000)
1129 return NULL;
1131 year += months / 12;
1132 month += months % 12;
1133 if (month < 1)
1135 month += 12;
1136 year--;
1138 else if (month > 12)
1140 month -= 12;
1141 year++;
1144 day = MIN (day, days_in_months[GREGORIAN_LEAP (year)][month]);
1146 return g_date_time_replace_days (datetime, ymd_to_days (year, month, day));
1150 * g_date_time_add_weeks:
1151 * @datetime: a #GDateTime
1152 * @weeks: the number of weeks
1154 * Creates a copy of @datetime and adds the specified number of weeks to the
1155 * copy.
1157 * Return value: the newly created #GDateTime which should be freed with
1158 * g_date_time_unref().
1160 * Since: 2.26
1162 GDateTime*
1163 g_date_time_add_weeks (GDateTime *datetime,
1164 gint weeks)
1166 g_return_val_if_fail (datetime != NULL, NULL);
1168 return g_date_time_add_days (datetime, weeks * 7);
1172 * g_date_time_add_days:
1173 * @datetime: a #GDateTime
1174 * @days: the number of days
1176 * Creates a copy of @datetime and adds the specified number of days to the
1177 * copy.
1179 * Return value: the newly created #GDateTime which should be freed with
1180 * g_date_time_unref().
1182 * Since: 2.26
1184 GDateTime*
1185 g_date_time_add_days (GDateTime *datetime,
1186 gint days)
1188 g_return_val_if_fail (datetime != NULL, NULL);
1190 if (days < -3660000 || days > 3660000)
1191 return NULL;
1193 return g_date_time_replace_days (datetime, datetime->days + days);
1197 * g_date_time_add_hours:
1198 * @datetime: a #GDateTime
1199 * @hours: the number of hours to add
1201 * Creates a copy of @datetime and adds the specified number of hours
1203 * Return value: the newly created #GDateTime which should be freed with
1204 * g_date_time_unref().
1206 * Since: 2.26
1208 GDateTime*
1209 g_date_time_add_hours (GDateTime *datetime,
1210 gint hours)
1212 return g_date_time_add (datetime, hours * USEC_PER_HOUR);
1216 * g_date_time_add_minutes:
1217 * @datetime: a #GDateTime
1218 * @minutes: the number of minutes to add
1220 * Creates a copy of @datetime adding the specified number of minutes.
1222 * Return value: the newly created #GDateTime which should be freed with
1223 * g_date_time_unref().
1225 * Since: 2.26
1227 GDateTime*
1228 g_date_time_add_minutes (GDateTime *datetime,
1229 gint minutes)
1231 return g_date_time_add (datetime, minutes * USEC_PER_MINUTE);
1236 * g_date_time_add_seconds:
1237 * @datetime: a #GDateTime
1238 * @seconds: the number of seconds to add
1240 * Creates a copy of @datetime and adds the specified number of seconds.
1242 * Return value: the newly created #GDateTime which should be freed with
1243 * g_date_time_unref().
1245 * Since: 2.26
1247 GDateTime*
1248 g_date_time_add_seconds (GDateTime *datetime,
1249 gdouble seconds)
1251 return g_date_time_add (datetime, seconds * USEC_PER_SECOND);
1255 * g_date_time_add_full:
1256 * @datetime: a #GDateTime
1257 * @years: the number of years to add
1258 * @months: the number of months to add
1259 * @days: the number of days to add
1260 * @hours: the number of hours to add
1261 * @minutes: the number of minutes to add
1262 * @seconds: the number of seconds to add
1264 * Creates a new #GDateTime adding the specified values to the current date and
1265 * time in @datetime.
1267 * Return value: the newly created #GDateTime that should be freed with
1268 * g_date_time_unref().
1270 * Since: 2.26
1272 GDateTime *
1273 g_date_time_add_full (GDateTime *datetime,
1274 gint years,
1275 gint months,
1276 gint days,
1277 gint hours,
1278 gint minutes,
1279 gdouble seconds)
1281 gint year, month, day;
1282 gint64 full_time;
1283 GDateTime *new;
1284 gint interval;
1286 g_return_val_if_fail (datetime != NULL, NULL);
1287 g_date_time_get_ymd (datetime, &year, &month, &day);
1289 months += years * 12;
1291 if (months < -120000 || months > 120000)
1292 return NULL;
1294 if (days < -3660000 || days > 3660000)
1295 return NULL;
1297 year += months / 12;
1298 month += months % 12;
1299 if (month < 1)
1301 month += 12;
1302 year--;
1304 else if (month > 12)
1306 month -= 12;
1307 year++;
1310 day = MIN (day, days_in_months[GREGORIAN_LEAP (year)][month]);
1312 /* full_time is now in unix (local) time */
1313 full_time = datetime->usec / USEC_PER_SECOND + SEC_PER_DAY *
1314 (ymd_to_days (year, month, day) + days - UNIX_EPOCH_START);
1316 interval = g_time_zone_adjust_time (datetime->tz,
1317 g_time_zone_is_dst (datetime->tz,
1318 datetime->interval),
1319 &full_time);
1321 /* move to UTC unix time */
1322 full_time -= g_time_zone_get_offset (datetime->tz, interval);
1324 /* convert back to an instant, add back fractional seconds */
1325 full_time += UNIX_EPOCH_START * SEC_PER_DAY;
1326 full_time = full_time * USEC_PER_SECOND +
1327 datetime->usec % USEC_PER_SECOND;
1329 /* do the actual addition now */
1330 full_time += (hours * USEC_PER_HOUR) +
1331 (minutes * USEC_PER_MINUTE) +
1332 (gint64) (seconds * USEC_PER_SECOND);
1334 /* find the new interval */
1335 interval = g_time_zone_find_interval (datetime->tz,
1336 G_TIME_TYPE_UNIVERSAL,
1337 INSTANT_TO_UNIX (full_time));
1339 /* convert back into local time */
1340 full_time += USEC_PER_SECOND *
1341 g_time_zone_get_offset (datetime->tz, interval);
1343 /* split into days and usec of a new datetime */
1344 new = g_date_time_alloc (datetime->tz);
1345 new->interval = interval;
1346 new->days = full_time / USEC_PER_DAY;
1347 new->usec = full_time % USEC_PER_DAY;
1349 /* XXX validate */
1351 return new;
1354 /* Compare, difference, hash, equal {{{1 */
1356 * g_date_time_compare:
1357 * @dt1: first #GDateTime to compare
1358 * @dt2: second #GDateTime to compare
1360 * A comparison function for #GDateTimes that is suitable
1361 * as a #GCompareFunc. Both #GDateTimes must be non-%NULL.
1363 * Return value: -1, 0 or 1 if @dt1 is less than, equal to or greater
1364 * than @dt2.
1366 * Since: 2.26
1368 gint
1369 g_date_time_compare (gconstpointer dt1,
1370 gconstpointer dt2)
1372 gint64 difference;
1374 difference = g_date_time_difference ((GDateTime *) dt1, (GDateTime *) dt2);
1376 if (difference < 0)
1377 return -1;
1379 else if (difference > 0)
1380 return 1;
1382 else
1383 return 0;
1387 * g_date_time_difference:
1388 * @end: a #GDateTime
1389 * @begin: a #GDateTime
1391 * Calculates the difference in time between @end and @begin. The
1392 * #GTimeSpan that is returned is effectively @end - @begin (ie:
1393 * positive if the first simparameter is larger).
1395 * Return value: the difference between the two #GDateTime, as a time
1396 * span expressed in microseconds.
1398 * Since: 2.26
1400 GTimeSpan
1401 g_date_time_difference (GDateTime *end,
1402 GDateTime *begin)
1404 g_return_val_if_fail (begin != NULL, 0);
1405 g_return_val_if_fail (end != NULL, 0);
1407 return g_date_time_to_instant (end) -
1408 g_date_time_to_instant (begin);
1412 * g_date_time_hash:
1413 * @datetime: a #GDateTime
1415 * Hashes @datetime into a #guint, suitable for use within #GHashTable.
1417 * Return value: a #guint containing the hash
1419 * Since: 2.26
1421 guint
1422 g_date_time_hash (gconstpointer datetime)
1424 return g_date_time_to_instant ((GDateTime *) datetime);
1428 * g_date_time_equal:
1429 * @dt1: a #GDateTime
1430 * @dt2: a #GDateTime
1432 * Checks to see if @dt1 and @dt2 are equal.
1434 * Equal here means that they represent the same moment after converting
1435 * them to the same time zone.
1437 * Return value: %TRUE if @dt1 and @dt2 are equal
1439 * Since: 2.26
1441 gboolean
1442 g_date_time_equal (gconstpointer dt1,
1443 gconstpointer dt2)
1445 return g_date_time_difference ((GDateTime *) dt1, (GDateTime *) dt2) == 0;
1448 /* Year, Month, Day Getters {{{1 */
1450 * g_date_time_get_ymd:
1451 * @datetime: a #GDateTime.
1452 * @year: (out) (allow-none): the return location for the gregorian year, or %NULL.
1453 * @month: (out) (allow-none): the return location for the month of the year, or %NULL.
1454 * @day: (out) (allow-none): the return location for the day of the month, or %NULL.
1456 * Retrieves the Gregorian day, month, and year of a given #GDateTime.
1458 * Since: 2.26
1460 void
1461 g_date_time_get_ymd (GDateTime *datetime,
1462 gint *year,
1463 gint *month,
1464 gint *day)
1466 gint the_year;
1467 gint the_month;
1468 gint the_day;
1469 gint remaining_days;
1470 gint y100_cycles;
1471 gint y4_cycles;
1472 gint y1_cycles;
1473 gint preceding;
1474 gboolean leap;
1476 g_return_if_fail (datetime != NULL);
1478 remaining_days = datetime->days;
1481 * We need to convert an offset in days to its year/month/day representation.
1482 * Leap years makes this a little trickier than it should be, so we use
1483 * 400, 100 and 4 years cycles here to get to the correct year.
1486 /* Our days offset starts sets 0001-01-01 as day 1, if it was day 0 our
1487 * math would be simpler, so let's do it */
1488 remaining_days--;
1490 the_year = (remaining_days / DAYS_IN_400YEARS) * 400 + 1;
1491 remaining_days = remaining_days % DAYS_IN_400YEARS;
1493 y100_cycles = remaining_days / DAYS_IN_100YEARS;
1494 remaining_days = remaining_days % DAYS_IN_100YEARS;
1495 the_year += y100_cycles * 100;
1497 y4_cycles = remaining_days / DAYS_IN_4YEARS;
1498 remaining_days = remaining_days % DAYS_IN_4YEARS;
1499 the_year += y4_cycles * 4;
1501 y1_cycles = remaining_days / 365;
1502 the_year += y1_cycles;
1503 remaining_days = remaining_days % 365;
1505 if (y1_cycles == 4 || y100_cycles == 4) {
1506 g_assert (remaining_days == 0);
1508 /* special case that indicates that the date is actually one year before,
1509 * in the 31th of December */
1510 the_year--;
1511 the_month = 12;
1512 the_day = 31;
1513 goto end;
1516 /* now get the month and the day */
1517 leap = y1_cycles == 3 && (y4_cycles != 24 || y100_cycles == 3);
1519 g_assert (leap == GREGORIAN_LEAP(the_year));
1521 the_month = (remaining_days + 50) >> 5;
1522 preceding = (days_in_year[0][the_month - 1] + (the_month > 2 && leap));
1523 if (preceding > remaining_days)
1525 /* estimate is too large */
1526 the_month -= 1;
1527 preceding -= leap ? days_in_months[1][the_month]
1528 : days_in_months[0][the_month];
1531 remaining_days -= preceding;
1532 g_assert(0 <= remaining_days);
1534 the_day = remaining_days + 1;
1536 end:
1537 if (year)
1538 *year = the_year;
1539 if (month)
1540 *month = the_month;
1541 if (day)
1542 *day = the_day;
1546 * g_date_time_get_year:
1547 * @datetime: A #GDateTime
1549 * Retrieves the year represented by @datetime in the Gregorian calendar.
1551 * Return value: the year represented by @datetime
1553 * Since: 2.26
1555 gint
1556 g_date_time_get_year (GDateTime *datetime)
1558 gint year;
1560 g_return_val_if_fail (datetime != NULL, 0);
1562 g_date_time_get_ymd (datetime, &year, NULL, NULL);
1564 return year;
1568 * g_date_time_get_month:
1569 * @datetime: a #GDateTime
1571 * Retrieves the month of the year represented by @datetime in the Gregorian
1572 * calendar.
1574 * Return value: the month represented by @datetime
1576 * Since: 2.26
1578 gint
1579 g_date_time_get_month (GDateTime *datetime)
1581 gint month;
1583 g_return_val_if_fail (datetime != NULL, 0);
1585 g_date_time_get_ymd (datetime, NULL, &month, NULL);
1587 return month;
1591 * g_date_time_get_day_of_month:
1592 * @datetime: a #GDateTime
1594 * Retrieves the day of the month represented by @datetime in the gregorian
1595 * calendar.
1597 * Return value: the day of the month
1599 * Since: 2.26
1601 gint
1602 g_date_time_get_day_of_month (GDateTime *datetime)
1604 gint day_of_year,
1606 const guint16 *days;
1607 guint16 last = 0;
1609 g_return_val_if_fail (datetime != NULL, 0);
1611 days = days_in_year[GREGORIAN_LEAP (g_date_time_get_year (datetime)) ? 1 : 0];
1612 g_date_time_get_week_number (datetime, NULL, NULL, &day_of_year);
1614 for (i = 1; i <= 12; i++)
1616 if (days [i] >= day_of_year)
1617 return day_of_year - last;
1618 last = days [i];
1621 g_warn_if_reached ();
1622 return 0;
1625 /* Week of year / day of week getters {{{1 */
1627 * g_date_time_get_week_numbering_year:
1628 * @datetime: a #GDateTime
1630 * Returns the ISO 8601 week-numbering year in which the week containing
1631 * @datetime falls.
1633 * This function, taken together with g_date_time_get_week_of_year() and
1634 * g_date_time_get_day_of_week() can be used to determine the full ISO
1635 * week date on which @datetime falls.
1637 * This is usually equal to the normal Gregorian year (as returned by
1638 * g_date_time_get_year()), except as detailed below:
1640 * For Thursday, the week-numbering year is always equal to the usual
1641 * calendar year. For other days, the number is such that every day
1642 * within a complete week (Monday to Sunday) is contained within the
1643 * same week-numbering year.
1645 * For Monday, Tuesday and Wednesday occurring near the end of the year,
1646 * this may mean that the week-numbering year is one greater than the
1647 * calendar year (so that these days have the same week-numbering year
1648 * as the Thursday occurring early in the next year).
1650 * For Friday, Saturaday and Sunday occurring near the start of the year,
1651 * this may mean that the week-numbering year is one less than the
1652 * calendar year (so that these days have the same week-numbering year
1653 * as the Thursday occurring late in the previous year).
1655 * An equivalent description is that the week-numbering year is equal to
1656 * the calendar year containing the majority of the days in the current
1657 * week (Monday to Sunday).
1659 * Note that January 1 0001 in the proleptic Gregorian calendar is a
1660 * Monday, so this function never returns 0.
1662 * Returns: the ISO 8601 week-numbering year for @datetime
1664 * Since: 2.26
1666 gint
1667 g_date_time_get_week_numbering_year (GDateTime *datetime)
1669 gint year, month, day, weekday;
1671 g_date_time_get_ymd (datetime, &year, &month, &day);
1672 weekday = g_date_time_get_day_of_week (datetime);
1674 /* January 1, 2, 3 might be in the previous year if they occur after
1675 * Thursday.
1677 * Jan 1: Friday, Saturday, Sunday => day 1: weekday 5, 6, 7
1678 * Jan 2: Saturday, Sunday => day 2: weekday 6, 7
1679 * Jan 3: Sunday => day 3: weekday 7
1681 * So we have a special case if (day - weekday) <= -4
1683 if (month == 1 && (day - weekday) <= -4)
1684 return year - 1;
1686 /* December 29, 30, 31 might be in the next year if they occur before
1687 * Thursday.
1689 * Dec 31: Monday, Tuesday, Wednesday => day 31: weekday 1, 2, 3
1690 * Dec 30: Monday, Tuesday => day 30: weekday 1, 2
1691 * Dec 29: Monday => day 29: weekday 1
1693 * So we have a special case if (day - weekday) >= 28
1695 else if (month == 12 && (day - weekday) >= 28)
1696 return year + 1;
1698 else
1699 return year;
1703 * g_date_time_get_week_of_year:
1704 * @datetime: a #GDateTime
1706 * Returns the ISO 8601 week number for the week containing @datetime.
1707 * The ISO 8601 week number is the same for every day of the week (from
1708 * Moday through Sunday). That can produce some unusual results
1709 * (described below).
1711 * The first week of the year is week 1. This is the week that contains
1712 * the first Thursday of the year. Equivalently, this is the first week
1713 * that has more than 4 of its days falling within the calendar year.
1715 * The value 0 is never returned by this function. Days contained
1716 * within a year but occurring before the first ISO 8601 week of that
1717 * year are considered as being contained in the last week of the
1718 * previous year. Similarly, the final days of a calendar year may be
1719 * considered as being part of the first ISO 8601 week of the next year
1720 * if 4 or more days of that week are contained within the new year.
1722 * Returns: the ISO 8601 week number for @datetime.
1724 * Since: 2.26
1726 gint
1727 g_date_time_get_week_of_year (GDateTime *datetime)
1729 gint weeknum;
1731 g_return_val_if_fail (datetime != NULL, 0);
1733 g_date_time_get_week_number (datetime, &weeknum, NULL, NULL);
1735 return weeknum;
1739 * g_date_time_get_day_of_week:
1740 * @datetime: a #GDateTime
1742 * Retrieves the ISO 8601 day of the week on which @datetime falls (1 is
1743 * Monday, 2 is Tuesday... 7 is Sunday).
1745 * Return value: the day of the week
1747 * Since: 2.26
1749 gint
1750 g_date_time_get_day_of_week (GDateTime *datetime)
1752 g_return_val_if_fail (datetime != NULL, 0);
1754 return (datetime->days - 1) % 7 + 1;
1757 /* Day of year getter {{{1 */
1759 * g_date_time_get_day_of_year:
1760 * @datetime: a #GDateTime
1762 * Retrieves the day of the year represented by @datetime in the Gregorian
1763 * calendar.
1765 * Return value: the day of the year
1767 * Since: 2.26
1769 gint
1770 g_date_time_get_day_of_year (GDateTime *datetime)
1772 gint doy = 0;
1774 g_return_val_if_fail (datetime != NULL, 0);
1776 g_date_time_get_week_number (datetime, NULL, NULL, &doy);
1777 return doy;
1780 /* Time component getters {{{1 */
1783 * g_date_time_get_hour:
1784 * @datetime: a #GDateTime
1786 * Retrieves the hour of the day represented by @datetime
1788 * Return value: the hour of the day
1790 * Since: 2.26
1792 gint
1793 g_date_time_get_hour (GDateTime *datetime)
1795 g_return_val_if_fail (datetime != NULL, 0);
1797 return (datetime->usec / USEC_PER_HOUR);
1801 * g_date_time_get_minute:
1802 * @datetime: a #GDateTime
1804 * Retrieves the minute of the hour represented by @datetime
1806 * Return value: the minute of the hour
1808 * Since: 2.26
1810 gint
1811 g_date_time_get_minute (GDateTime *datetime)
1813 g_return_val_if_fail (datetime != NULL, 0);
1815 return (datetime->usec % USEC_PER_HOUR) / USEC_PER_MINUTE;
1819 * g_date_time_get_second:
1820 * @datetime: a #GDateTime
1822 * Retrieves the second of the minute represented by @datetime
1824 * Return value: the second represented by @datetime
1826 * Since: 2.26
1828 gint
1829 g_date_time_get_second (GDateTime *datetime)
1831 g_return_val_if_fail (datetime != NULL, 0);
1833 return (datetime->usec % USEC_PER_MINUTE) / USEC_PER_SECOND;
1837 * g_date_time_get_microsecond:
1838 * @datetime: a #GDateTime
1840 * Retrieves the microsecond of the date represented by @datetime
1842 * Return value: the microsecond of the second
1844 * Since: 2.26
1846 gint
1847 g_date_time_get_microsecond (GDateTime *datetime)
1849 g_return_val_if_fail (datetime != NULL, 0);
1851 return (datetime->usec % USEC_PER_SECOND);
1855 * g_date_time_get_seconds:
1856 * @datetime: a #GDateTime
1858 * Retrieves the number of seconds since the start of the last minute,
1859 * including the fractional part.
1861 * Returns: the number of seconds
1863 * Since: 2.26
1865 gdouble
1866 g_date_time_get_seconds (GDateTime *datetime)
1868 g_return_val_if_fail (datetime != NULL, 0);
1870 return (datetime->usec % USEC_PER_MINUTE) / 1000000.0;
1873 /* Exporters {{{1 */
1875 * g_date_time_to_unix:
1876 * @datetime: a #GDateTime
1878 * Gives the Unix time corresponding to @datetime, rounding down to the
1879 * nearest second.
1881 * Unix time is the number of seconds that have elapsed since 1970-01-01
1882 * 00:00:00 UTC, regardless of the time zone associated with @datetime.
1884 * Returns: the Unix time corresponding to @datetime
1886 * Since: 2.26
1888 gint64
1889 g_date_time_to_unix (GDateTime *datetime)
1891 return INSTANT_TO_UNIX (g_date_time_to_instant (datetime));
1895 * g_date_time_to_timeval:
1896 * @datetime: a #GDateTime
1897 * @tv: a #GTimeVal to modify
1899 * Stores the instant in time that @datetime represents into @tv.
1901 * The time contained in a #GTimeVal is always stored in the form of
1902 * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the time
1903 * zone associated with @datetime.
1905 * On systems where 'long' is 32bit (ie: all 32bit systems and all
1906 * Windows systems), a #GTimeVal is incapable of storing the entire
1907 * range of values that #GDateTime is capable of expressing. On those
1908 * systems, this function returns %FALSE to indicate that the time is
1909 * out of range.
1911 * On systems where 'long' is 64bit, this function never fails.
1913 * Returns: %TRUE if successful, else %FALSE
1915 * Since: 2.26
1917 gboolean
1918 g_date_time_to_timeval (GDateTime *datetime,
1919 GTimeVal *tv)
1921 tv->tv_sec = INSTANT_TO_UNIX (g_date_time_to_instant (datetime));
1922 tv->tv_usec = datetime->usec % USEC_PER_SECOND;
1924 return TRUE;
1927 /* Timezone queries {{{1 */
1929 * g_date_time_get_utc_offset:
1930 * @datetime: a #GDateTime
1932 * Determines the offset to UTC in effect at the time and in the time
1933 * zone of @datetime.
1935 * The offset is the number of microseconds that you add to UTC time to
1936 * arrive at local time for the time zone (ie: negative numbers for time
1937 * zones west of GMT, positive numbers for east).
1939 * If @datetime represents UTC time, then the offset is always zero.
1941 * Returns: the number of microseconds that should be added to UTC to
1942 * get the local time
1944 * Since: 2.26
1946 GTimeSpan
1947 g_date_time_get_utc_offset (GDateTime *datetime)
1949 gint offset;
1951 g_return_val_if_fail (datetime != NULL, 0);
1953 offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
1955 return (gint64) offset * USEC_PER_SECOND;
1959 * g_date_time_get_timezone_abbreviation:
1960 * @datetime: a #GDateTime
1962 * Determines the time zone abbreviation to be used at the time and in
1963 * the time zone of @datetime.
1965 * For example, in Toronto this is currently "EST" during the winter
1966 * months and "EDT" during the summer months when daylight savings
1967 * time is in effect.
1969 * Returns: (transfer none): the time zone abbreviation. The returned
1970 * string is owned by the #GDateTime and it should not be
1971 * modified or freed
1973 * Since: 2.26
1975 const gchar *
1976 g_date_time_get_timezone_abbreviation (GDateTime *datetime)
1978 g_return_val_if_fail (datetime != NULL, NULL);
1980 return g_time_zone_get_abbreviation (datetime->tz, datetime->interval);
1984 * g_date_time_is_daylight_savings:
1985 * @datetime: a #GDateTime
1987 * Determines if daylight savings time is in effect at the time and in
1988 * the time zone of @datetime.
1990 * Returns: %TRUE if daylight savings time is in effect
1992 * Since: 2.26
1994 gboolean
1995 g_date_time_is_daylight_savings (GDateTime *datetime)
1997 g_return_val_if_fail (datetime != NULL, FALSE);
1999 return g_time_zone_is_dst (datetime->tz, datetime->interval);
2002 /* Timezone convert {{{1 */
2004 * g_date_time_to_timezone:
2005 * @datetime: a #GDateTime
2006 * @tz: the new #GTimeZone
2008 * Create a new #GDateTime corresponding to the same instant in time as
2009 * @datetime, but in the time zone @tz.
2011 * This call can fail in the case that the time goes out of bounds. For
2012 * example, converting 0001-01-01 00:00:00 UTC to a time zone west of
2013 * Greenwich will fail (due to the year 0 being out of range).
2015 * You should release the return value by calling g_date_time_unref()
2016 * when you are done with it.
2018 * Returns: a new #GDateTime, or %NULL
2020 * Since: 2.26
2022 GDateTime *
2023 g_date_time_to_timezone (GDateTime *datetime,
2024 GTimeZone *tz)
2026 return g_date_time_from_instant (tz, g_date_time_to_instant (datetime));
2030 * g_date_time_to_local:
2031 * @datetime: a #GDateTime
2033 * Creates a new #GDateTime corresponding to the same instant in time as
2034 * @datetime, but in the local time zone.
2036 * This call is equivalent to calling g_date_time_to_timezone() with the
2037 * time zone returned by g_time_zone_new_local().
2039 * Returns: the newly created #GDateTime
2041 * Since: 2.26
2043 GDateTime *
2044 g_date_time_to_local (GDateTime *datetime)
2046 GDateTime *new;
2047 GTimeZone *local;
2049 local = g_time_zone_new_local ();
2050 new = g_date_time_to_timezone (datetime, local);
2051 g_time_zone_unref (local);
2053 return new;
2057 * g_date_time_to_utc:
2058 * @datetime: a #GDateTime
2060 * Creates a new #GDateTime corresponding to the same instant in time as
2061 * @datetime, but in UTC.
2063 * This call is equivalent to calling g_date_time_to_timezone() with the
2064 * time zone returned by g_time_zone_new_utc().
2066 * Returns: the newly created #GDateTime
2068 * Since: 2.26
2070 GDateTime *
2071 g_date_time_to_utc (GDateTime *datetime)
2073 GDateTime *new;
2074 GTimeZone *utc;
2076 utc = g_time_zone_new_utc ();
2077 new = g_date_time_to_timezone (datetime, utc);
2078 g_time_zone_unref (utc);
2080 return new;
2083 /* Format {{{1 */
2085 static void
2086 format_number (GString *str,
2087 gboolean use_alt_digits,
2088 gchar *pad,
2089 gint width,
2090 guint32 number)
2092 const gchar *ascii_digits[10] = {
2093 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
2095 const gchar **digits = ascii_digits;
2096 const gchar *tmp[10];
2097 gint i = 0;
2099 g_return_if_fail (width <= 10);
2101 #ifdef HAVE_LANGINFO_OUTDIGIT
2102 if (use_alt_digits)
2104 static const gchar *alt_digits[10];
2105 static gsize initialised;
2106 /* 2^32 has 10 digits */
2108 if G_UNLIKELY (g_once_init_enter (&initialised))
2110 #define DO_DIGIT(n) \
2111 alt_digits[n] = nl_langinfo (_NL_CTYPE_OUTDIGIT## n ##_MB)
2112 DO_DIGIT(0); DO_DIGIT(1); DO_DIGIT(2); DO_DIGIT(3); DO_DIGIT(4);
2113 DO_DIGIT(5); DO_DIGIT(6); DO_DIGIT(7); DO_DIGIT(8); DO_DIGIT(9);
2114 #undef DO_DIGIT
2115 g_once_init_leave (&initialised, TRUE);
2118 digits = alt_digits;
2120 #endif /* HAVE_LANGINFO_OUTDIGIT */
2124 tmp[i++] = digits[number % 10];
2125 number /= 10;
2127 while (number);
2129 while (pad && i < width)
2130 tmp[i++] = *pad == '0' ? digits[0] : pad;
2132 /* should really be impossible */
2133 g_assert (i <= 10);
2135 while (i)
2136 g_string_append (str, tmp[--i]);
2139 static gboolean g_date_time_format_locale (GDateTime *datetime,
2140 const gchar *format,
2141 GString *outstr,
2142 gboolean locale_is_utf8);
2144 /* g_date_time_format() subroutine that takes a locale-encoded format
2145 * string and produces a locale-encoded date/time string.
2147 static gboolean
2148 g_date_time_locale_format_locale (GDateTime *datetime,
2149 const gchar *format,
2150 GString *outstr,
2151 gboolean locale_is_utf8)
2153 gchar *utf8_format;
2154 gboolean success;
2156 if (locale_is_utf8)
2157 return g_date_time_format_locale (datetime, format, outstr,
2158 locale_is_utf8);
2160 utf8_format = g_locale_to_utf8 (format, -1, NULL, NULL, NULL);
2161 if (!utf8_format)
2162 return FALSE;
2164 success = g_date_time_format_locale (datetime, utf8_format, outstr,
2165 locale_is_utf8);
2166 g_free (utf8_format);
2167 return success;
2170 /* g_date_time_format() subroutine that takes a UTF-8 format
2171 * string and produces a locale-encoded date/time string.
2173 static gboolean
2174 g_date_time_format_locale (GDateTime *datetime,
2175 const gchar *format,
2176 GString *outstr,
2177 gboolean locale_is_utf8)
2179 guint len;
2180 gchar *tmp;
2181 gunichar c;
2182 gboolean alt_digits = FALSE;
2183 gboolean pad_set = FALSE;
2184 gchar *pad = "";
2185 gchar *ampm;
2186 const gchar *tz;
2188 while (*format)
2190 len = strcspn (format, "%");
2191 if (len)
2193 if (locale_is_utf8)
2194 g_string_append_len (outstr, format, len);
2195 else
2197 tmp = g_locale_from_utf8 (format, len, NULL, NULL, NULL);
2198 if (!tmp)
2199 return FALSE;
2200 g_string_append (outstr, tmp);
2201 g_free (tmp);
2205 format += len;
2206 if (!*format)
2207 break;
2209 g_assert (*format == '%');
2210 format++;
2211 if (!*format)
2212 break;
2214 alt_digits = FALSE;
2215 pad_set = FALSE;
2217 next_mod:
2218 c = g_utf8_get_char (format);
2219 format = g_utf8_next_char (format);
2220 switch (c)
2222 case 'a':
2223 g_string_append (outstr, WEEKDAY_ABBR (datetime));
2224 break;
2225 case 'A':
2226 g_string_append (outstr, WEEKDAY_FULL (datetime));
2227 break;
2228 case 'b':
2229 g_string_append (outstr, MONTH_ABBR (datetime));
2230 break;
2231 case 'B':
2232 g_string_append (outstr, MONTH_FULL (datetime));
2233 break;
2234 case 'c':
2236 if (!g_date_time_locale_format_locale (datetime, PREFERRED_DATE_TIME_FMT,
2237 outstr, locale_is_utf8))
2238 return FALSE;
2240 break;
2241 case 'C':
2242 format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
2243 g_date_time_get_year (datetime) / 100);
2244 break;
2245 case 'd':
2246 format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
2247 g_date_time_get_day_of_month (datetime));
2248 break;
2249 case 'e':
2250 format_number (outstr, alt_digits, pad_set ? pad : " ", 2,
2251 g_date_time_get_day_of_month (datetime));
2252 break;
2253 case 'F':
2254 g_string_append_printf (outstr, "%d-%02d-%02d",
2255 g_date_time_get_year (datetime),
2256 g_date_time_get_month (datetime),
2257 g_date_time_get_day_of_month (datetime));
2258 break;
2259 case 'g':
2260 format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
2261 g_date_time_get_week_numbering_year (datetime) % 100);
2262 break;
2263 case 'G':
2264 format_number (outstr, alt_digits, pad_set ? pad : 0, 0,
2265 g_date_time_get_week_numbering_year (datetime));
2266 break;
2267 case 'h':
2268 g_string_append (outstr, MONTH_ABBR (datetime));
2269 break;
2270 case 'H':
2271 format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
2272 g_date_time_get_hour (datetime));
2273 break;
2274 case 'I':
2275 format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
2276 (g_date_time_get_hour (datetime) + 11) % 12 + 1);
2277 break;
2278 case 'j':
2279 format_number (outstr, alt_digits, pad_set ? pad : "0", 3,
2280 g_date_time_get_day_of_year (datetime));
2281 break;
2282 case 'k':
2283 format_number (outstr, alt_digits, pad_set ? pad : " ", 2,
2284 g_date_time_get_hour (datetime));
2285 break;
2286 case 'l':
2287 format_number (outstr, alt_digits, pad_set ? pad : " ", 2,
2288 (g_date_time_get_hour (datetime) + 11) % 12 + 1);
2289 break;
2290 case 'n':
2291 g_string_append_c (outstr, '\n');
2292 break;
2293 case 'm':
2294 format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
2295 g_date_time_get_month (datetime));
2296 break;
2297 case 'M':
2298 format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
2299 g_date_time_get_minute (datetime));
2300 break;
2301 case 'O':
2302 alt_digits = TRUE;
2303 goto next_mod;
2304 case 'p':
2305 ampm = GET_AMPM (datetime);
2306 if (!locale_is_utf8)
2308 ampm = tmp = g_locale_to_utf8 (ampm, -1, NULL, NULL, NULL);
2309 if (!tmp)
2310 return FALSE;
2312 ampm = g_utf8_strup (ampm, -1);
2313 if (!locale_is_utf8)
2315 g_free (tmp);
2316 tmp = g_locale_from_utf8 (ampm, -1, NULL, NULL, NULL);
2317 g_free (ampm);
2318 if (!tmp)
2319 return FALSE;
2320 ampm = tmp;
2322 g_string_append (outstr, ampm);
2323 g_free (ampm);
2324 break;
2325 case 'P':
2326 ampm = GET_AMPM (datetime);
2327 if (!locale_is_utf8)
2329 ampm = tmp = g_locale_to_utf8 (ampm, -1, NULL, NULL, NULL);
2330 if (!tmp)
2331 return FALSE;
2333 ampm = g_utf8_strdown (ampm, -1);
2334 if (!locale_is_utf8)
2336 g_free (tmp);
2337 tmp = g_locale_from_utf8 (ampm, -1, NULL, NULL, NULL);
2338 g_free (ampm);
2339 if (!tmp)
2340 return FALSE;
2341 ampm = tmp;
2343 g_string_append (outstr, ampm);
2344 g_free (ampm);
2345 break;
2346 case 'r':
2348 if (!g_date_time_locale_format_locale (datetime, PREFERRED_12HR_TIME_FMT,
2349 outstr, locale_is_utf8))
2350 return FALSE;
2352 break;
2353 case 'R':
2354 g_string_append_printf (outstr, "%02d:%02d",
2355 g_date_time_get_hour (datetime),
2356 g_date_time_get_minute (datetime));
2357 break;
2358 case 's':
2359 g_string_append_printf (outstr, "%" G_GINT64_FORMAT, g_date_time_to_unix (datetime));
2360 break;
2361 case 'S':
2362 format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
2363 g_date_time_get_second (datetime));
2364 break;
2365 case 't':
2366 g_string_append_c (outstr, '\t');
2367 break;
2368 case 'T':
2369 g_string_append_printf (outstr, "%02d:%02d:%02d",
2370 g_date_time_get_hour (datetime),
2371 g_date_time_get_minute (datetime),
2372 g_date_time_get_second (datetime));
2373 break;
2374 case 'u':
2375 format_number (outstr, alt_digits, 0, 0,
2376 g_date_time_get_day_of_week (datetime));
2377 break;
2378 case 'V':
2379 format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
2380 g_date_time_get_week_of_year (datetime));
2381 break;
2382 case 'w':
2383 format_number (outstr, alt_digits, 0, 0,
2384 g_date_time_get_day_of_week (datetime) % 7);
2385 break;
2386 case 'x':
2388 if (!g_date_time_locale_format_locale (datetime, PREFERRED_DATE_FMT,
2389 outstr, locale_is_utf8))
2390 return FALSE;
2392 break;
2393 case 'X':
2395 if (!g_date_time_locale_format_locale (datetime, PREFERRED_TIME_FMT,
2396 outstr, locale_is_utf8))
2397 return FALSE;
2399 break;
2400 case 'y':
2401 format_number (outstr, alt_digits, pad_set ? pad : "0", 2,
2402 g_date_time_get_year (datetime) % 100);
2403 break;
2404 case 'Y':
2405 format_number (outstr, alt_digits, 0, 0,
2406 g_date_time_get_year (datetime));
2407 break;
2408 case 'z':
2409 if (datetime->tz != NULL)
2411 gint64 offset = g_date_time_get_utc_offset (datetime)
2412 / USEC_PER_SECOND;
2414 g_string_append_printf (outstr, "%+03d%02d",
2415 (int) offset / 3600,
2416 (int) abs(offset) / 60 % 60);
2418 else
2419 g_string_append (outstr, "+0000");
2420 break;
2421 case 'Z':
2422 tz = g_date_time_get_timezone_abbreviation (datetime);
2423 if (!locale_is_utf8)
2425 tz = tmp = g_locale_from_utf8 (tz, -1, NULL, NULL, NULL);
2426 if (!tmp)
2427 return FALSE;
2429 g_string_append (outstr, tz);
2430 if (!locale_is_utf8)
2431 g_free (tmp);
2432 break;
2433 case '%':
2434 g_string_append_c (outstr, '%');
2435 break;
2436 case '-':
2437 pad_set = TRUE;
2438 pad = "";
2439 goto next_mod;
2440 case '_':
2441 pad_set = TRUE;
2442 pad = " ";
2443 goto next_mod;
2444 case '0':
2445 pad_set = TRUE;
2446 pad = "0";
2447 goto next_mod;
2448 default:
2449 return FALSE;
2453 return TRUE;
2457 * g_date_time_format:
2458 * @datetime: A #GDateTime
2459 * @format: a valid UTF-8 string, containing the format for the
2460 * #GDateTime
2462 * Creates a newly allocated string representing the requested @format.
2464 * The format strings understood by this function are a subset of the
2465 * strftime() format language as specified by C99. The \%D, \%U and \%W
2466 * conversions are not supported, nor is the 'E' modifier. The GNU
2467 * extensions \%k, \%l, \%s and \%P are supported, however, as are the
2468 * '0', '_' and '-' modifiers.
2470 * In contrast to strftime(), this function always produces a UTF-8
2471 * string, regardless of the current locale. Note that the rendering of
2472 * many formats is locale-dependent and may not match the strftime()
2473 * output exactly.
2475 * The following format specifiers are supported:
2477 * <variablelist>
2478 * <varlistentry><term>
2479 * <literal>\%a</literal>:
2480 * </term><listitem><simpara>
2481 * the abbreviated weekday name according to the current locale
2482 * </simpara></listitem></varlistentry>
2483 * <varlistentry><term>
2484 * <literal>\%A</literal>:
2485 * </term><listitem><simpara>
2486 * the full weekday name according to the current locale
2487 * </simpara></listitem></varlistentry>
2488 * <varlistentry><term>
2489 * <literal>\%b</literal>:
2490 * </term><listitem><simpara>
2491 * the abbreviated month name according to the current locale
2492 * </simpara></listitem></varlistentry>
2493 * <varlistentry><term>
2494 * <literal>\%B</literal>:
2495 * </term><listitem><simpara>
2496 * the full month name according to the current locale
2497 * </simpara></listitem></varlistentry>
2498 * <varlistentry><term>
2499 * <literal>\%c</literal>:
2500 * </term><listitem><simpara>
2501 * the preferred date and time representation for the current locale
2502 * </simpara></listitem></varlistentry>
2503 * <varlistentry><term>
2504 * <literal>\%C</literal>:
2505 * </term><listitem><simpara>
2506 * The century number (year/100) as a 2-digit integer (00-99)
2507 * </simpara></listitem></varlistentry>
2508 * <varlistentry><term>
2509 * <literal>\%d</literal>:
2510 * </term><listitem><simpara>
2511 * the day of the month as a decimal number (range 01 to 31)
2512 * </simpara></listitem></varlistentry>
2513 * <varlistentry><term>
2514 * <literal>\%e</literal>:
2515 * </term><listitem><simpara>
2516 * the day of the month as a decimal number (range 1 to 31)
2517 * </simpara></listitem></varlistentry>
2518 * <varlistentry><term>
2519 * <literal>\%F</literal>:
2520 * </term><listitem><simpara>
2521 * equivalent to <literal>\%Y-\%m-\%d</literal> (the ISO 8601 date
2522 * format)
2523 * </simpara></listitem></varlistentry>
2524 * <varlistentry><term>
2525 * <literal>\%g</literal>:
2526 * </term><listitem><simpara>
2527 * the last two digits of the ISO 8601 week-based year as a decimal
2528 * number (00-99). This works well with \%V and \%u.
2529 * </simpara></listitem></varlistentry>
2530 * <varlistentry><term>
2531 * <literal>\%G</literal>:
2532 * </term><listitem><simpara>
2533 * the ISO 8601 week-based year as a decimal number. This works well
2534 * with \%V and \%u.
2535 * </simpara></listitem></varlistentry>
2536 * <varlistentry><term>
2537 * <literal>\%h</literal>:
2538 * </term><listitem><simpara>
2539 * equivalent to <literal>\%b</literal>
2540 * </simpara></listitem></varlistentry>
2541 * <varlistentry><term>
2542 * <literal>\%H</literal>:
2543 * </term><listitem><simpara>
2544 * the hour as a decimal number using a 24-hour clock (range 00 to
2545 * 23)
2546 * </simpara></listitem></varlistentry>
2547 * <varlistentry><term>
2548 * <literal>\%I</literal>:
2549 * </term><listitem><simpara>
2550 * the hour as a decimal number using a 12-hour clock (range 01 to
2551 * 12)
2552 * </simpara></listitem></varlistentry>
2553 * <varlistentry><term>
2554 * <literal>\%j</literal>:
2555 * </term><listitem><simpara>
2556 * the day of the year as a decimal number (range 001 to 366)
2557 * </simpara></listitem></varlistentry>
2558 * <varlistentry><term>
2559 * <literal>\%k</literal>:
2560 * </term><listitem><simpara>
2561 * the hour (24-hour clock) as a decimal number (range 0 to 23);
2562 * single digits are preceded by a blank
2563 * </simpara></listitem></varlistentry>
2564 * <varlistentry><term>
2565 * <literal>\%l</literal>:
2566 * </term><listitem><simpara>
2567 * the hour (12-hour clock) as a decimal number (range 1 to 12);
2568 * single digits are preceded by a blank
2569 * </simpara></listitem></varlistentry>
2570 * <varlistentry><term>
2571 * <literal>\%m</literal>:
2572 * </term><listitem><simpara>
2573 * the month as a decimal number (range 01 to 12)
2574 * </simpara></listitem></varlistentry>
2575 * <varlistentry><term>
2576 * <literal>\%M</literal>:
2577 * </term><listitem><simpara>
2578 * the minute as a decimal number (range 00 to 59)
2579 * </simpara></listitem></varlistentry>
2580 * <varlistentry><term>
2581 * <literal>\%p</literal>:
2582 * </term><listitem><simpara>
2583 * either "AM" or "PM" according to the given time value, or the
2584 * corresponding strings for the current locale. Noon is treated as
2585 * "PM" and midnight as "AM".
2586 * </simpara></listitem></varlistentry>
2587 * <varlistentry><term>
2588 * <literal>\%P</literal>:
2589 * </term><listitem><simpara>
2590 * like \%p but lowercase: "am" or "pm" or a corresponding string for
2591 * the current locale
2592 * </simpara></listitem></varlistentry>
2593 * <varlistentry><term>
2594 * <literal>\%r</literal>:
2595 * </term><listitem><simpara>
2596 * the time in a.m. or p.m. notation
2597 * </simpara></listitem></varlistentry>
2598 * <varlistentry><term>
2599 * <literal>\%R</literal>:
2600 * </term><listitem><simpara>
2601 * the time in 24-hour notation (<literal>\%H:\%M</literal>)
2602 * </simpara></listitem></varlistentry>
2603 * <varlistentry><term>
2604 * <literal>\%s</literal>:
2605 * </term><listitem><simpara>
2606 * the number of seconds since the Epoch, that is, since 1970-01-01
2607 * 00:00:00 UTC
2608 * </simpara></listitem></varlistentry>
2609 * <varlistentry><term>
2610 * <literal>\%S</literal>:
2611 * </term><listitem><simpara>
2612 * the second as a decimal number (range 00 to 60)
2613 * </simpara></listitem></varlistentry>
2614 * <varlistentry><term>
2615 * <literal>\%t</literal>:
2616 * </term><listitem><simpara>
2617 * a tab character
2618 * </simpara></listitem></varlistentry>
2619 * <varlistentry><term>
2620 * <literal>\%T</literal>:
2621 * </term><listitem><simpara>
2622 * the time in 24-hour notation with seconds (<literal>\%H:\%M:\%S</literal>)
2623 * </simpara></listitem></varlistentry>
2624 * <varlistentry><term>
2625 * <literal>\%u</literal>:
2626 * </term><listitem><simpara>
2627 * the ISO 8601 standard day of the week as a decimal, range 1 to 7,
2628 * Monday being 1. This works well with \%G and \%V.
2629 * </simpara></listitem></varlistentry>
2630 * <varlistentry><term>
2631 * <literal>\%V</literal>:
2632 * </term><listitem><simpara>
2633 * the ISO 8601 standard week number of the current year as a decimal
2634 * number, range 01 to 53, where week 1 is the first week that has at
2635 * least 4 days in the new year. See g_date_time_get_week_of_year().
2636 * This works well with \%G and \%u.
2637 * </simpara></listitem></varlistentry>
2638 * <varlistentry><term>
2639 * <literal>\%w</literal>:
2640 * </term><listitem><simpara>
2641 * the day of the week as a decimal, range 0 to 6, Sunday being 0.
2642 * This is not the ISO 8601 standard format -- use \%u instead.
2643 * </simpara></listitem></varlistentry>
2644 * <varlistentry><term>
2645 * <literal>\%x</literal>:
2646 * </term><listitem><simpara>
2647 * the preferred date representation for the current locale without
2648 * the time
2649 * </simpara></listitem></varlistentry>
2650 * <varlistentry><term>
2651 * <literal>\%X</literal>:
2652 * </term><listitem><simpara>
2653 * the preferred time representation for the current locale without
2654 * the date
2655 * </simpara></listitem></varlistentry>
2656 * <varlistentry><term>
2657 * <literal>\%y</literal>:
2658 * </term><listitem><simpara>
2659 * the year as a decimal number without the century
2660 * </simpara></listitem></varlistentry>
2661 * <varlistentry><term>
2662 * <literal>\%Y</literal>:
2663 * </term><listitem><simpara>
2664 * the year as a decimal number including the century
2665 * </simpara></listitem></varlistentry>
2666 * <varlistentry><term>
2667 * <literal>\%z</literal>:
2668 * </term><listitem><simpara>
2669 * the time-zone as hour offset from UTC
2670 * </simpara></listitem></varlistentry>
2671 * <varlistentry><term>
2672 * <literal>\%Z</literal>:
2673 * </term><listitem><simpara>
2674 * the time zone or name or abbreviation
2675 * </simpara></listitem></varlistentry>
2676 * <varlistentry><term>
2677 * <literal>\%\%</literal>:
2678 * </term><listitem><simpara>
2679 * a literal <literal>\%</literal> character
2680 * </simpara></listitem></varlistentry>
2681 * </variablelist>
2683 * Some conversion specifications can be modified by preceding the
2684 * conversion specifier by one or more modifier characters. The
2685 * following modifiers are supported for many of the numeric
2686 * conversions:
2687 * <variablelist>
2688 * <varlistentry>
2689 * <term>O</term>
2690 * <listitem>
2691 * Use alternative numeric symbols, if the current locale
2692 * supports those.
2693 * </listitem>
2694 * </varlistentry>
2695 * <varlistentry>
2696 * <term>_</term>
2697 * <listitem>
2698 * Pad a numeric result with spaces.
2699 * This overrides the default padding for the specifier.
2700 * </listitem>
2701 * </varlistentry>
2702 * <varlistentry>
2703 * <term>-</term>
2704 * <listitem>
2705 * Do not pad a numeric result.
2706 * This overrides the default padding for the specifier.
2707 * </listitem>
2708 * </varlistentry>
2709 * <varlistentry>
2710 * <term>0</term>
2711 * <listitem>
2712 * Pad a numeric result with zeros.
2713 * This overrides the default padding for the specifier.
2714 * </listitem>
2715 * </varlistentry>
2716 * </variablelist>
2718 * Returns: a newly allocated string formatted to the requested format
2719 * or %NULL in the case that there was an error. The string
2720 * should be freed with g_free().
2722 * Since: 2.26
2724 gchar *
2725 g_date_time_format (GDateTime *datetime,
2726 const gchar *format)
2728 GString *outstr;
2729 gchar *utf8;
2730 gboolean locale_is_utf8 = g_get_charset (NULL);
2732 g_return_val_if_fail (datetime != NULL, NULL);
2733 g_return_val_if_fail (format != NULL, NULL);
2734 g_return_val_if_fail (g_utf8_validate (format, -1, NULL), NULL);
2736 outstr = g_string_sized_new (strlen (format) * 2);
2738 if (!g_date_time_format_locale (datetime, format, outstr, locale_is_utf8))
2740 g_string_free (outstr, TRUE);
2741 return NULL;
2744 if (locale_is_utf8)
2745 return g_string_free (outstr, FALSE);
2747 utf8 = g_locale_to_utf8 (outstr->str, outstr->len, NULL, NULL, NULL);
2748 g_string_free (outstr, TRUE);
2749 return utf8;
2753 /* Epilogue {{{1 */
2754 /* vim:set foldmethod=marker: */