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
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
42 * This document is provided "as is". No warranties are made as
57 #ifdef HAVE_LANGINFO_TIME
61 #include "gdatetime.h"
65 #include "gfileutils.h"
68 #include "gmappedfile.h"
69 #include "gstrfuncs.h"
70 #include "gtestutils.h"
72 #include "gtimezone.h"
79 #endif /* !G_OS_WIN32 */
84 * @short_description: A structure representing Date and Time
85 * @see_also: #GTimeZone
87 * #GDateTime is a structure that combines a Gregorian date and time
88 * into a single structure. It provides many conversion and methods to
89 * manipulate dates and times. Time precision is provided down to
90 * microseconds and the time can range (proleptically) from 0001-01-01
91 * 00:00:00 to 9999-12-31 23:59:59.999999. #GDateTime follows POSIX
92 * time in the sense that it is oblivious to leap seconds.
94 * #GDateTime is an immutable object; once it has been created it cannot
95 * be modified further. All modifiers will create a new #GDateTime.
96 * Nearly all such functions can fail due to the date or time going out
97 * of range, in which case %NULL will be returned.
99 * #GDateTime is reference counted: the reference count is increased by calling
100 * g_date_time_ref() and decreased by calling g_date_time_unref(). When the
101 * reference count drops to 0, the resources allocated by the #GDateTime
102 * structure are released.
104 * Many parts of the API may produce non-obvious results. As an
105 * example, adding two months to January 31st will yield March 31st
106 * whereas adding one month and then one month again will yield either
107 * March 28th or March 29th. Also note that adding 24 hours is not
108 * always the same as adding one day (since days containing daylight
109 * savings time transitions are either 23 or 25 hours in length).
111 * #GDateTime is available since GLib 2.26.
116 /* 1 is 0001-01-01 in Proleptic Gregorian */
119 /* Microsecond timekeeping within Day */
122 /* TimeZone information */
126 volatile gint ref_count;
129 /* Time conversion {{{1 */
131 #define UNIX_EPOCH_START 719163
132 #define INSTANT_TO_UNIX(instant) \
133 ((instant)/USEC_PER_SECOND - UNIX_EPOCH_START * SEC_PER_DAY)
134 #define UNIX_TO_INSTANT(unix) \
135 (((unix) + UNIX_EPOCH_START * SEC_PER_DAY) * USEC_PER_SECOND)
137 #define DAYS_IN_4YEARS 1461 /* days in 4 years */
138 #define DAYS_IN_100YEARS 36524 /* days in 100 years */
139 #define DAYS_IN_400YEARS 146097 /* days in 400 years */
141 #define USEC_PER_SECOND (G_GINT64_CONSTANT (1000000))
142 #define USEC_PER_MINUTE (G_GINT64_CONSTANT (60000000))
143 #define USEC_PER_HOUR (G_GINT64_CONSTANT (3600000000))
144 #define USEC_PER_MILLISECOND (G_GINT64_CONSTANT (1000))
145 #define USEC_PER_DAY (G_GINT64_CONSTANT (86400000000))
146 #define SEC_PER_DAY (G_GINT64_CONSTANT (86400))
148 #define SECS_PER_MINUTE (60)
149 #define SECS_PER_HOUR (60 * SECS_PER_MINUTE)
150 #define SECS_PER_DAY (24 * SECS_PER_HOUR)
151 #define SECS_PER_YEAR (365 * SECS_PER_DAY)
152 #define SECS_PER_JULIAN (DAYS_PER_PERIOD * SECS_PER_DAY)
154 #define GREGORIAN_LEAP(y) ((((y) % 4) == 0) && (!((((y) % 100) == 0) && (((y) % 400) != 0))))
155 #define JULIAN_YEAR(d) ((d)->julian / 365.25)
156 #define DAYS_PER_PERIOD (G_GINT64_CONSTANT (2914695))
158 static const guint16 days_in_months[2][13] =
160 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
161 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
164 static const guint16 days_in_year[2][13] =
166 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
167 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
170 #ifdef HAVE_LANGINFO_TIME
172 #define GET_AMPM(d) ((g_date_time_get_hour (d) < 12) ? \
173 nl_langinfo (AM_STR) : \
174 nl_langinfo (PM_STR))
176 #define PREFERRED_DATE_TIME_FMT nl_langinfo (D_T_FMT)
177 #define PREFERRED_DATE_FMT nl_langinfo (D_FMT)
178 #define PREFERRED_TIME_FMT nl_langinfo (T_FMT)
179 #define PREFERRED_TIME_FMT nl_langinfo (T_FMT)
180 #define PREFERRED_12HR_TIME_FMT nl_langinfo (T_FMT_AMPM)
182 static const gint weekday_item[2][7] =
184 { ABDAY_2, ABDAY_3, ABDAY_4, ABDAY_5, ABDAY_6, ABDAY_7, ABDAY_1 },
185 { DAY_2, DAY_3, DAY_4, DAY_5, DAY_6, DAY_7, DAY_1 }
188 static const gint month_item[2][12] =
190 { ABMON_1, ABMON_2, ABMON_3, ABMON_4, ABMON_5, ABMON_6, ABMON_7, ABMON_8, ABMON_9, ABMON_10, ABMON_11, ABMON_12 },
191 { MON_1, MON_2, MON_3, MON_4, MON_5, MON_6, MON_7, MON_8, MON_9, MON_10, MON_11, MON_12 },
194 #define WEEKDAY_ABBR(d) nl_langinfo (weekday_item[0][g_date_time_get_day_of_week (d) - 1])
195 #define WEEKDAY_FULL(d) nl_langinfo (weekday_item[1][g_date_time_get_day_of_week (d) - 1])
196 #define MONTH_ABBR(d) nl_langinfo (month_item[0][g_date_time_get_month (d) - 1])
197 #define MONTH_FULL(d) nl_langinfo (month_item[1][g_date_time_get_month (d) - 1])
201 #define GET_AMPM(d) ((g_date_time_get_hour (d) < 12) \
202 /* Translators: 'before midday' indicator */ \
203 ? C_("GDateTime", "AM") \
204 /* Translators: 'after midday' indicator */ \
205 : C_("GDateTime", "PM"))
207 /* Translators: this is the preferred format for expressing the date and the time */
208 #define PREFERRED_DATE_TIME_FMT C_("GDateTime", "%a %b %e %H:%M:%S %Y")
210 /* Translators: this is the preferred format for expressing the date */
211 #define PREFERRED_DATE_FMT C_("GDateTime", "%m/%d/%y")
213 /* Translators: this is the preferred format for expressing the time */
214 #define PREFERRED_TIME_FMT C_("GDateTime", "%H:%M:%S")
216 /* Translators: this is the preferred format for expressing 12 hour time */
217 #define PREFERRED_12HR_TIME_FMT C_("GDateTime", "%I:%M:%S %p")
219 #define WEEKDAY_ABBR(d) (get_weekday_name_abbr (g_date_time_get_day_of_week (d)))
220 #define WEEKDAY_FULL(d) (get_weekday_name (g_date_time_get_day_of_week (d)))
221 #define MONTH_ABBR(d) (get_month_name_abbr (g_date_time_get_month (d)))
222 #define MONTH_FULL(d) (get_month_name (g_date_time_get_month (d)))
225 get_month_name (gint month)
230 return C_("full month name", "January");
232 return C_("full month name", "February");
234 return C_("full month name", "March");
236 return C_("full month name", "April");
238 return C_("full month name", "May");
240 return C_("full month name", "June");
242 return C_("full month name", "July");
244 return C_("full month name", "August");
246 return C_("full month name", "September");
248 return C_("full month name", "October");
250 return C_("full month name", "November");
252 return C_("full month name", "December");
255 g_warning ("Invalid month number %d", month);
262 get_month_name_abbr (gint month)
267 return C_("abbreviated month name", "Jan");
269 return C_("abbreviated month name", "Feb");
271 return C_("abbreviated month name", "Mar");
273 return C_("abbreviated month name", "Apr");
275 return C_("abbreviated month name", "May");
277 return C_("abbreviated month name", "Jun");
279 return C_("abbreviated month name", "Jul");
281 return C_("abbreviated month name", "Aug");
283 return C_("abbreviated month name", "Sep");
285 return C_("abbreviated month name", "Oct");
287 return C_("abbreviated month name", "Nov");
289 return C_("abbreviated month name", "Dec");
292 g_warning ("Invalid month number %d", month);
299 get_weekday_name (gint day)
304 return C_("full weekday name", "Monday");
306 return C_("full weekday name", "Tuesday");
308 return C_("full weekday name", "Wednesday");
310 return C_("full weekday name", "Thursday");
312 return C_("full weekday name", "Friday");
314 return C_("full weekday name", "Saturday");
316 return C_("full weekday name", "Sunday");
319 g_warning ("Invalid week day number %d", day);
326 get_weekday_name_abbr (gint day)
331 return C_("abbreviated weekday name", "Mon");
333 return C_("abbreviated weekday name", "Tue");
335 return C_("abbreviated weekday name", "Wed");
337 return C_("abbreviated weekday name", "Thu");
339 return C_("abbreviated weekday name", "Fri");
341 return C_("abbreviated weekday name", "Sat");
343 return C_("abbreviated weekday name", "Sun");
346 g_warning ("Invalid week day number %d", day);
352 #endif /* HAVE_LANGINFO_TIME */
355 ymd_to_days (gint year,
361 days = (year - 1) * 365 + ((year - 1) / 4) - ((year - 1) / 100)
362 + ((year - 1) / 400);
364 days += days_in_year[0][month - 1];
365 if (GREGORIAN_LEAP (year) && month > 2)
374 g_date_time_get_week_number (GDateTime *datetime,
379 gint a, b, c, d, e, f, g, n, s, month, day, year;
381 g_date_time_get_ymd (datetime, &year, &month, &day);
385 a = g_date_time_get_year (datetime) - 1;
386 b = (a / 4) - (a / 100) + (a / 400);
387 c = ((a - 1) / 4) - ((a - 1) / 100) + ((a - 1) / 400);
390 f = day - 1 + (31 * (month - 1));
395 b = (a / 4) - (a / 100) + (a / 400);
396 c = ((a - 1) / 4) - ((a - 1) / 100) + ((a - 1) / 400);
399 f = day + (((153 * (month - 3)) + 2) / 5) + 58 + s;
409 *week_number = 53 - ((g - s) / 5);
410 else if (n > 364 + s)
413 *week_number = (n / 7) + 1;
417 *day_of_week = d + 1;
420 *day_of_year = f + 1;
426 g_date_time_alloc (GTimeZone *tz)
430 datetime = g_slice_new0 (GDateTime);
431 datetime->tz = g_time_zone_ref (tz);
432 datetime->ref_count = 1;
439 * @datetime: a #GDateTime
441 * Atomically increments the reference count of @datetime by one.
443 * Return value: the #GDateTime with the reference count increased
448 g_date_time_ref (GDateTime *datetime)
450 g_return_val_if_fail (datetime != NULL, NULL);
451 g_return_val_if_fail (datetime->ref_count > 0, NULL);
453 g_atomic_int_inc (&datetime->ref_count);
460 * @datetime: a #GDateTime
462 * Atomically decrements the reference count of @datetime by one.
464 * When the reference count reaches zero, the resources allocated by
465 * @datetime are freed
470 g_date_time_unref (GDateTime *datetime)
472 g_return_if_fail (datetime != NULL);
473 g_return_if_fail (datetime->ref_count > 0);
475 if (g_atomic_int_dec_and_test (&datetime->ref_count))
477 g_time_zone_unref (datetime->tz);
478 g_slice_free (GDateTime, datetime);
482 /* Internal state transformers {{{1 */
484 * g_date_time_to_instant:
485 * @datetime: a #GDateTime
487 * Convert a @datetime into an instant.
489 * An instant is a number that uniquely describes a particular
490 * microsecond in time, taking time zone considerations into account.
491 * (ie: "03:00 -0400" is the same instant as "02:00 -0500").
493 * An instant is always positive but we use a signed return value to
494 * avoid troubles with C.
497 g_date_time_to_instant (GDateTime *datetime)
501 offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
502 offset *= USEC_PER_SECOND;
504 return datetime->days * USEC_PER_DAY + datetime->usec - offset;
508 * g_date_time_from_instant:
510 * @instant: a instant in time
512 * Creates a #GDateTime from a time zone and an instant.
514 * This might fail if the time ends up being out of range.
517 g_date_time_from_instant (GTimeZone *tz,
523 if (instant < 0 || instant > G_GINT64_CONSTANT (1000000000000000000))
526 datetime = g_date_time_alloc (tz);
527 datetime->interval = g_time_zone_find_interval (tz,
528 G_TIME_TYPE_UNIVERSAL,
529 INSTANT_TO_UNIX (instant));
530 offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
531 offset *= USEC_PER_SECOND;
535 datetime->days = instant / USEC_PER_DAY;
536 datetime->usec = instant % USEC_PER_DAY;
538 if (datetime->days < 1 || 3652059 < datetime->days)
540 g_date_time_unref (datetime);
549 * g_date_time_deal_with_date_change:
550 * @datetime: a #GDateTime
552 * This function should be called whenever the date changes by adding
553 * days, months or years. It does three things.
555 * First, we ensure that the date falls between 0001-01-01 and
556 * 9999-12-31 and return %FALSE if it does not.
558 * Next we update the ->interval field.
560 * Finally, we ensure that the resulting date and time pair exists (by
561 * ensuring that our time zone has an interval containing it) and
562 * adjusting as required. For example, if we have the time 02:30:00 on
563 * March 13 2010 in Toronto and we add 1 day to it, we would end up with
564 * 2:30am on March 14th, which doesn't exist. In that case, we bump the
568 g_date_time_deal_with_date_change (GDateTime *datetime)
574 if (datetime->days < 1 || datetime->days > 3652059)
577 was_dst = g_time_zone_is_dst (datetime->tz, datetime->interval);
579 full_time = datetime->days * USEC_PER_DAY + datetime->usec;
582 usec = full_time % USEC_PER_SECOND;
583 full_time /= USEC_PER_SECOND;
584 full_time -= UNIX_EPOCH_START * SEC_PER_DAY;
586 datetime->interval = g_time_zone_adjust_time (datetime->tz,
589 full_time += UNIX_EPOCH_START * SEC_PER_DAY;
590 full_time *= USEC_PER_SECOND;
593 datetime->days = full_time / USEC_PER_DAY;
594 datetime->usec = full_time % USEC_PER_DAY;
596 /* maybe daylight time caused us to shift to a different day,
597 * but it definitely didn't push us into a different year */
602 g_date_time_replace_days (GDateTime *datetime,
607 new = g_date_time_alloc (datetime->tz);
608 new->interval = datetime->interval;
609 new->usec = datetime->usec;
612 if (!g_date_time_deal_with_date_change (new))
614 g_date_time_unref (new);
621 /* now/unix/timeval Constructors {{{1 */
624 * g_date_time_new_from_timeval:
628 * Creates a #GDateTime corresponding to the given #GTimeVal @tv in the
629 * given time zone @tz.
631 * The time contained in a #GTimeVal is always stored in the form of
632 * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the
635 * This call can fail (returning %NULL) if @tv represents a time outside
636 * of the supported range of #GDateTime.
638 * You should release the return value by calling g_date_time_unref()
639 * when you are done with it.
641 * Returns: a new #GDateTime, or %NULL
646 g_date_time_new_from_timeval (GTimeZone *tz,
649 return g_date_time_from_instant (tz, tv->tv_usec +
650 UNIX_TO_INSTANT (tv->tv_sec));
654 * g_date_time_new_from_unix:
658 * Creates a #GDateTime corresponding to the given Unix time @t in the
659 * given time zone @tz.
661 * Unix time is the number of seconds that have elapsed since 1970-01-01
662 * 00:00:00 UTC, regardless of the time zone given.
664 * This call can fail (returning %NULL) if @t represents a time outside
665 * of the supported range of #GDateTime.
667 * You should release the return value by calling g_date_time_unref()
668 * when you are done with it.
670 * Returns: a new #GDateTime, or %NULL
675 g_date_time_new_from_unix (GTimeZone *tz,
678 return g_date_time_from_instant (tz, UNIX_TO_INSTANT (secs));
682 * g_date_time_new_now:
685 * Creates a #GDateTime corresponding to this exact instant in the given
686 * time zone @tz. The time is as accurate as the system allows, to a
687 * maximum accuracy of 1 microsecond.
689 * This function will always succeed unless the system clock is set to
690 * truly insane values (or unless GLib is still being used after the
693 * You should release the return value by calling g_date_time_unref()
694 * when you are done with it.
696 * Returns: a new #GDateTime, or %NULL
701 g_date_time_new_now (GTimeZone *tz)
705 g_get_current_time (&tv);
707 return g_date_time_new_from_timeval (tz, &tv);
711 * g_date_time_new_now_local:
713 * Creates a #GDateTime corresponding to this exact instant in the local
716 * This is equivalent to calling g_date_time_new_now() with the time
717 * zone returned by g_time_zone_new_local().
719 * Returns: a new #GDateTime, or %NULL
724 g_date_time_new_now_local (void)
729 local = g_time_zone_new_local ();
730 datetime = g_date_time_new_now (local);
731 g_time_zone_unref (local);
737 * g_date_time_new_now_utc:
739 * Creates a #GDateTime corresponding to this exact instant in UTC.
741 * This is equivalent to calling g_date_time_new_now() with the time
742 * zone returned by g_time_zone_new_utc().
744 * Returns: a new #GDateTime, or %NULL
749 g_date_time_new_now_utc (void)
754 utc = g_time_zone_new_utc ();
755 datetime = g_date_time_new_now (utc);
756 g_time_zone_unref (utc);
762 * g_date_time_new_from_unix_local:
765 * Creates a #GDateTime corresponding to the given Unix time @t in the
768 * Unix time is the number of seconds that have elapsed since 1970-01-01
769 * 00:00:00 UTC, regardless of the local time offset.
771 * This call can fail (returning %NULL) if @t represents a time outside
772 * of the supported range of #GDateTime.
774 * You should release the return value by calling g_date_time_unref()
775 * when you are done with it.
777 * Returns: a new #GDateTime, or %NULL
782 g_date_time_new_from_unix_local (gint64 t)
787 local = g_time_zone_new_local ();
788 datetime = g_date_time_new_from_unix (local, t);
789 g_time_zone_unref (local);
795 * g_date_time_new_from_unix_utc:
798 * Creates a #GDateTime corresponding to the given Unix time @t in UTC.
800 * Unix time is the number of seconds that have elapsed since 1970-01-01
803 * This call can fail (returning %NULL) if @t represents a time outside
804 * of the supported range of #GDateTime.
806 * You should release the return value by calling g_date_time_unref()
807 * when you are done with it.
809 * Returns: a new #GDateTime, or %NULL
814 g_date_time_new_from_unix_utc (gint64 t)
819 utc = g_time_zone_new_utc ();
820 datetime = g_date_time_new_from_unix (utc, t);
821 g_time_zone_unref (utc);
827 * g_date_time_new_from_timeval_local:
830 * Creates a #GDateTime corresponding to the given #GTimeVal @tv in the
833 * The time contained in a #GTimeVal is always stored in the form of
834 * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the
837 * This call can fail (returning %NULL) if @tv represents a time outside
838 * of the supported range of #GDateTime.
840 * You should release the return value by calling g_date_time_unref()
841 * when you are done with it.
843 * Returns: a new #GDateTime, or %NULL
848 g_date_time_new_from_timeval_local (const GTimeVal *tv)
853 local = g_time_zone_new_local ();
854 datetime = g_date_time_new_from_timeval (local, tv);
855 g_time_zone_unref (local);
861 * g_date_time_new_from_timeval_utc:
864 * Creates a #GDateTime corresponding to the given #GTimeVal @tv in UTC.
866 * The time contained in a #GTimeVal is always stored in the form of
867 * seconds elapsed since 1970-01-01 00:00:00 UTC.
869 * This call can fail (returning %NULL) if @tv represents a time outside
870 * of the supported range of #GDateTime.
872 * You should release the return value by calling g_date_time_unref()
873 * when you are done with it.
875 * Returns: a new #GDateTime, or %NULL
880 g_date_time_new_from_timeval_utc (const GTimeVal *tv)
885 utc = g_time_zone_new_utc ();
886 datetime = g_date_time_new_from_timeval (utc, tv);
887 g_time_zone_unref (utc);
892 /* full new functions {{{1 */
897 * @year: the year component of the date
898 * @month: the month component of the date
899 * @day: the day component of the date
900 * @hour: the hour component of the date
901 * @minute: the minute component of the date
902 * @seconds: the number of seconds past the minute
904 * Creates a new #GDateTime corresponding to the given date and time in
907 * The @year must be between 1 and 9999, @month between 1 and 12 and @day
908 * between 1 and 28, 29, 30 or 31 depending on the month and the year.
910 * @hour must be between 0 and 23 and @minute must be between 0 and 59.
912 * @seconds must be at least 0.0 and must be strictly less than 60.0.
913 * It will be rounded down to the nearest microsecond.
915 * If the given time is not representable in the given time zone (for
916 * example, 02:30 on March 14th 2010 in Toronto, due to daylight savings
917 * time) then the time will be rounded up to the nearest existing time
918 * (in this case, 03:00). If this matters to you then you should verify
919 * the return value for containing the same as the numbers you gave.
921 * In the case that the given time is ambiguous in the given time zone
922 * (for example, 01:30 on November 7th 2010 in Toronto, due to daylight
923 * savings time) then the time falling within standard (ie:
924 * non-daylight) time is taken.
926 * It not considered a programmer error for the values to this function
927 * to be out of range, but in the case that they are, the function will
930 * You should release the return value by calling g_date_time_unref()
931 * when you are done with it.
933 * Returns: a new #GDateTime, or %NULL
938 g_date_time_new (GTimeZone *tz,
949 datetime = g_date_time_alloc (tz);
950 datetime->days = ymd_to_days (year, month, day);
951 datetime->usec = (hour * USEC_PER_HOUR)
952 + (minute * USEC_PER_MINUTE)
953 + (gint64) (seconds * USEC_PER_SECOND);
955 full_time = SEC_PER_DAY *
956 (ymd_to_days (year, month, day) - UNIX_EPOCH_START) +
957 SECS_PER_HOUR * hour +
958 SECS_PER_MINUTE * minute +
961 datetime->interval = g_time_zone_adjust_time (datetime->tz,
962 G_TIME_TYPE_STANDARD,
965 full_time += UNIX_EPOCH_START * SEC_PER_DAY;
966 datetime->days = full_time / SEC_PER_DAY;
967 datetime->usec = (full_time % SEC_PER_DAY) * USEC_PER_SECOND;
968 datetime->usec += ((int) (seconds * USEC_PER_SECOND)) % USEC_PER_SECOND;
974 * g_date_time_new_local:
975 * @year: the year component of the date
976 * @month: the month component of the date
977 * @day: the day component of the date
978 * @hour: the hour component of the date
979 * @minute: the minute component of the date
980 * @seconds: the number of seconds past the minute
982 * Creates a new #GDateTime corresponding to the given date and time in
983 * the local time zone.
985 * This call is equivalent to calling g_date_time_new() with the time
986 * zone returned by g_time_zone_new_local().
988 * Returns: a #GDateTime, or %NULL
993 g_date_time_new_local (gint year,
1000 GDateTime *datetime;
1003 local = g_time_zone_new_local ();
1004 datetime = g_date_time_new (local, year, month, day, hour, minute, seconds);
1005 g_time_zone_unref (local);
1011 * g_date_time_new_utc:
1012 * @year: the year component of the date
1013 * @month: the month component of the date
1014 * @day: the day component of the date
1015 * @hour: the hour component of the date
1016 * @minute: the minute component of the date
1017 * @seconds: the number of seconds past the minute
1019 * Creates a new #GDateTime corresponding to the given date and time in
1022 * This call is equivalent to calling g_date_time_new() with the time
1023 * zone returned by g_time_zone_new_utc().
1025 * Returns: a #GDateTime, or %NULL
1030 g_date_time_new_utc (gint year,
1037 GDateTime *datetime;
1040 utc = g_time_zone_new_utc ();
1041 datetime = g_date_time_new (utc, year, month, day, hour, minute, seconds);
1042 g_time_zone_unref (utc);
1051 * @datetime: a #GDateTime
1052 * @timespan: a #GTimeSpan
1054 * Creates a copy of @datetime and adds the specified timespan to the copy.
1056 * Return value: the newly created #GDateTime which should be freed with
1057 * g_date_time_unref().
1062 g_date_time_add (GDateTime *datetime,
1065 return g_date_time_from_instant (datetime->tz, timespan +
1066 g_date_time_to_instant (datetime));
1070 * g_date_time_add_years:
1071 * @datetime: a #GDateTime
1072 * @years: the number of years
1074 * Creates a copy of @datetime and adds the specified number of years to the
1077 * Return value: the newly created #GDateTime which should be freed with
1078 * g_date_time_unref().
1083 g_date_time_add_years (GDateTime *datetime,
1086 gint year, month, day;
1088 g_return_val_if_fail (datetime != NULL, NULL);
1090 if (years < -10000 || years > 10000)
1093 g_date_time_get_ymd (datetime, &year, &month, &day);
1096 /* only possible issue is if we've entered a year with no February 29
1098 if (month == 2 && day == 29 && !GREGORIAN_LEAP (year))
1101 return g_date_time_replace_days (datetime, ymd_to_days (year, month, day));
1105 * g_date_time_add_months:
1106 * @datetime: a #GDateTime
1107 * @months: the number of months
1109 * Creates a copy of @datetime and adds the specified number of months to the
1112 * Return value: the newly created #GDateTime which should be freed with
1113 * g_date_time_unref().
1118 g_date_time_add_months (GDateTime *datetime,
1121 gint year, month, day;
1123 g_return_val_if_fail (datetime != NULL, NULL);
1124 g_date_time_get_ymd (datetime, &year, &month, &day);
1126 if (months < -120000 || months > 120000)
1129 year += months / 12;
1130 month += months % 12;
1136 else if (month > 12)
1142 day = MIN (day, days_in_months[GREGORIAN_LEAP (year)][month]);
1144 return g_date_time_replace_days (datetime, ymd_to_days (year, month, day));
1148 * g_date_time_add_weeks:
1149 * @datetime: a #GDateTime
1150 * @weeks: the number of weeks
1152 * Creates a copy of @datetime and adds the specified number of weeks to the
1155 * Return value: the newly created #GDateTime which should be freed with
1156 * g_date_time_unref().
1161 g_date_time_add_weeks (GDateTime *datetime,
1164 g_return_val_if_fail (datetime != NULL, NULL);
1166 return g_date_time_add_days (datetime, weeks * 7);
1170 * g_date_time_add_days:
1171 * @datetime: a #GDateTime
1172 * @days: the number of days
1174 * Creates a copy of @datetime and adds the specified number of days to the
1177 * Return value: the newly created #GDateTime which should be freed with
1178 * g_date_time_unref().
1183 g_date_time_add_days (GDateTime *datetime,
1186 g_return_val_if_fail (datetime != NULL, NULL);
1188 if (days < -3660000 || days > 3660000)
1191 return g_date_time_replace_days (datetime, datetime->days + days);
1195 * g_date_time_add_hours:
1196 * @datetime: a #GDateTime
1197 * @hours: the number of hours to add
1199 * Creates a copy of @datetime and adds the specified number of hours
1201 * Return value: the newly created #GDateTime which should be freed with
1202 * g_date_time_unref().
1207 g_date_time_add_hours (GDateTime *datetime,
1210 return g_date_time_add (datetime, hours * USEC_PER_HOUR);
1214 * g_date_time_add_minutes:
1215 * @datetime: a #GDateTime
1216 * @minutes: the number of minutes to add
1218 * Creates a copy of @datetime adding the specified number of minutes.
1220 * Return value: the newly created #GDateTime which should be freed with
1221 * g_date_time_unref().
1226 g_date_time_add_minutes (GDateTime *datetime,
1229 return g_date_time_add (datetime, minutes * USEC_PER_MINUTE);
1234 * g_date_time_add_seconds:
1235 * @datetime: a #GDateTime
1236 * @seconds: the number of seconds to add
1238 * Creates a copy of @datetime and adds the specified number of seconds.
1240 * Return value: the newly created #GDateTime which should be freed with
1241 * g_date_time_unref().
1246 g_date_time_add_seconds (GDateTime *datetime,
1249 return g_date_time_add (datetime, seconds * USEC_PER_SECOND);
1253 * g_date_time_add_full:
1254 * @datetime: a #GDateTime
1255 * @years: the number of years to add
1256 * @months: the number of months to add
1257 * @days: the number of days to add
1258 * @hours: the number of hours to add
1259 * @minutes: the number of minutes to add
1260 * @seconds: the number of seconds to add
1262 * Creates a new #GDateTime adding the specified values to the current date and
1263 * time in @datetime.
1265 * Return value: the newly created #GDateTime that should be freed with
1266 * g_date_time_unref().
1271 g_date_time_add_full (GDateTime *datetime,
1279 gint year, month, day;
1284 g_return_val_if_fail (datetime != NULL, NULL);
1285 g_date_time_get_ymd (datetime, &year, &month, &day);
1287 months += years * 12;
1289 if (months < -120000 || months > 120000)
1292 if (days < -3660000 || days > 3660000)
1295 year += months / 12;
1296 month += months % 12;
1302 else if (month > 12)
1308 day = MIN (day, days_in_months[GREGORIAN_LEAP (year)][month]);
1310 /* full_time is now in unix (local) time */
1311 full_time = datetime->usec / USEC_PER_SECOND + SEC_PER_DAY *
1312 (ymd_to_days (year, month, day) + days - UNIX_EPOCH_START);
1314 interval = g_time_zone_adjust_time (datetime->tz,
1315 g_time_zone_is_dst (datetime->tz,
1316 datetime->interval),
1319 /* move to UTC unix time */
1320 full_time -= g_time_zone_get_offset (datetime->tz, interval);
1322 /* convert back to an instant, add back fractional seconds */
1323 full_time += UNIX_EPOCH_START * SEC_PER_DAY;
1324 full_time = full_time * USEC_PER_SECOND +
1325 datetime->usec % USEC_PER_SECOND;
1327 /* do the actual addition now */
1328 full_time += (hours * USEC_PER_HOUR) +
1329 (minutes * USEC_PER_MINUTE) +
1330 (gint64) (seconds * USEC_PER_SECOND);
1332 /* find the new interval */
1333 interval = g_time_zone_find_interval (datetime->tz,
1334 G_TIME_TYPE_UNIVERSAL,
1335 INSTANT_TO_UNIX (full_time));
1337 /* convert back into local time */
1338 full_time += USEC_PER_SECOND *
1339 g_time_zone_get_offset (datetime->tz, interval);
1341 /* split into days and usec of a new datetime */
1342 new = g_date_time_alloc (datetime->tz);
1343 new->interval = interval;
1344 new->days = full_time / USEC_PER_DAY;
1345 new->usec = full_time % USEC_PER_DAY;
1352 /* Compare, difference, hash, equal {{{1 */
1354 * g_date_time_compare:
1355 * @dt1: first #GDateTime to compare
1356 * @dt2: second #GDateTime to compare
1358 * A comparison function for #GDateTimes that is suitable
1359 * as a #GCompareFunc. Both #GDateTimes must be non-%NULL.
1361 * Return value: -1, 0 or 1 if @dt1 is less than, equal to or greater
1367 g_date_time_compare (gconstpointer dt1,
1372 difference = g_date_time_difference ((GDateTime *) dt1, (GDateTime *) dt2);
1377 else if (difference > 0)
1385 * g_date_time_difference:
1386 * @end: a #GDateTime
1387 * @begin: a #GDateTime
1389 * Calculates the difference in time between @end and @begin. The
1390 * #GTimeSpan that is returned is effectively @end - @begin (ie:
1391 * positive if the first simparameter is larger).
1393 * Return value: the difference between the two #GDateTime, as a time
1394 * span expressed in microseconds.
1399 g_date_time_difference (GDateTime *end,
1402 g_return_val_if_fail (begin != NULL, 0);
1403 g_return_val_if_fail (end != NULL, 0);
1405 return g_date_time_to_instant (end) -
1406 g_date_time_to_instant (begin);
1411 * @datetime: a #GDateTime
1413 * Hashes @datetime into a #guint, suitable for use within #GHashTable.
1415 * Return value: a #guint containing the hash
1420 g_date_time_hash (gconstpointer datetime)
1422 return g_date_time_to_instant ((GDateTime *) datetime);
1426 * g_date_time_equal:
1427 * @dt1: a #GDateTime
1428 * @dt2: a #GDateTime
1430 * Checks to see if @dt1 and @dt2 are equal.
1432 * Equal here means that they represent the same moment after converting
1433 * them to the same time zone.
1435 * Return value: %TRUE if @dt1 and @dt2 are equal
1440 g_date_time_equal (gconstpointer dt1,
1443 return g_date_time_difference ((GDateTime *) dt1, (GDateTime *) dt2) == 0;
1446 /* Year, Month, Day Getters {{{1 */
1448 * g_date_time_get_ymd:
1449 * @datetime: a #GDateTime.
1450 * @year: (out): the return location for the gregorian year, or %NULL.
1451 * @month: (out): the return location for the month of the year, or %NULL.
1452 * @day: (out): the return location for the day of the month, or %NULL.
1454 * Retrieves the Gregorian day, month, and year of a given #GDateTime.
1459 g_date_time_get_ymd (GDateTime *datetime,
1467 gint remaining_days;
1474 g_return_if_fail (datetime != NULL);
1476 remaining_days = datetime->days;
1479 * We need to convert an offset in days to its year/month/day representation.
1480 * Leap years makes this a little trickier than it should be, so we use
1481 * 400, 100 and 4 years cycles here to get to the correct year.
1484 /* Our days offset starts sets 0001-01-01 as day 1, if it was day 0 our
1485 * math would be simpler, so let's do it */
1488 the_year = (remaining_days / DAYS_IN_400YEARS) * 400 + 1;
1489 remaining_days = remaining_days % DAYS_IN_400YEARS;
1491 y100_cycles = remaining_days / DAYS_IN_100YEARS;
1492 remaining_days = remaining_days % DAYS_IN_100YEARS;
1493 the_year += y100_cycles * 100;
1495 y4_cycles = remaining_days / DAYS_IN_4YEARS;
1496 remaining_days = remaining_days % DAYS_IN_4YEARS;
1497 the_year += y4_cycles * 4;
1499 y1_cycles = remaining_days / 365;
1500 the_year += y1_cycles;
1501 remaining_days = remaining_days % 365;
1503 if (y1_cycles == 4 || y100_cycles == 4) {
1504 g_assert (remaining_days == 0);
1506 /* special case that indicates that the date is actually one year before,
1507 * in the 31th of December */
1514 /* now get the month and the day */
1515 leap = y1_cycles == 3 && (y4_cycles != 24 || y100_cycles == 3);
1517 g_assert (leap == GREGORIAN_LEAP(the_year));
1519 the_month = (remaining_days + 50) >> 5;
1520 preceding = (days_in_year[0][the_month - 1] + (the_month > 2 && leap));
1521 if (preceding > remaining_days)
1523 /* estimate is too large */
1525 preceding -= leap ? days_in_months[1][the_month]
1526 : days_in_months[0][the_month];
1529 remaining_days -= preceding;
1530 g_assert(0 <= remaining_days);
1532 the_day = remaining_days + 1;
1544 * g_date_time_get_year:
1545 * @datetime: A #GDateTime
1547 * Retrieves the year represented by @datetime in the Gregorian calendar.
1549 * Return value: the year represented by @datetime
1554 g_date_time_get_year (GDateTime *datetime)
1558 g_return_val_if_fail (datetime != NULL, 0);
1560 g_date_time_get_ymd (datetime, &year, NULL, NULL);
1566 * g_date_time_get_month:
1567 * @datetime: a #GDateTime
1569 * Retrieves the month of the year represented by @datetime in the Gregorian
1572 * Return value: the month represented by @datetime
1577 g_date_time_get_month (GDateTime *datetime)
1581 g_return_val_if_fail (datetime != NULL, 0);
1583 g_date_time_get_ymd (datetime, NULL, &month, NULL);
1589 * g_date_time_get_day_of_month:
1590 * @datetime: a #GDateTime
1592 * Retrieves the day of the month represented by @datetime in the gregorian
1595 * Return value: the day of the month
1600 g_date_time_get_day_of_month (GDateTime *datetime)
1604 const guint16 *days;
1607 g_return_val_if_fail (datetime != NULL, 0);
1609 days = days_in_year[GREGORIAN_LEAP (g_date_time_get_year (datetime)) ? 1 : 0];
1610 g_date_time_get_week_number (datetime, NULL, NULL, &day_of_year);
1612 for (i = 1; i <= 12; i++)
1614 if (days [i] >= day_of_year)
1615 return day_of_year - last;
1619 g_warn_if_reached ();
1623 /* Week of year / day of week getters {{{1 */
1625 * g_date_time_get_week_numbering_year:
1626 * @datetime: a #GDateTime
1628 * Returns the ISO 8601 week-numbering year in which the week containing
1631 * This function, taken together with g_date_time_get_week_of_year() and
1632 * g_date_time_get_day_of_week() can be used to determine the full ISO
1633 * week date on which @datetime falls.
1635 * This is usually equal to the normal Gregorian year (as returned by
1636 * g_date_time_get_year()), except as detailed below:
1638 * For Thursday, the week-numbering year is always equal to the usual
1639 * calendar year. For other days, the number is such that every day
1640 * within a complete week (Monday to Sunday) is contained within the
1641 * same week-numbering year.
1643 * For Monday, Tuesday and Wednesday occurring near the end of the year,
1644 * this may mean that the week-numbering year is one greater than the
1645 * calendar year (so that these days have the same week-numbering year
1646 * as the Thursday occurring early in the next year).
1648 * For Friday, Saturaday and Sunday occurring near the start of the year,
1649 * this may mean that the week-numbering year is one less than the
1650 * calendar year (so that these days have the same week-numbering year
1651 * as the Thursday occurring late in the previous year).
1653 * An equivalent description is that the week-numbering year is equal to
1654 * the calendar year containing the majority of the days in the current
1655 * week (Monday to Sunday).
1657 * Note that January 1 0001 in the proleptic Gregorian calendar is a
1658 * Monday, so this function never returns 0.
1660 * Returns: the ISO 8601 week-numbering year for @datetime
1665 g_date_time_get_week_numbering_year (GDateTime *datetime)
1667 gint year, month, day, weekday;
1669 g_date_time_get_ymd (datetime, &year, &month, &day);
1670 weekday = g_date_time_get_day_of_week (datetime);
1672 /* January 1, 2, 3 might be in the previous year if they occur after
1675 * Jan 1: Friday, Saturday, Sunday => day 1: weekday 5, 6, 7
1676 * Jan 2: Saturday, Sunday => day 2: weekday 6, 7
1677 * Jan 3: Sunday => day 3: weekday 7
1679 * So we have a special case if (day - weekday) <= -4
1681 if (month == 1 && (day - weekday) <= -4)
1684 /* December 29, 30, 31 might be in the next year if they occur before
1687 * Dec 31: Monday, Tuesday, Wednesday => day 31: weekday 1, 2, 3
1688 * Dec 30: Monday, Tuesday => day 30: weekday 1, 2
1689 * Dec 29: Monday => day 29: weekday 1
1691 * So we have a special case if (day - weekday) >= 28
1693 else if (month == 12 && (day - weekday) >= 28)
1701 * g_date_time_get_week_of_year:
1702 * @datetime: a #GDateTime
1704 * Returns the ISO 8601 week number for the week containing @datetime.
1705 * The ISO 8601 week number is the same for every day of the week (from
1706 * Moday through Sunday). That can produce some unusual results
1707 * (described below).
1709 * The first week of the year is week 1. This is the week that contains
1710 * the first Thursday of the year. Equivalently, this is the first week
1711 * that has more than 4 of its days falling within the calendar year.
1713 * The value 0 is never returned by this function. Days contained
1714 * within a year but occurring before the first ISO 8601 week of that
1715 * year are considered as being contained in the last week of the
1716 * previous year. Similarly, the final days of a calendar year may be
1717 * considered as being part of the first ISO 8601 week of the next year
1718 * if 4 or more days of that week are contained within the new year.
1720 * Returns: the ISO 8601 week number for @datetime.
1725 g_date_time_get_week_of_year (GDateTime *datetime)
1729 g_return_val_if_fail (datetime != NULL, 0);
1731 g_date_time_get_week_number (datetime, &weeknum, NULL, NULL);
1737 * g_date_time_get_day_of_week:
1738 * @datetime: a #GDateTime
1740 * Retrieves the ISO 8601 day of the week on which @datetime falls (1 is
1741 * Monday, 2 is Tuesday... 7 is Sunday).
1743 * Return value: the day of the week
1748 g_date_time_get_day_of_week (GDateTime *datetime)
1750 g_return_val_if_fail (datetime != NULL, 0);
1752 return (datetime->days - 1) % 7 + 1;
1755 /* Day of year getter {{{1 */
1757 * g_date_time_get_day_of_year:
1758 * @datetime: a #GDateTime
1760 * Retrieves the day of the year represented by @datetime in the Gregorian
1763 * Return value: the day of the year
1768 g_date_time_get_day_of_year (GDateTime *datetime)
1772 g_return_val_if_fail (datetime != NULL, 0);
1774 g_date_time_get_week_number (datetime, NULL, NULL, &doy);
1778 /* Time component getters {{{1 */
1781 * g_date_time_get_hour:
1782 * @datetime: a #GDateTime
1784 * Retrieves the hour of the day represented by @datetime
1786 * Return value: the hour of the day
1791 g_date_time_get_hour (GDateTime *datetime)
1793 g_return_val_if_fail (datetime != NULL, 0);
1795 return (datetime->usec / USEC_PER_HOUR);
1799 * g_date_time_get_minute:
1800 * @datetime: a #GDateTime
1802 * Retrieves the minute of the hour represented by @datetime
1804 * Return value: the minute of the hour
1809 g_date_time_get_minute (GDateTime *datetime)
1811 g_return_val_if_fail (datetime != NULL, 0);
1813 return (datetime->usec % USEC_PER_HOUR) / USEC_PER_MINUTE;
1817 * g_date_time_get_second:
1818 * @datetime: a #GDateTime
1820 * Retrieves the second of the minute represented by @datetime
1822 * Return value: the second represented by @datetime
1827 g_date_time_get_second (GDateTime *datetime)
1829 g_return_val_if_fail (datetime != NULL, 0);
1831 return (datetime->usec % USEC_PER_MINUTE) / USEC_PER_SECOND;
1835 * g_date_time_get_microsecond:
1836 * @datetime: a #GDateTime
1838 * Retrieves the microsecond of the date represented by @datetime
1840 * Return value: the microsecond of the second
1845 g_date_time_get_microsecond (GDateTime *datetime)
1847 g_return_val_if_fail (datetime != NULL, 0);
1849 return (datetime->usec % USEC_PER_SECOND);
1853 * g_date_time_get_seconds:
1854 * @datetime: a #GDateTime
1856 * Retrieves the number of seconds since the start of the last minute,
1857 * including the fractional part.
1859 * Returns: the number of seconds
1864 g_date_time_get_seconds (GDateTime *datetime)
1866 g_return_val_if_fail (datetime != NULL, 0);
1868 return (datetime->usec % USEC_PER_MINUTE) / 1000000.0;
1871 /* Exporters {{{1 */
1873 * g_date_time_to_unix:
1874 * @datetime: a #GDateTime
1876 * Gives the Unix time corresponding to @datetime, rounding down to the
1879 * Unix time is the number of seconds that have elapsed since 1970-01-01
1880 * 00:00:00 UTC, regardless of the time zone associated with @datetime.
1882 * Returns: the Unix time corresponding to @datetime
1887 g_date_time_to_unix (GDateTime *datetime)
1889 return INSTANT_TO_UNIX (g_date_time_to_instant (datetime));
1893 * g_date_time_to_timeval:
1894 * @datetime: a #GDateTime
1895 * @tv: a #GTimeVal to modify
1897 * Stores the instant in time that @datetime represents into @tv.
1899 * The time contained in a #GTimeVal is always stored in the form of
1900 * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the time
1901 * zone associated with @datetime.
1903 * On systems where 'long' is 32bit (ie: all 32bit systems and all
1904 * Windows systems), a #GTimeVal is incapable of storing the entire
1905 * range of values that #GDateTime is capable of expressing. On those
1906 * systems, this function returns %FALSE to indicate that the time is
1909 * On systems where 'long' is 64bit, this function never fails.
1911 * Returns: %TRUE if successful, else %FALSE
1916 g_date_time_to_timeval (GDateTime *datetime,
1919 tv->tv_sec = INSTANT_TO_UNIX (g_date_time_to_instant (datetime));
1920 tv->tv_usec = datetime->usec % USEC_PER_SECOND;
1925 /* Timezone queries {{{1 */
1927 * g_date_time_get_utc_offset:
1928 * @datetime: a #GDateTime
1930 * Determines the offset to UTC in effect at the time and in the time
1931 * zone of @datetime.
1933 * The offset is the number of microseconds that you add to UTC time to
1934 * arrive at local time for the time zone (ie: negative numbers for time
1935 * zones west of GMT, positive numbers for east).
1937 * If @datetime represents UTC time, then the offset is always zero.
1939 * Returns: the number of microseconds that should be added to UTC to
1940 * get the local time
1945 g_date_time_get_utc_offset (GDateTime *datetime)
1949 g_return_val_if_fail (datetime != NULL, 0);
1951 offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
1953 return (gint64) offset * USEC_PER_SECOND;
1957 * g_date_time_get_timezone_abbreviation:
1958 * @datetime: a #GDateTime
1960 * Determines the time zone abbreviation to be used at the time and in
1961 * the time zone of @datetime.
1963 * For example, in Toronto this is currently "EST" during the winter
1964 * months and "EDT" during the summer months when daylight savings
1965 * time is in effect.
1967 * Returns: (transfer none): the time zone abbreviation. The returned
1968 * string is owned by the #GDateTime and it should not be
1974 g_date_time_get_timezone_abbreviation (GDateTime *datetime)
1976 g_return_val_if_fail (datetime != NULL, NULL);
1978 return g_time_zone_get_abbreviation (datetime->tz, datetime->interval);
1982 * g_date_time_is_daylight_savings:
1983 * @datetime: a #GDateTime
1985 * Determines if daylight savings time is in effect at the time and in
1986 * the time zone of @datetime.
1988 * Returns: %TRUE if daylight savings time is in effect
1993 g_date_time_is_daylight_savings (GDateTime *datetime)
1995 g_return_val_if_fail (datetime != NULL, FALSE);
1997 return g_time_zone_is_dst (datetime->tz, datetime->interval);
2000 /* Timezone convert {{{1 */
2002 * g_date_time_to_timezone:
2003 * @datetime: a #GDateTime
2004 * @tz: the new #GTimeZone
2006 * Create a new #GDateTime corresponding to the same instant in time as
2007 * @datetime, but in the time zone @tz.
2009 * This call can fail in the case that the time goes out of bounds. For
2010 * example, converting 0001-01-01 00:00:00 UTC to a time zone west of
2011 * Greenwich will fail (due to the year 0 being out of range).
2013 * You should release the return value by calling g_date_time_unref()
2014 * when you are done with it.
2016 * Returns: a new #GDateTime, or %NULL
2021 g_date_time_to_timezone (GDateTime *datetime,
2024 return g_date_time_from_instant (tz, g_date_time_to_instant (datetime));
2028 * g_date_time_to_local:
2029 * @datetime: a #GDateTime
2031 * Creates a new #GDateTime corresponding to the same instant in time as
2032 * @datetime, but in the local time zone.
2034 * This call is equivalent to calling g_date_time_to_timezone() with the
2035 * time zone returned by g_time_zone_new_local().
2037 * Returns: the newly created #GDateTime
2042 g_date_time_to_local (GDateTime *datetime)
2047 local = g_time_zone_new_local ();
2048 new = g_date_time_to_timezone (datetime, local);
2049 g_time_zone_unref (local);
2055 * g_date_time_to_utc:
2056 * @datetime: a #GDateTime
2058 * Creates a new #GDateTime corresponding to the same instant in time as
2059 * @datetime, but in UTC.
2061 * This call is equivalent to calling g_date_time_to_timezone() with the
2062 * time zone returned by g_time_zone_new_utc().
2064 * Returns: the newly created #GDateTime
2069 g_date_time_to_utc (GDateTime *datetime)
2074 utc = g_time_zone_new_utc ();
2075 new = g_date_time_to_timezone (datetime, utc);
2076 g_time_zone_unref (utc);
2084 format_number (GString *str,
2085 gboolean use_alt_digits,
2090 const gunichar ascii_digits[10] = {
2091 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
2093 const gunichar *digits = ascii_digits;
2097 g_return_if_fail (width <= 10);
2099 #ifdef HAVE_LANGINFO_OUTDIGIT
2102 static gunichar alt_digits[10];
2103 static gsize initialised;
2104 /* 2^32 has 10 digits */
2106 if G_UNLIKELY (g_once_init_enter (&initialised))
2108 #define DO_DIGIT(n) \
2110 union { guint integer; char *pointer; } val; \
2111 val.pointer = nl_langinfo (_NL_CTYPE_OUTDIGIT## n ##_WC); \
2112 alt_digits[n] = val.integer; \
2114 DO_DIGIT(0); DO_DIGIT(1); DO_DIGIT(2); DO_DIGIT(3); DO_DIGIT(4);
2115 DO_DIGIT(5); DO_DIGIT(6); DO_DIGIT(7); DO_DIGIT(8); DO_DIGIT(9);
2117 g_once_init_leave (&initialised, TRUE);
2120 digits = alt_digits;
2122 #endif /* HAVE_LANGINFO_OUTDIGIT */
2126 tmp[i++] = digits[number % 10];
2131 while (pad && i < width)
2132 tmp[i++] = pad == '0' ? digits[0] : pad;
2134 /* should really be impossible */
2138 g_string_append_unichar (str, tmp[--i]);
2142 * g_date_time_format:
2143 * @datetime: A #GDateTime
2144 * @format: a valid UTF-8 string, containing the format for the
2147 * Creates a newly allocated string representing the requested @format.
2149 * The format strings understood by this function are a subset of the
2150 * strftime() format language as specified by C99. The \%D, \%U and \%W
2151 * conversions are not supported, nor is the 'E' modifier. The GNU
2152 * extensions \%k, \%l, \%s and \%P are supported, however, as are the
2153 * '0', '_' and '-' modifiers.
2155 * In contrast to strftime(), this function always produces a UTF-8
2156 * string, regardless of the current locale. Note that the rendering of
2157 * many formats is locale-dependent and may not match the strftime()
2160 * The following format specifiers are supported:
2163 * <varlistentry><term>
2164 * <literal>\%a</literal>:
2165 * </term><listitem><simpara>
2166 * the abbreviated weekday name according to the current locale
2167 * </simpara></listitem></varlistentry>
2168 * <varlistentry><term>
2169 * <literal>\%A</literal>:
2170 * </term><listitem><simpara>
2171 * the full weekday name according to the current locale
2172 * </simpara></listitem></varlistentry>
2173 * <varlistentry><term>
2174 * <literal>\%b</literal>:
2175 * </term><listitem><simpara>
2176 * the abbreviated month name according to the current locale
2177 * </simpara></listitem></varlistentry>
2178 * <varlistentry><term>
2179 * <literal>\%B</literal>:
2180 * </term><listitem><simpara>
2181 * the full month name according to the current locale
2182 * </simpara></listitem></varlistentry>
2183 * <varlistentry><term>
2184 * <literal>\%c</literal>:
2185 * </term><listitem><simpara>
2186 * the preferred date and time representation for the current locale
2187 * </simpara></listitem></varlistentry>
2188 * <varlistentry><term>
2189 * <literal>\%C</literal>:
2190 * </term><listitem><simpara>
2191 * The century number (year/100) as a 2-digit integer (00-99)
2192 * </simpara></listitem></varlistentry>
2193 * <varlistentry><term>
2194 * <literal>\%d</literal>:
2195 * </term><listitem><simpara>
2196 * the day of the month as a decimal number (range 01 to 31)
2197 * </simpara></listitem></varlistentry>
2198 * <varlistentry><term>
2199 * <literal>\%e</literal>:
2200 * </term><listitem><simpara>
2201 * the day of the month as a decimal number (range 1 to 31)
2202 * </simpara></listitem></varlistentry>
2203 * <varlistentry><term>
2204 * <literal>\%F</literal>:
2205 * </term><listitem><simpara>
2206 * equivalent to <literal>\%Y-\%m-\%d</literal> (the ISO 8601 date
2208 * </simpara></listitem></varlistentry>
2209 * <varlistentry><term>
2210 * <literal>\%g</literal>:
2211 * </term><listitem><simpara>
2212 * the last two digits of the ISO 8601 week-based year as a decimal
2213 * number (00-99). This works well with \%V and \%u.
2214 * </simpara></listitem></varlistentry>
2215 * <varlistentry><term>
2216 * <literal>\%G</literal>:
2217 * </term><listitem><simpara>
2218 * the ISO 8601 week-based year as a decimal number. This works well
2220 * </simpara></listitem></varlistentry>
2221 * <varlistentry><term>
2222 * <literal>\%h</literal>:
2223 * </term><listitem><simpara>
2224 * equivalent to <literal>\%b</literal>
2225 * </simpara></listitem></varlistentry>
2226 * <varlistentry><term>
2227 * <literal>\%H</literal>:
2228 * </term><listitem><simpara>
2229 * the hour as a decimal number using a 24-hour clock (range 00 to
2231 * </simpara></listitem></varlistentry>
2232 * <varlistentry><term>
2233 * <literal>\%I</literal>:
2234 * </term><listitem><simpara>
2235 * the hour as a decimal number using a 12-hour clock (range 01 to
2237 * </simpara></listitem></varlistentry>
2238 * <varlistentry><term>
2239 * <literal>\%j</literal>:
2240 * </term><listitem><simpara>
2241 * the day of the year as a decimal number (range 001 to 366)
2242 * </simpara></listitem></varlistentry>
2243 * <varlistentry><term>
2244 * <literal>\%k</literal>:
2245 * </term><listitem><simpara>
2246 * the hour (24-hour clock) as a decimal number (range 0 to 23);
2247 * single digits are preceded by a blank
2248 * </simpara></listitem></varlistentry>
2249 * <varlistentry><term>
2250 * <literal>\%l</literal>:
2251 * </term><listitem><simpara>
2252 * the hour (12-hour clock) as a decimal number (range 1 to 12);
2253 * single digits are preceded by a blank
2254 * </simpara></listitem></varlistentry>
2255 * <varlistentry><term>
2256 * <literal>\%m</literal>:
2257 * </term><listitem><simpara>
2258 * the month as a decimal number (range 01 to 12)
2259 * </simpara></listitem></varlistentry>
2260 * <varlistentry><term>
2261 * <literal>\%M</literal>:
2262 * </term><listitem><simpara>
2263 * the minute as a decimal number (range 00 to 59)
2264 * </simpara></listitem></varlistentry>
2265 * <varlistentry><term>
2266 * <literal>\%p</literal>:
2267 * </term><listitem><simpara>
2268 * either "AM" or "PM" according to the given time value, or the
2269 * corresponding strings for the current locale. Noon is treated as
2270 * "PM" and midnight as "AM".
2271 * </simpara></listitem></varlistentry>
2272 * <varlistentry><term>
2273 * <literal>\%P</literal>:
2274 * </term><listitem><simpara>
2275 * like \%p but lowercase: "am" or "pm" or a corresponding string for
2276 * the current locale
2277 * </simpara></listitem></varlistentry>
2278 * <varlistentry><term>
2279 * <literal>\%r</literal>:
2280 * </term><listitem><simpara>
2281 * the time in a.m. or p.m. notation
2282 * </simpara></listitem></varlistentry>
2283 * <varlistentry><term>
2284 * <literal>\%R</literal>:
2285 * </term><listitem><simpara>
2286 * the time in 24-hour notation (<literal>\%H:\%M</literal>)
2287 * </simpara></listitem></varlistentry>
2288 * <varlistentry><term>
2289 * <literal>\%s</literal>:
2290 * </term><listitem><simpara>
2291 * the number of seconds since the Epoch, that is, since 1970-01-01
2293 * </simpara></listitem></varlistentry>
2294 * <varlistentry><term>
2295 * <literal>\%S</literal>:
2296 * </term><listitem><simpara>
2297 * the second as a decimal number (range 00 to 60)
2298 * </simpara></listitem></varlistentry>
2299 * <varlistentry><term>
2300 * <literal>\%t</literal>:
2301 * </term><listitem><simpara>
2303 * </simpara></listitem></varlistentry>
2304 * <varlistentry><term>
2305 * <literal>\%T</literal>:
2306 * </term><listitem><simpara>
2307 * the time in 24-hour notation with seconds (<literal>\%H:\%M:\%S</literal>)
2308 * </simpara></listitem></varlistentry>
2309 * <varlistentry><term>
2310 * <literal>\%u</literal>:
2311 * </term><listitem><simpara>
2312 * the ISO 8601 standard day of the week as a decimal, range 1 to 7,
2313 * Monday being 1. This works well with \%G and \%V.
2314 * </simpara></listitem></varlistentry>
2315 * <varlistentry><term>
2316 * <literal>\%V</literal>:
2317 * </term><listitem><simpara>
2318 * the ISO 8601 standard week number of the current year as a decimal
2319 * number, range 01 to 53, where week 1 is the first week that has at
2320 * least 4 days in the new year. See g_date_time_get_week_of_year().
2321 * This works well with \%G and \%u.
2322 * </simpara></listitem></varlistentry>
2323 * <varlistentry><term>
2324 * <literal>\%w</literal>:
2325 * </term><listitem><simpara>
2326 * the day of the week as a decimal, range 0 to 6, Sunday being 0.
2327 * This is not the ISO 8601 standard format -- use \%u instead.
2328 * </simpara></listitem></varlistentry>
2329 * <varlistentry><term>
2330 * <literal>\%x</literal>:
2331 * </term><listitem><simpara>
2332 * the preferred date representation for the current locale without
2334 * </simpara></listitem></varlistentry>
2335 * <varlistentry><term>
2336 * <literal>\%X</literal>:
2337 * </term><listitem><simpara>
2338 * the preferred time representation for the current locale without
2340 * </simpara></listitem></varlistentry>
2341 * <varlistentry><term>
2342 * <literal>\%y</literal>:
2343 * </term><listitem><simpara>
2344 * the year as a decimal number without the century
2345 * </simpara></listitem></varlistentry>
2346 * <varlistentry><term>
2347 * <literal>\%Y</literal>:
2348 * </term><listitem><simpara>
2349 * the year as a decimal number including the century
2350 * </simpara></listitem></varlistentry>
2351 * <varlistentry><term>
2352 * <literal>\%z</literal>:
2353 * </term><listitem><simpara>
2354 * the time-zone as hour offset from UTC
2355 * </simpara></listitem></varlistentry>
2356 * <varlistentry><term>
2357 * <literal>\%Z</literal>:
2358 * </term><listitem><simpara>
2359 * the time zone or name or abbreviation
2360 * </simpara></listitem></varlistentry>
2361 * <varlistentry><term>
2362 * <literal>\%\%</literal>:
2363 * </term><listitem><simpara>
2364 * a literal <literal>\%</literal> character
2365 * </simpara></listitem></varlistentry>
2368 * Some conversion specifications can be modified by preceding the
2369 * conversion specifier by one or more modifier characters. The
2370 * following modifiers are supported for many of the numeric
2376 * Use alternative numeric symbols, if the current locale
2383 * Pad a numeric result with spaces.
2384 * This overrides the default padding for the specifier.
2390 * Do not pad a numeric result.
2391 * This overrides the default padding for the specifier.
2397 * Pad a numeric result with zeros.
2398 * This overrides the default padding for the specifier.
2403 * Returns: a newly allocated string formatted to the requested format
2404 * or %NULL in the case that there was an error. The string
2405 * should be freed with g_free().
2410 g_date_time_format (GDateTime *datetime,
2411 const gchar *format)
2416 gboolean in_mod = FALSE;
2417 gboolean alt_digits = FALSE;
2418 gboolean pad_set = FALSE;
2422 g_return_val_if_fail (datetime != NULL, NULL);
2423 g_return_val_if_fail (format != NULL, NULL);
2424 g_return_val_if_fail (g_utf8_validate (format, -1, NULL), NULL);
2426 outstr = g_string_sized_new (strlen (format) * 2);
2429 for (; *format; format = g_utf8_next_char (format))
2431 c = g_utf8_get_char (format);
2450 g_string_append (outstr, WEEKDAY_ABBR (datetime));
2453 g_string_append (outstr, WEEKDAY_FULL (datetime));
2456 g_string_append (outstr, MONTH_ABBR (datetime));
2459 g_string_append (outstr, MONTH_FULL (datetime));
2463 tmp = g_date_time_format (datetime, PREFERRED_DATE_TIME_FMT);
2464 g_string_append (outstr, tmp);
2469 format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
2470 g_date_time_get_year (datetime) / 100);
2473 format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
2474 g_date_time_get_day_of_month (datetime));
2477 format_number (outstr, alt_digits, pad_set ? pad : ' ', 2,
2478 g_date_time_get_day_of_month (datetime));
2481 g_string_append_printf (outstr, "%d-%02d-%02d",
2482 g_date_time_get_year (datetime),
2483 g_date_time_get_month (datetime),
2484 g_date_time_get_day_of_month (datetime));
2487 format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
2488 g_date_time_get_week_numbering_year (datetime) % 100);
2491 format_number (outstr, alt_digits, pad_set ? pad : 0, 0,
2492 g_date_time_get_week_numbering_year (datetime));
2495 g_string_append (outstr, MONTH_ABBR (datetime));
2498 format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
2499 g_date_time_get_hour (datetime));
2502 format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
2503 (g_date_time_get_hour (datetime) + 11) % 12 + 1);
2506 format_number (outstr, alt_digits, pad_set ? pad : '0', 3,
2507 g_date_time_get_day_of_year (datetime));
2510 format_number (outstr, alt_digits, pad_set ? pad : ' ', 2,
2511 g_date_time_get_hour (datetime));
2514 format_number (outstr, alt_digits, pad_set ? pad : ' ', 2,
2515 (g_date_time_get_hour (datetime) + 11) % 12 + 1);
2518 g_string_append_c (outstr, '\n');
2521 format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
2522 g_date_time_get_month (datetime));
2525 format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
2526 g_date_time_get_minute (datetime));
2532 ampm = g_utf8_strup (GET_AMPM (datetime), -1);
2533 g_string_append (outstr, ampm);
2537 ampm = g_utf8_strdown (GET_AMPM (datetime), -1);
2538 g_string_append (outstr, ampm);
2543 tmp = g_date_time_format (datetime, PREFERRED_12HR_TIME_FMT);
2544 g_string_append (outstr, tmp);
2549 g_string_append_printf (outstr, "%02d:%02d",
2550 g_date_time_get_hour (datetime),
2551 g_date_time_get_minute (datetime));
2554 g_string_append_printf (outstr, "%" G_GINT64_FORMAT, g_date_time_to_unix (datetime));
2557 format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
2558 g_date_time_get_second (datetime));
2561 g_string_append_c (outstr, '\t');
2564 g_string_append_printf (outstr, "%02d:%02d:%02d",
2565 g_date_time_get_hour (datetime),
2566 g_date_time_get_minute (datetime),
2567 g_date_time_get_second (datetime));
2570 format_number (outstr, alt_digits, 0, 0,
2571 g_date_time_get_day_of_week (datetime));
2574 format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
2575 g_date_time_get_week_of_year (datetime));
2578 format_number (outstr, alt_digits, 0, 0,
2579 g_date_time_get_day_of_week (datetime) % 7);
2583 tmp = g_date_time_format (datetime, PREFERRED_DATE_FMT);
2584 g_string_append (outstr, tmp);
2590 tmp = g_date_time_format (datetime, PREFERRED_TIME_FMT);
2591 g_string_append (outstr, tmp);
2596 format_number (outstr, alt_digits, pad_set ? pad : '0', 2,
2597 g_date_time_get_year (datetime) % 100);
2600 format_number (outstr, alt_digits, 0, 0,
2601 g_date_time_get_year (datetime));
2604 if (datetime->tz != NULL)
2606 gint64 offset = g_date_time_get_utc_offset (datetime)
2609 g_string_append_printf (outstr, "%+03d%02d",
2610 (int) offset / 3600,
2611 (int) abs(offset) / 60 % 60);
2614 g_string_append (outstr, "+0000");
2617 g_string_append (outstr, g_date_time_get_timezone_abbreviation (datetime));
2620 g_string_append_c (outstr, '%');
2640 g_string_append_unichar (outstr, c);
2645 return g_string_free (outstr, FALSE);
2648 g_string_free (outstr, TRUE);
2654 /* vim:set foldmethod=marker: */