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"
64 #include "gfileutils.h"
67 #include "gmappedfile.h"
68 #include "gstrfuncs.h"
69 #include "gtestutils.h"
71 #include "gtimezone.h"
78 #endif /* !G_OS_WIN32 */
83 * @short_description: A structure representing Date and Time
84 * @see_also: #GTimeZone
86 * #GDateTime is a structure that combines a Gregorian date and time
87 * into a single structure. It provides many conversion and methods to
88 * manipulate dates and times. Time precision is provided down to
89 * microseconds and the time can range (proleptically) from 0001-01-01
90 * 00:00:00 to 9999-12-31 23:59:59.999999. #GDateTime follows POSIX
91 * time in the sense that it is oblivious to leap seconds.
93 * #GDateTime is an immutable object; once it has been created it cannot
94 * be modified further. All modifiers will create a new #GDateTime.
95 * Nearly all such functions can fail due to the date or time going out
96 * of range, in which case %NULL will be returned.
98 * #GDateTime is reference counted: the reference count is increased by calling
99 * g_date_time_ref() and decreased by calling g_date_time_unref(). When the
100 * reference count drops to 0, the resources allocated by the #GDateTime
101 * structure are released.
103 * Many parts of the API may produce non-obvious results. As an
104 * example, adding two months to January 31st will yield March 31st
105 * whereas adding one month and then one month again will yield either
106 * March 28th or March 29th. Also note that adding 24 hours is not
107 * always the same as adding one day (since days containing daylight
108 * savings time transitions are either 23 or 25 hours in length).
110 * #GDateTime is available since GLib 2.26.
115 /* 1 is 0001-01-01 in Proleptic Gregorian */
118 /* Microsecond timekeeping within Day */
121 /* TimeZone information */
125 volatile gint ref_count;
128 /* Time conversion {{{1 */
130 #define UNIX_EPOCH_START 719163
131 #define INSTANT_TO_UNIX(instant) \
132 ((instant)/USEC_PER_SECOND - UNIX_EPOCH_START * SEC_PER_DAY)
133 #define UNIX_TO_INSTANT(unix) \
134 (((unix) + UNIX_EPOCH_START * SEC_PER_DAY) * USEC_PER_SECOND)
136 #define DAYS_IN_4YEARS 1461 /* days in 4 years */
137 #define DAYS_IN_100YEARS 36524 /* days in 100 years */
138 #define DAYS_IN_400YEARS 146097 /* days in 400 years */
140 #define USEC_PER_SECOND (G_GINT64_CONSTANT (1000000))
141 #define USEC_PER_MINUTE (G_GINT64_CONSTANT (60000000))
142 #define USEC_PER_HOUR (G_GINT64_CONSTANT (3600000000))
143 #define USEC_PER_MILLISECOND (G_GINT64_CONSTANT (1000))
144 #define USEC_PER_DAY (G_GINT64_CONSTANT (86400000000))
145 #define SEC_PER_DAY (G_GINT64_CONSTANT (86400))
147 #define SECS_PER_MINUTE (60)
148 #define SECS_PER_HOUR (60 * SECS_PER_MINUTE)
149 #define SECS_PER_DAY (24 * SECS_PER_HOUR)
150 #define SECS_PER_YEAR (365 * SECS_PER_DAY)
151 #define SECS_PER_JULIAN (DAYS_PER_PERIOD * SECS_PER_DAY)
153 #define GREGORIAN_LEAP(y) ((((y) % 4) == 0) && (!((((y) % 100) == 0) && (((y) % 400) != 0))))
154 #define JULIAN_YEAR(d) ((d)->julian / 365.25)
155 #define DAYS_PER_PERIOD (G_GINT64_CONSTANT (2914695))
157 static const guint16 days_in_months[2][13] =
159 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
160 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
163 static const guint16 days_in_year[2][13] =
165 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
166 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
169 #ifdef HAVE_LANGINFO_TIME
171 #define GET_AMPM(d) ((g_date_time_get_hour (d) < 12) ? \
172 nl_langinfo (AM_STR) : \
173 nl_langinfo (PM_STR))
175 #define PREFERRED_DATE_TIME_FMT nl_langinfo (D_T_FMT)
176 #define PREFERRED_DATE_FMT nl_langinfo (D_FMT)
177 #define PREFERRED_TIME_FMT nl_langinfo (T_FMT)
179 static const gint weekday_item[2][7] =
181 { ABDAY_2, ABDAY_3, ABDAY_4, ABDAY_5, ABDAY_6, ABDAY_7, ABDAY_1 },
182 { DAY_2, DAY_3, DAY_4, DAY_5, DAY_6, DAY_7, DAY_1 }
185 static const gint month_item[2][12] =
187 { ABMON_1, ABMON_2, ABMON_3, ABMON_4, ABMON_5, ABMON_6, ABMON_7, ABMON_8, ABMON_9, ABMON_10, ABMON_11, ABMON_12 },
188 { MON_1, MON_2, MON_3, MON_4, MON_5, MON_6, MON_7, MON_8, MON_9, MON_10, MON_11, MON_12 },
191 #define WEEKDAY_ABBR(d) nl_langinfo (weekday_item[0][g_date_time_get_day_of_week (d) - 1])
192 #define WEEKDAY_FULL(d) nl_langinfo (weekday_item[1][g_date_time_get_day_of_week (d) - 1])
193 #define MONTH_ABBR(d) nl_langinfo (month_item[0][g_date_time_get_month (d) - 1])
194 #define MONTH_FULL(d) nl_langinfo (month_item[1][g_date_time_get_month (d) - 1])
198 #define GET_AMPM(d) ((g_date_time_get_hour (d) < 12) \
199 /* Translators: 'before midday' indicator */ \
200 ? C_("GDateTime", "am") \
201 /* Translators: 'after midday' indicator */ \
202 : C_("GDateTime", "pm"))
204 /* Translators: this is the preferred format for expressing the date and the time */
205 #define PREFERRED_DATE_TIME_FMT C_("GDateTime", "%a %b %e %H:%M:%S %Y")
207 /* Translators: this is the preferred format for expressing the date */
208 #define PREFERRED_DATE_FMT C_("GDateTime", "%m/%d/%y")
210 /* Translators: this is the preferred format for expressing the time */
211 #define PREFERRED_TIME_FMT C_("GDateTime", "%H:%M:%S")
214 #define WEEKDAY_ABBR(d) (get_weekday_name_abbr (g_date_time_get_day_of_week (d)))
215 #define WEEKDAY_FULL(d) (get_weekday_name (g_date_time_get_day_of_week (d)))
216 #define MONTH_ABBR(d) (get_month_name_abbr (g_date_time_get_month (d)))
217 #define MONTH_FULL(d) (get_month_name (g_date_time_get_month (d)))
220 get_month_name (gint month)
225 return C_("full month name", "January");
227 return C_("full month name", "February");
229 return C_("full month name", "March");
231 return C_("full month name", "April");
233 return C_("full month name", "May");
235 return C_("full month name", "June");
237 return C_("full month name", "July");
239 return C_("full month name", "August");
241 return C_("full month name", "September");
243 return C_("full month name", "October");
245 return C_("full month name", "November");
247 return C_("full month name", "December");
250 g_warning ("Invalid month number %d", month);
257 get_month_name_abbr (gint month)
262 return C_("abbreviated month name", "Jan");
264 return C_("abbreviated month name", "Feb");
266 return C_("abbreviated month name", "Mar");
268 return C_("abbreviated month name", "Apr");
270 return C_("abbreviated month name", "May");
272 return C_("abbreviated month name", "Jun");
274 return C_("abbreviated month name", "Jul");
276 return C_("abbreviated month name", "Aug");
278 return C_("abbreviated month name", "Sep");
280 return C_("abbreviated month name", "Oct");
282 return C_("abbreviated month name", "Nov");
284 return C_("abbreviated month name", "Dec");
287 g_warning ("Invalid month number %d", month);
294 get_weekday_name (gint day)
299 return C_("full weekday name", "Monday");
301 return C_("full weekday name", "Tuesday");
303 return C_("full weekday name", "Wednesday");
305 return C_("full weekday name", "Thursday");
307 return C_("full weekday name", "Friday");
309 return C_("full weekday name", "Saturday");
311 return C_("full weekday name", "Sunday");
314 g_warning ("Invalid week day number %d", day);
321 get_weekday_name_abbr (gint day)
326 return C_("abbreviated weekday name", "Mon");
328 return C_("abbreviated weekday name", "Tue");
330 return C_("abbreviated weekday name", "Wed");
332 return C_("abbreviated weekday name", "Thu");
334 return C_("abbreviated weekday name", "Fri");
336 return C_("abbreviated weekday name", "Sat");
338 return C_("abbreviated weekday name", "Sun");
341 g_warning ("Invalid week day number %d", day);
347 #endif /* HAVE_LANGINFO_TIME */
350 ymd_to_days (gint year,
356 days = (year - 1) * 365 + ((year - 1) / 4) - ((year - 1) / 100)
357 + ((year - 1) / 400);
359 days += days_in_year[0][month - 1];
360 if (GREGORIAN_LEAP (year) && month > 2)
369 g_date_time_get_week_number (GDateTime *datetime,
374 gint a, b, c, d, e, f, g, n, s, month, day, year;
376 g_date_time_get_ymd (datetime, &year, &month, &day);
380 a = g_date_time_get_year (datetime) - 1;
381 b = (a / 4) - (a / 100) + (a / 400);
382 c = ((a - 1) / 4) - ((a - 1) / 100) + ((a - 1) / 400);
385 f = day - 1 + (31 * (month - 1));
390 b = (a / 4) - (a / 100) + (a / 400);
391 c = ((a - 1) / 4) - ((a - 1) / 100) + ((a - 1) / 400);
394 f = day + (((153 * (month - 3)) + 2) / 5) + 58 + s;
404 *week_number = 53 - ((g - s) / 5);
405 else if (n > 364 + s)
408 *week_number = (n / 7) + 1;
412 *day_of_week = d + 1;
415 *day_of_year = f + 1;
421 g_date_time_alloc (GTimeZone *tz)
425 datetime = g_slice_new0 (GDateTime);
426 datetime->tz = g_time_zone_ref (tz);
427 datetime->ref_count = 1;
434 * @datetime: a #GDateTime
436 * Atomically increments the reference count of @datetime by one.
438 * Return value: the #GDateTime with the reference count increased
443 g_date_time_ref (GDateTime *datetime)
445 g_return_val_if_fail (datetime != NULL, NULL);
446 g_return_val_if_fail (datetime->ref_count > 0, NULL);
448 g_atomic_int_inc (&datetime->ref_count);
455 * @datetime: a #GDateTime
457 * Atomically decrements the reference count of @datetime by one.
459 * When the reference count reaches zero, the resources allocated by
460 * @datetime are freed
465 g_date_time_unref (GDateTime *datetime)
467 g_return_if_fail (datetime != NULL);
468 g_return_if_fail (datetime->ref_count > 0);
470 if (g_atomic_int_dec_and_test (&datetime->ref_count))
472 g_time_zone_unref (datetime->tz);
473 g_slice_free (GDateTime, datetime);
477 /* Internal state transformers {{{1 */
479 * g_date_time_to_instant:
480 * @datetime: a #GDateTime
482 * Convert a @datetime into an instant.
484 * An instant is a number that uniquely describes a particular
485 * microsecond in time, taking time zone considerations into account.
486 * (ie: "03:00 -0400" is the same instant as "02:00 -0500").
488 * An instant is always positive but we use a signed return value to
489 * avoid troubles with C.
492 g_date_time_to_instant (GDateTime *datetime)
496 offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
497 offset *= USEC_PER_SECOND;
499 return datetime->days * USEC_PER_DAY + datetime->usec - offset;
503 * g_date_time_from_instant:
505 * @instant: a instant in time
507 * Creates a #GDateTime from a time zone and an instant.
509 * This might fail if the time ends up being out of range.
512 g_date_time_from_instant (GTimeZone *tz,
518 if (instant < 0 || instant > G_GINT64_CONSTANT (1000000000000000000))
521 datetime = g_date_time_alloc (tz);
522 datetime->interval = g_time_zone_find_interval (tz,
523 G_TIME_TYPE_UNIVERSAL,
524 INSTANT_TO_UNIX (instant));
525 offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
526 offset *= USEC_PER_SECOND;
530 datetime->days = instant / USEC_PER_DAY;
531 datetime->usec = instant % USEC_PER_DAY;
533 if (datetime->days < 1 || 3652059 < datetime->days)
535 g_date_time_unref (datetime);
544 * g_date_time_deal_with_date_change:
545 * @datetime: a #GDateTime
547 * This function should be called whenever the date changes by adding
548 * days, months or years. It does three things.
550 * First, we ensure that the date falls between 0001-01-01 and
551 * 9999-12-31 and return %FALSE if it does not.
553 * Next we update the ->interval field.
555 * Finally, we ensure that the resulting date and time pair exists (by
556 * ensuring that our time zone has an interval containing it) and
557 * adjusting as required. For example, if we have the time 02:30:00 on
558 * March 13 2010 in Toronto and we add 1 day to it, we would end up with
559 * 2:30am on March 14th, which doesn't exist. In that case, we bump the
563 g_date_time_deal_with_date_change (GDateTime *datetime)
569 if (datetime->days < 1 || datetime->days > 3652059)
572 was_dst = g_time_zone_is_dst (datetime->tz, datetime->interval);
574 full_time = datetime->days * USEC_PER_DAY + datetime->usec;
577 usec = full_time % USEC_PER_SECOND;
578 full_time /= USEC_PER_SECOND;
579 full_time -= UNIX_EPOCH_START * SEC_PER_DAY;
581 datetime->interval = g_time_zone_adjust_time (datetime->tz,
584 full_time += UNIX_EPOCH_START * SEC_PER_DAY;
585 full_time *= USEC_PER_SECOND;
588 datetime->days = full_time / USEC_PER_DAY;
589 datetime->usec = full_time % USEC_PER_DAY;
591 /* maybe daylight time caused us to shift to a different day,
592 * but it definitely didn't push us into a different year */
597 g_date_time_replace_days (GDateTime *datetime,
602 new = g_date_time_alloc (datetime->tz);
603 new->interval = datetime->interval;
604 new->usec = datetime->usec;
607 if (!g_date_time_deal_with_date_change (new))
609 g_date_time_unref (new);
616 /* now/unix/timeval Constructors {{{1 */
619 * g_date_time_new_from_timeval:
623 * Creates a #GDateTime corresponding to the given #GTimeVal @tv in the
624 * given time zone @tz.
626 * The time contained in a #GTimeVal is always stored in the form of
627 * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the
630 * This call can fail (returning %NULL) if @tv represents a time outside
631 * of the supported range of #GDateTime.
633 * You should release the return value by calling g_date_time_unref()
634 * when you are done with it.
636 * Returns: a new #GDateTime, or %NULL
641 g_date_time_new_from_timeval (GTimeZone *tz,
644 return g_date_time_from_instant (tz, tv->tv_usec +
645 UNIX_TO_INSTANT (tv->tv_sec));
649 * g_date_time_new_from_unix:
653 * Creates a #GDateTime corresponding to the given Unix time @t in the
654 * given time zone @tz.
656 * Unix time is the number of seconds that have elapsed since 1970-01-01
657 * 00:00:00 UTC, regardless of the time zone given.
659 * This call can fail (returning %NULL) if @t represents a time outside
660 * of the supported range of #GDateTime.
662 * You should release the return value by calling g_date_time_unref()
663 * when you are done with it.
665 * Returns: a new #GDateTime, or %NULL
670 g_date_time_new_from_unix (GTimeZone *tz,
673 return g_date_time_from_instant (tz, UNIX_TO_INSTANT (secs));
677 * g_date_time_new_now:
680 * Creates a #GDateTime corresponding to this exact instant in the given
681 * time zone @tz. The time is as accurate as the system allows, to a
682 * maximum accuracy of 1 microsecond.
684 * This function will always succeed unless the system clock is set to
685 * truly insane values (or unless GLib is still being used after the
688 * You should release the return value by calling g_date_time_unref()
689 * when you are done with it.
691 * Returns: a new #GDateTime, or %NULL
696 g_date_time_new_now (GTimeZone *tz)
700 g_get_current_time (&tv);
702 return g_date_time_new_from_timeval (tz, &tv);
706 * g_date_time_new_now_local:
708 * Creates a #GDateTime corresponding to this exact instant in the local
711 * This is equivalent to calling g_date_time_new_now() with the time
712 * zone returned by g_time_zone_new_local().
714 * Returns: a new #GDateTime, or %NULL
719 g_date_time_new_now_local (void)
724 local = g_time_zone_new_local ();
725 datetime = g_date_time_new_now (local);
726 g_time_zone_unref (local);
732 * g_date_time_new_now_utc:
734 * Creates a #GDateTime corresponding to this exact instant in UTC.
736 * This is equivalent to calling g_date_time_new_now() with the time
737 * zone returned by g_time_zone_new_utc().
739 * Returns: a new #GDateTime, or %NULL
744 g_date_time_new_now_utc (void)
749 utc = g_time_zone_new_utc ();
750 datetime = g_date_time_new_now (utc);
751 g_time_zone_unref (utc);
757 * g_date_time_new_from_unix_local:
760 * Creates a #GDateTime corresponding to the given Unix time @t in the
763 * Unix time is the number of seconds that have elapsed since 1970-01-01
764 * 00:00:00 UTC, regardless of the local time offset.
766 * This call can fail (returning %NULL) if @t represents a time outside
767 * of the supported range of #GDateTime.
769 * You should release the return value by calling g_date_time_unref()
770 * when you are done with it.
772 * Returns: a new #GDateTime, or %NULL
777 g_date_time_new_from_unix_local (gint64 t)
782 local = g_time_zone_new_local ();
783 datetime = g_date_time_new_from_unix (local, t);
784 g_time_zone_unref (local);
790 * g_date_time_new_from_unix_utc:
793 * Creates a #GDateTime corresponding to the given Unix time @t in UTC.
795 * Unix time is the number of seconds that have elapsed since 1970-01-01
798 * This call can fail (returning %NULL) if @t represents a time outside
799 * of the supported range of #GDateTime.
801 * You should release the return value by calling g_date_time_unref()
802 * when you are done with it.
804 * Returns: a new #GDateTime, or %NULL
809 g_date_time_new_from_unix_utc (gint64 t)
814 utc = g_time_zone_new_utc ();
815 datetime = g_date_time_new_from_unix (utc, t);
816 g_time_zone_unref (utc);
822 * g_date_time_new_from_timeval_local:
825 * Creates a #GDateTime corresponding to the given #GTimeVal @tv in the
828 * The time contained in a #GTimeVal is always stored in the form of
829 * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the
832 * This call can fail (returning %NULL) if @tv represents a time outside
833 * of the supported range of #GDateTime.
835 * You should release the return value by calling g_date_time_unref()
836 * when you are done with it.
838 * Returns: a new #GDateTime, or %NULL
843 g_date_time_new_from_timeval_local (const GTimeVal *tv)
848 local = g_time_zone_new_local ();
849 datetime = g_date_time_new_from_timeval (local, tv);
850 g_time_zone_unref (local);
856 * g_date_time_new_from_timeval_utc:
859 * Creates a #GDateTime corresponding to the given #GTimeVal @tv in UTC.
861 * The time contained in a #GTimeVal is always stored in the form of
862 * seconds elapsed since 1970-01-01 00:00:00 UTC.
864 * This call can fail (returning %NULL) if @tv represents a time outside
865 * of the supported range of #GDateTime.
867 * You should release the return value by calling g_date_time_unref()
868 * when you are done with it.
870 * Returns: a new #GDateTime, or %NULL
875 g_date_time_new_from_timeval_utc (const GTimeVal *tv)
880 utc = g_time_zone_new_utc ();
881 datetime = g_date_time_new_from_timeval (utc, tv);
882 g_time_zone_unref (utc);
887 /* full new functions {{{1 */
892 * @year: the year component of the date
893 * @month: the month component of the date
894 * @day: the day component of the date
895 * @hour: the hour component of the date
896 * @minute: the minute component of the date
897 * @seconds: the number of seconds past the minute
899 * Creates a new #GDateTime corresponding to the given date and time in
902 * The @year must be between 1 and 9999, @month between 1 and 12 and @day
903 * between 1 and 28, 29, 30 or 31 depending on the month and the year.
905 * @hour must be between 0 and 23 and @minute must be between 0 and 59.
907 * @seconds must be at least 0.0 and must be strictly less than 60.0.
908 * It will be rounded down to the nearest microsecond.
910 * If the given time is not representable in the given time zone (for
911 * example, 02:30 on March 14th 2010 in Toronto, due to daylight savings
912 * time) then the time will be rounded up to the nearest existing time
913 * (in this case, 03:00). If this matters to you then you should verify
914 * the return value for containing the same as the numbers you gave.
916 * In the case that the given time is ambiguous in the given time zone
917 * (for example, 01:30 on November 7th 2010 in Toronto, due to daylight
918 * savings time) then the time falling within standard (ie:
919 * non-daylight) time is taken.
921 * It not considered a programmer error for the values to this function
922 * to be out of range, but in the case that they are, the function will
925 * You should release the return value by calling g_date_time_unref()
926 * when you are done with it.
928 * Returns: a new #GDateTime, or %NULL
933 g_date_time_new (GTimeZone *tz,
944 datetime = g_date_time_alloc (tz);
945 datetime->days = ymd_to_days (year, month, day);
946 datetime->usec = (hour * USEC_PER_HOUR)
947 + (minute * USEC_PER_MINUTE)
948 + (gint64) (seconds * USEC_PER_SECOND);
950 full_time = SEC_PER_DAY *
951 (ymd_to_days (year, month, day) - UNIX_EPOCH_START) +
952 SECS_PER_HOUR * hour +
953 SECS_PER_MINUTE * minute +
956 datetime->interval = g_time_zone_adjust_time (datetime->tz,
957 G_TIME_TYPE_STANDARD,
960 full_time += UNIX_EPOCH_START * SEC_PER_DAY;
961 datetime->days = full_time / SEC_PER_DAY;
962 datetime->usec = (full_time % SEC_PER_DAY) * USEC_PER_SECOND;
963 datetime->usec += ((int) (seconds * USEC_PER_SECOND)) % USEC_PER_SECOND;
969 * g_date_time_new_local:
970 * @year: the year component of the date
971 * @month: the month component of the date
972 * @day: the day component of the date
973 * @hour: the hour component of the date
974 * @minute: the minute component of the date
975 * @seconds: the number of seconds past the minute
977 * Creates a new #GDateTime corresponding to the given date and time in
978 * the local time zone.
980 * This call is equivalent to calling g_date_time_new() with the time
981 * zone returned by g_time_zone_new_local().
983 * Returns: a #GDateTime, or %NULL
988 g_date_time_new_local (gint year,
998 local = g_time_zone_new_local ();
999 datetime = g_date_time_new (local, year, month, day, hour, minute, seconds);
1000 g_time_zone_unref (local);
1006 * g_date_time_new_utc:
1007 * @year: the year component of the date
1008 * @month: the month component of the date
1009 * @day: the day component of the date
1010 * @hour: the hour component of the date
1011 * @minute: the minute component of the date
1012 * @seconds: the number of seconds past the minute
1014 * Creates a new #GDateTime corresponding to the given date and time in
1017 * This call is equivalent to calling g_date_time_new() with the time
1018 * zone returned by g_time_zone_new_utc().
1020 * Returns: a #GDateTime, or %NULL
1025 g_date_time_new_utc (gint year,
1032 GDateTime *datetime;
1035 utc = g_time_zone_new_utc ();
1036 datetime = g_date_time_new (utc, year, month, day, hour, minute, seconds);
1037 g_time_zone_unref (utc);
1046 * @datetime: a #GDateTime
1047 * @timespan: a #GTimeSpan
1049 * Creates a copy of @datetime and adds the specified timespan to the copy.
1051 * Return value: the newly created #GDateTime which should be freed with
1052 * g_date_time_unref().
1057 g_date_time_add (GDateTime *datetime,
1060 return g_date_time_from_instant (datetime->tz, timespan +
1061 g_date_time_to_instant (datetime));
1065 * g_date_time_add_years:
1066 * @datetime: a #GDateTime
1067 * @years: the number of years
1069 * Creates a copy of @datetime and adds the specified number of years to the
1072 * Return value: the newly created #GDateTime which should be freed with
1073 * g_date_time_unref().
1078 g_date_time_add_years (GDateTime *datetime,
1081 gint year, month, day;
1083 g_return_val_if_fail (datetime != NULL, NULL);
1085 if (years < -10000 || years > 10000)
1088 g_date_time_get_ymd (datetime, &year, &month, &day);
1091 /* only possible issue is if we've entered a year with no February 29
1093 if (month == 2 && day == 29 && !GREGORIAN_LEAP (year))
1096 return g_date_time_replace_days (datetime, ymd_to_days (year, month, day));
1100 * g_date_time_add_months:
1101 * @datetime: a #GDateTime
1102 * @months: the number of months
1104 * Creates a copy of @datetime and adds the specified number of months to the
1107 * Return value: the newly created #GDateTime which should be freed with
1108 * g_date_time_unref().
1113 g_date_time_add_months (GDateTime *datetime,
1116 gint year, month, day;
1118 g_return_val_if_fail (datetime != NULL, NULL);
1119 g_date_time_get_ymd (datetime, &year, &month, &day);
1121 if (months < -120000 || months > 120000)
1124 year += months / 12;
1125 month += months % 12;
1131 else if (month > 12)
1137 day = MIN (day, days_in_months[GREGORIAN_LEAP (year)][month]);
1139 return g_date_time_replace_days (datetime, ymd_to_days (year, month, day));
1143 * g_date_time_add_weeks:
1144 * @datetime: a #GDateTime
1145 * @weeks: the number of weeks
1147 * Creates a copy of @datetime and adds the specified number of weeks to the
1150 * Return value: the newly created #GDateTime which should be freed with
1151 * g_date_time_unref().
1156 g_date_time_add_weeks (GDateTime *datetime,
1159 g_return_val_if_fail (datetime != NULL, NULL);
1161 return g_date_time_add_days (datetime, weeks * 7);
1165 * g_date_time_add_days:
1166 * @datetime: a #GDateTime
1167 * @days: the number of days
1169 * Creates a copy of @datetime and adds the specified number of days to the
1172 * Return value: the newly created #GDateTime which should be freed with
1173 * g_date_time_unref().
1178 g_date_time_add_days (GDateTime *datetime,
1181 g_return_val_if_fail (datetime != NULL, NULL);
1183 if (days < -3660000 || days > 3660000)
1186 return g_date_time_replace_days (datetime, datetime->days + days);
1190 * g_date_time_add_hours:
1191 * @datetime: a #GDateTime
1192 * @hours: the number of hours to add
1194 * Creates a copy of @datetime and adds the specified number of hours
1196 * Return value: the newly created #GDateTime which should be freed with
1197 * g_date_time_unref().
1202 g_date_time_add_hours (GDateTime *datetime,
1205 return g_date_time_add (datetime, hours * USEC_PER_HOUR);
1209 * g_date_time_add_minutes:
1210 * @datetime: a #GDateTime
1211 * @minutes: the number of minutes to add
1213 * Creates a copy of @datetime adding the specified number of minutes.
1215 * Return value: the newly created #GDateTime which should be freed with
1216 * g_date_time_unref().
1221 g_date_time_add_minutes (GDateTime *datetime,
1224 return g_date_time_add (datetime, minutes * USEC_PER_MINUTE);
1229 * g_date_time_add_seconds:
1230 * @datetime: a #GDateTime
1231 * @seconds: the number of seconds to add
1233 * Creates a copy of @datetime and adds the specified number of seconds.
1235 * Return value: the newly created #GDateTime which should be freed with
1236 * g_date_time_unref().
1241 g_date_time_add_seconds (GDateTime *datetime,
1244 return g_date_time_add (datetime, seconds * USEC_PER_SECOND);
1248 * g_date_time_add_full:
1249 * @datetime: a #GDateTime
1250 * @years: the number of years to add
1251 * @months: the number of months to add
1252 * @days: the number of days to add
1253 * @hours: the number of hours to add
1254 * @minutes: the number of minutes to add
1255 * @seconds: the number of seconds to add
1257 * Creates a new #GDateTime adding the specified values to the current date and
1258 * time in @datetime.
1260 * Return value: the newly created #GDateTime that should be freed with
1261 * g_date_time_unref().
1266 g_date_time_add_full (GDateTime *datetime,
1274 gint year, month, day;
1279 g_return_val_if_fail (datetime != NULL, NULL);
1280 g_date_time_get_ymd (datetime, &year, &month, &day);
1282 months += years * 12;
1284 if (months < -120000 || months > 120000)
1287 if (days < -3660000 || days > 3660000)
1290 year += months / 12;
1291 month += months % 12;
1297 else if (month > 12)
1303 day = MIN (day, days_in_months[GREGORIAN_LEAP (year)][month]);
1305 /* full_time is now in unix (local) time */
1306 full_time = datetime->usec / USEC_PER_SECOND + SEC_PER_DAY *
1307 (ymd_to_days (year, month, day) + days - UNIX_EPOCH_START);
1309 interval = g_time_zone_adjust_time (datetime->tz,
1310 g_time_zone_is_dst (datetime->tz,
1311 datetime->interval),
1314 /* move to UTC unix time */
1315 full_time -= g_time_zone_get_offset (datetime->tz, interval);
1317 /* convert back to an instant, add back fractional seconds */
1318 full_time += UNIX_EPOCH_START * SEC_PER_DAY;
1319 full_time = full_time * USEC_PER_SECOND +
1320 datetime->usec % USEC_PER_SECOND;
1322 /* do the actual addition now */
1323 full_time += (hours * USEC_PER_HOUR) +
1324 (minutes * USEC_PER_MINUTE) +
1325 (gint64) (seconds * USEC_PER_SECOND);
1327 /* find the new interval */
1328 interval = g_time_zone_find_interval (datetime->tz,
1329 G_TIME_TYPE_UNIVERSAL,
1330 INSTANT_TO_UNIX (full_time));
1332 /* convert back into local time */
1333 full_time += USEC_PER_SECOND *
1334 g_time_zone_get_offset (datetime->tz, interval);
1336 /* split into days and usec of a new datetime */
1337 new = g_date_time_alloc (datetime->tz);
1338 new->interval = interval;
1339 new->days = full_time / USEC_PER_DAY;
1340 new->usec = full_time % USEC_PER_DAY;
1347 /* Compare, difference, hash, equal {{{1 */
1349 * g_date_time_compare:
1350 * @dt1: first #GDateTime to compare
1351 * @dt2: second #GDateTime to compare
1353 * A comparison function for #GDateTimes that is suitable
1354 * as a #GCompareFunc. Both #GDateTimes must be non-%NULL.
1356 * Return value: -1, 0 or 1 if @dt1 is less than, equal to or greater
1362 g_date_time_compare (gconstpointer dt1,
1367 difference = g_date_time_difference ((GDateTime *) dt1, (GDateTime *) dt2);
1372 else if (difference > 0)
1380 * g_date_time_difference:
1381 * @end: a #GDateTime
1382 * @begin: a #GDateTime
1384 * Calculates the difference in time between @end and @begin. The
1385 * #GTimeSpan that is returned is effectively @end - @begin (ie:
1386 * positive if the first simparameter is larger).
1388 * Return value: the difference between the two #GDateTime, as a time
1389 * span expressed in microseconds.
1394 g_date_time_difference (GDateTime *end,
1397 g_return_val_if_fail (begin != NULL, 0);
1398 g_return_val_if_fail (end != NULL, 0);
1400 return g_date_time_to_instant (end) -
1401 g_date_time_to_instant (begin);
1406 * @datetime: a #GDateTime
1408 * Hashes @datetime into a #guint, suitable for use within #GHashTable.
1410 * Return value: a #guint containing the hash
1415 g_date_time_hash (gconstpointer datetime)
1417 return g_date_time_to_instant ((GDateTime *) datetime);
1421 * g_date_time_equal:
1422 * @dt1: a #GDateTime
1423 * @dt2: a #GDateTime
1425 * Checks to see if @dt1 and @dt2 are equal.
1427 * Equal here means that they represent the same moment after converting
1428 * them to the same time zone.
1430 * Return value: %TRUE if @dt1 and @dt2 are equal
1435 g_date_time_equal (gconstpointer dt1,
1438 return g_date_time_difference ((GDateTime *) dt1, (GDateTime *) dt2) == 0;
1441 /* Year, Month, Day Getters {{{1 */
1443 * g_date_time_get_ymd:
1444 * @datetime: a #GDateTime.
1445 * @year: (out): the return location for the gregorian year, or %NULL.
1446 * @month: (out): the return location for the month of the year, or %NULL.
1447 * @day: (out): the return location for the day of the month, or %NULL.
1449 * Retrieves the Gregorian day, month, and year of a given #GDateTime.
1454 g_date_time_get_ymd (GDateTime *datetime,
1462 gint remaining_days;
1469 g_return_if_fail (datetime != NULL);
1471 remaining_days = datetime->days;
1474 * We need to convert an offset in days to its year/month/day representation.
1475 * Leap years makes this a little trickier than it should be, so we use
1476 * 400, 100 and 4 years cycles here to get to the correct year.
1479 /* Our days offset starts sets 0001-01-01 as day 1, if it was day 0 our
1480 * math would be simpler, so let's do it */
1483 the_year = (remaining_days / DAYS_IN_400YEARS) * 400 + 1;
1484 remaining_days = remaining_days % DAYS_IN_400YEARS;
1486 y100_cycles = remaining_days / DAYS_IN_100YEARS;
1487 remaining_days = remaining_days % DAYS_IN_100YEARS;
1488 the_year += y100_cycles * 100;
1490 y4_cycles = remaining_days / DAYS_IN_4YEARS;
1491 remaining_days = remaining_days % DAYS_IN_4YEARS;
1492 the_year += y4_cycles * 4;
1494 y1_cycles = remaining_days / 365;
1495 the_year += y1_cycles;
1496 remaining_days = remaining_days % 365;
1498 if (y1_cycles == 4 || y100_cycles == 4) {
1499 g_assert (remaining_days == 0);
1501 /* special case that indicates that the date is actually one year before,
1502 * in the 31th of December */
1509 /* now get the month and the day */
1510 leap = y1_cycles == 3 && (y4_cycles != 24 || y100_cycles == 3);
1512 g_assert (leap == GREGORIAN_LEAP(the_year));
1514 the_month = (remaining_days + 50) >> 5;
1515 preceding = (days_in_year[0][the_month - 1] + (the_month > 2 && leap));
1516 if (preceding > remaining_days)
1518 /* estimate is too large */
1520 preceding -= leap ? days_in_months[1][the_month]
1521 : days_in_months[0][the_month];
1524 remaining_days -= preceding;
1525 g_assert(0 <= remaining_days);
1527 the_day = remaining_days + 1;
1539 * g_date_time_get_year:
1540 * @datetime: A #GDateTime
1542 * Retrieves the year represented by @datetime in the Gregorian calendar.
1544 * Return value: the year represented by @datetime
1549 g_date_time_get_year (GDateTime *datetime)
1553 g_return_val_if_fail (datetime != NULL, 0);
1555 g_date_time_get_ymd (datetime, &year, NULL, NULL);
1561 * g_date_time_get_month:
1562 * @datetime: a #GDateTime
1564 * Retrieves the month of the year represented by @datetime in the Gregorian
1567 * Return value: the month represented by @datetime
1572 g_date_time_get_month (GDateTime *datetime)
1576 g_return_val_if_fail (datetime != NULL, 0);
1578 g_date_time_get_ymd (datetime, NULL, &month, NULL);
1584 * g_date_time_get_day_of_month:
1585 * @datetime: a #GDateTime
1587 * Retrieves the day of the month represented by @datetime in the gregorian
1590 * Return value: the day of the month
1595 g_date_time_get_day_of_month (GDateTime *datetime)
1599 const guint16 *days;
1602 g_return_val_if_fail (datetime != NULL, 0);
1604 days = days_in_year[GREGORIAN_LEAP (g_date_time_get_year (datetime)) ? 1 : 0];
1605 g_date_time_get_week_number (datetime, NULL, NULL, &day_of_year);
1607 for (i = 1; i <= 12; i++)
1609 if (days [i] >= day_of_year)
1610 return day_of_year - last;
1614 g_warn_if_reached ();
1618 /* Week of year / day of week getters {{{1 */
1620 * g_date_time_get_week_numbering_year:
1621 * @datetime: a #GDateTime
1623 * Returns the ISO 8601 week-numbering year in which the week containing
1626 * This function, taken together with g_date_time_get_week_of_year() and
1627 * g_date_time_get_day_of_week() can be used to determine the full ISO
1628 * week date on which @datetime falls.
1630 * This is usually equal to the normal Gregorian year (as returned by
1631 * g_date_time_get_year()), except as detailed below:
1633 * For Thursday, the week-numbering year is always equal to the usual
1634 * calendar year. For other days, the number is such that every day
1635 * within a complete week (Monday to Sunday) is contained within the
1636 * same week-numbering year.
1638 * For Monday, Tuesday and Wednesday occurring near the end of the year,
1639 * this may mean that the week-numbering year is one greater than the
1640 * calendar year (so that these days have the same week-numbering year
1641 * as the Thursday occurring early in the next year).
1643 * For Friday, Saturaday and Sunday occurring near the start of the year,
1644 * this may mean that the week-numbering year is one less than the
1645 * calendar year (so that these days have the same week-numbering year
1646 * as the Thursday occurring late in the previous year).
1648 * An equivalent description is that the week-numbering year is equal to
1649 * the calendar year containing the majority of the days in the current
1650 * week (Monday to Sunday).
1652 * Note that January 1 0001 in the proleptic Gregorian calendar is a
1653 * Monday, so this function never returns 0.
1655 * Returns: the ISO 8601 week-numbering year for @datetime
1660 g_date_time_get_week_numbering_year (GDateTime *datetime)
1662 gint year, month, day, weekday;
1664 g_date_time_get_ymd (datetime, &year, &month, &day);
1665 weekday = g_date_time_get_day_of_week (datetime);
1667 /* January 1, 2, 3 might be in the previous year if they occur after
1670 * Jan 1: Friday, Saturday, Sunday => day 1: weekday 5, 6, 7
1671 * Jan 2: Saturday, Sunday => day 2: weekday 6, 7
1672 * Jan 3: Sunday => day 3: weekday 7
1674 * So we have a special case if (day - weekday) <= -4
1676 if (month == 1 && (day - weekday) <= -4)
1679 /* December 29, 30, 31 might be in the next year if they occur before
1682 * Dec 31: Monday, Tuesday, Wednesday => day 31: weekday 1, 2, 3
1683 * Dec 30: Monday, Tuesday => day 30: weekday 1, 2
1684 * Dec 29: Monday => day 29: weekday 1
1686 * So we have a special case if (day - weekday) >= 28
1688 else if (month == 12 && (day - weekday) >= 28)
1696 * g_date_time_get_week_of_year:
1697 * @datetime: a #GDateTime
1699 * Returns the ISO 8601 week number for the week containing @datetime.
1700 * The ISO 8601 week number is the same for every day of the week (from
1701 * Moday through Sunday). That can produce some unusual results
1702 * (described below).
1704 * The first week of the year is week 1. This is the week that contains
1705 * the first Thursday of the year. Equivalently, this is the first week
1706 * that has more than 4 of its days falling within the calendar year.
1708 * The value 0 is never returned by this function. Days contained
1709 * within a year but occurring before the first ISO 8601 week of that
1710 * year are considered as being contained in the last week of the
1711 * previous year. Similarly, the final days of a calendar year may be
1712 * considered as being part of the first ISO 8601 week of the next year
1713 * if 4 or more days of that week are contained within the new year.
1715 * Returns: the ISO 8601 week number for @datetime.
1720 g_date_time_get_week_of_year (GDateTime *datetime)
1724 g_return_val_if_fail (datetime != NULL, 0);
1726 g_date_time_get_week_number (datetime, &weeknum, NULL, NULL);
1732 * g_date_time_get_day_of_week:
1733 * @datetime: a #GDateTime
1735 * Retrieves the ISO 8601 day of the week on which @datetime falls (1 is
1736 * Monday, 2 is Tuesday... 7 is Sunday).
1738 * Return value: the day of the week
1743 g_date_time_get_day_of_week (GDateTime *datetime)
1745 g_return_val_if_fail (datetime != NULL, 0);
1747 return (datetime->days - 1) % 7 + 1;
1750 /* Day of year getter {{{1 */
1752 * g_date_time_get_day_of_year:
1753 * @datetime: a #GDateTime
1755 * Retrieves the day of the year represented by @datetime in the Gregorian
1758 * Return value: the day of the year
1763 g_date_time_get_day_of_year (GDateTime *datetime)
1767 g_return_val_if_fail (datetime != NULL, 0);
1769 g_date_time_get_week_number (datetime, NULL, NULL, &doy);
1773 /* Time component getters {{{1 */
1776 * g_date_time_get_hour:
1777 * @datetime: a #GDateTime
1779 * Retrieves the hour of the day represented by @datetime
1781 * Return value: the hour of the day
1786 g_date_time_get_hour (GDateTime *datetime)
1788 g_return_val_if_fail (datetime != NULL, 0);
1790 return (datetime->usec / USEC_PER_HOUR);
1794 * g_date_time_get_minute:
1795 * @datetime: a #GDateTime
1797 * Retrieves the minute of the hour represented by @datetime
1799 * Return value: the minute of the hour
1804 g_date_time_get_minute (GDateTime *datetime)
1806 g_return_val_if_fail (datetime != NULL, 0);
1808 return (datetime->usec % USEC_PER_HOUR) / USEC_PER_MINUTE;
1812 * g_date_time_get_second:
1813 * @datetime: a #GDateTime
1815 * Retrieves the second of the minute represented by @datetime
1817 * Return value: the second represented by @datetime
1822 g_date_time_get_second (GDateTime *datetime)
1824 g_return_val_if_fail (datetime != NULL, 0);
1826 return (datetime->usec % USEC_PER_MINUTE) / USEC_PER_SECOND;
1830 * g_date_time_get_microsecond:
1831 * @datetime: a #GDateTime
1833 * Retrieves the microsecond of the date represented by @datetime
1835 * Return value: the microsecond of the second
1840 g_date_time_get_microsecond (GDateTime *datetime)
1842 g_return_val_if_fail (datetime != NULL, 0);
1844 return (datetime->usec % USEC_PER_SECOND);
1848 * g_date_time_get_seconds:
1849 * @datetime: a #GDateTime
1851 * Retrieves the number of seconds since the start of the last minute,
1852 * including the fractional part.
1854 * Returns: the number of seconds
1859 g_date_time_get_seconds (GDateTime *datetime)
1861 g_return_val_if_fail (datetime != NULL, 0);
1863 return (datetime->usec % USEC_PER_MINUTE) / 1000000.0;
1866 /* Exporters {{{1 */
1868 * g_date_time_to_unix:
1869 * @datetime: a #GDateTime
1871 * Gives the Unix time corresponding to @datetime, rounding down to the
1874 * Unix time is the number of seconds that have elapsed since 1970-01-01
1875 * 00:00:00 UTC, regardless of the time zone associated with @datetime.
1877 * Returns: the Unix time corresponding to @datetime
1882 g_date_time_to_unix (GDateTime *datetime)
1884 return INSTANT_TO_UNIX (g_date_time_to_instant (datetime));
1888 * g_date_time_to_timeval:
1889 * @datetime: a #GDateTime
1890 * @tv: a #GTimeVal to modify
1892 * Stores the instant in time that @datetime represents into @tv.
1894 * The time contained in a #GTimeVal is always stored in the form of
1895 * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the time
1896 * zone associated with @datetime.
1898 * On systems where 'long' is 32bit (ie: all 32bit systems and all
1899 * Windows systems), a #GTimeVal is incapable of storing the entire
1900 * range of values that #GDateTime is capable of expressing. On those
1901 * systems, this function returns %FALSE to indicate that the time is
1904 * On systems where 'long' is 64bit, this function never fails.
1906 * Returns: %TRUE if successful, else %FALSE
1911 g_date_time_to_timeval (GDateTime *datetime,
1914 tv->tv_sec = INSTANT_TO_UNIX (g_date_time_to_instant (datetime));
1915 tv->tv_usec = datetime->usec % USEC_PER_SECOND;
1920 /* Timezone queries {{{1 */
1922 * g_date_time_get_utc_offset:
1923 * @datetime: a #GDateTime
1925 * Determines the offset to UTC in effect at the time and in the time
1926 * zone of @datetime.
1928 * The offset is the number of microseconds that you add to UTC time to
1929 * arrive at local time for the time zone (ie: negative numbers for time
1930 * zones west of GMT, positive numbers for east).
1932 * If @datetime represents UTC time, then the offset is always zero.
1934 * Returns: the number of microseconds that should be added to UTC to
1935 * get the local time
1940 g_date_time_get_utc_offset (GDateTime *datetime)
1944 g_return_val_if_fail (datetime != NULL, 0);
1946 offset = g_time_zone_get_offset (datetime->tz, datetime->interval);
1948 return (gint64) offset * USEC_PER_SECOND;
1952 * g_date_time_get_timezone_abbreviation:
1953 * @datetime: a #GDateTime
1955 * Determines the time zone abbreviation to be used at the time and in
1956 * the time zone of @datetime.
1958 * For example, in Toronto this is currently "EST" during the winter
1959 * months and "EDT" during the summer months when daylight savings
1960 * time is in effect.
1962 * Returns: (transfer none): the time zone abbreviation. The returned
1963 * string is owned by the #GDateTime and it should not be
1969 g_date_time_get_timezone_abbreviation (GDateTime *datetime)
1971 g_return_val_if_fail (datetime != NULL, NULL);
1973 return g_time_zone_get_abbreviation (datetime->tz, datetime->interval);
1977 * g_date_time_is_daylight_savings:
1978 * @datetime: a #GDateTime
1980 * Determines if daylight savings time is in effect at the time and in
1981 * the time zone of @datetime.
1983 * Returns: %TRUE if daylight savings time is in effect
1988 g_date_time_is_daylight_savings (GDateTime *datetime)
1990 g_return_val_if_fail (datetime != NULL, FALSE);
1992 return g_time_zone_is_dst (datetime->tz, datetime->interval);
1995 /* Timezone convert {{{1 */
1997 * g_date_time_to_timezone:
1998 * @datetime: a #GDateTime
1999 * @tz: the new #GTimeZone
2001 * Create a new #GDateTime corresponding to the same instant in time as
2002 * @datetime, but in the time zone @tz.
2004 * This call can fail in the case that the time goes out of bounds. For
2005 * example, converting 0001-01-01 00:00:00 UTC to a time zone west of
2006 * Greenwich will fail (due to the year 0 being out of range).
2008 * You should release the return value by calling g_date_time_unref()
2009 * when you are done with it.
2011 * Returns: a new #GDateTime, or %NULL
2016 g_date_time_to_timezone (GDateTime *datetime,
2019 return g_date_time_from_instant (tz, g_date_time_to_instant (datetime));
2023 * g_date_time_to_local:
2024 * @datetime: a #GDateTime
2026 * Creates a new #GDateTime corresponding to the same instant in time as
2027 * @datetime, but in the local time zone.
2029 * This call is equivalent to calling g_date_time_to_timezone() with the
2030 * time zone returned by g_time_zone_new_local().
2032 * Returns: the newly created #GDateTime
2037 g_date_time_to_local (GDateTime *datetime)
2042 local = g_time_zone_new_local ();
2043 new = g_date_time_to_timezone (datetime, local);
2044 g_time_zone_unref (local);
2050 * g_date_time_to_utc:
2051 * @datetime: a #GDateTime
2053 * Creates a new #GDateTime corresponding to the same instant in time as
2054 * @datetime, but in UTC.
2056 * This call is equivalent to calling g_date_time_to_timezone() with the
2057 * time zone returned by g_time_zone_new_utc().
2059 * Returns: the newly created #GDateTime
2064 g_date_time_to_utc (GDateTime *datetime)
2069 utc = g_time_zone_new_utc ();
2070 new = g_date_time_to_timezone (datetime, utc);
2071 g_time_zone_unref (utc);
2079 get_numeric_format (gchar *fmt,
2081 gboolean alt_digits,
2085 const gchar *width_str;
2097 g_warning ("get_numeric_format: width %d not handled", width);
2114 g_snprintf (fmt, len, "%%%s%sd", alt_digits ? "I": "", width_str);
2118 * g_date_time_format:
2119 * @datetime: A #GDateTime
2120 * @format: a valid UTF-8 string, containing the format for the
2123 * Creates a newly allocated string representing the requested @format.
2125 * The format strings understood by this function are a subset of the
2126 * strftime() format language. In contrast to strftime(), this function
2127 * always produces a UTF-8 string, regardless of the current locale.
2128 * Note that the rendering of many formats is locale-dependent and may
2129 * not match the strftime() output exactly.
2131 * The following format specifiers are supported:
2134 * <varlistentry><term>
2135 * <literal>%%a</literal>:
2136 * </term><listitem><simpara>
2137 * the abbreviated weekday name according to the current locale
2138 * </simpara></listitem></varlistentry>
2139 * <varlistentry><term>
2140 * <literal>%%A</literal>:
2141 * </term><listitem><simpara>
2142 * the full weekday name according to the current locale
2143 * </simpara></listitem></varlistentry>
2144 * <varlistentry><term>
2145 * <literal>%%b</literal>:
2146 * </term><listitem><simpara>
2147 * the abbreviated month name according to the current locale
2148 * </simpara></listitem></varlistentry>
2149 * <varlistentry><term>
2150 * <literal>%%B</literal>:
2151 * </term><listitem><simpara>
2152 * the full month name according to the current locale
2153 * </simpara></listitem></varlistentry>
2154 * <varlistentry><term>
2155 * <literal>%%c</literal>:
2156 * </term><listitem><simpara>
2157 * the preferred date and time representation for the current locale
2158 * </simpara></listitem></varlistentry>
2159 * <varlistentry><term>
2160 * <literal>%%C</literal>:
2161 * </term><listitem><simpara>
2162 * The century number (year/100) as a 2-digit integer (00-99)
2163 * </simpara></listitem></varlistentry>
2164 * <varlistentry><term>
2165 * <literal>%%d</literal>:
2166 * </term><listitem><simpara>
2167 * the day of the month as a decimal number (range 01 to 31)
2168 * </simpara></listitem></varlistentry>
2169 * <varlistentry><term>
2170 * <literal>%%e</literal>:
2171 * </term><listitem><simpara>
2172 * the day of the month as a decimal number (range 1 to 31)
2173 * </simpara></listitem></varlistentry>
2174 * <varlistentry><term>
2175 * <literal>%%F</literal>:
2176 * </term><listitem><simpara>
2177 * equivalent to <literal>%%Y-%%m-%%d</literal> (the ISO 8601 date
2179 * </simpara></listitem></varlistentry>
2180 * <varlistentry><term>
2181 * <literal>%%h</literal>:
2182 * </term><listitem><simpara>
2183 * equivalent to <literal>%%b</literal>
2184 * </simpara></listitem></varlistentry>
2185 * <varlistentry><term>
2186 * <literal>%%H</literal>:
2187 * </term><listitem><simpara>
2188 * the hour as a decimal number using a 24-hour clock (range 00 to
2190 * </simpara></listitem></varlistentry>
2191 * <varlistentry><term>
2192 * <literal>%%I</literal>:
2193 * </term><listitem><simpara>
2194 * the hour as a decimal number using a 12-hour clock (range 01 to
2196 * </simpara></listitem></varlistentry>
2197 * <varlistentry><term>
2198 * <literal>%%j</literal>:
2199 * </term><listitem><simpara>
2200 * the day of the year as a decimal number (range 001 to 366)
2201 * </simpara></listitem></varlistentry>
2202 * <varlistentry><term>
2203 * <literal>%%k</literal>:
2204 * </term><listitem><simpara>
2205 * the hour (24-hour clock) as a decimal number (range 0 to 23);
2206 * single digits are preceded by a blank
2207 * </simpara></listitem></varlistentry>
2208 * <varlistentry><term>
2209 * <literal>%%l</literal>:
2210 * </term><listitem><simpara>
2211 * the hour (12-hour clock) as a decimal number (range 1 to 12);
2212 * single digits are preceded by a blank
2213 * </simpara></listitem></varlistentry>
2214 * <varlistentry><term>
2215 * <literal>%%m</literal>:
2216 * </term><listitem><simpara>
2217 * the month as a decimal number (range 01 to 12)
2218 * </simpara></listitem></varlistentry>
2219 * <varlistentry><term>
2220 * <literal>%%M</literal>:
2221 * </term><listitem><simpara>
2222 * the minute as a decimal number (range 00 to 59)
2223 * </simpara></listitem></varlistentry>
2224 * <varlistentry><term>
2225 * <literal>%%p</literal>:
2226 * </term><listitem><simpara>
2227 * either "AM" or "PM" according to the given time value, or the
2228 * corresponding strings for the current locale. Noon is treated as
2229 * "PM" and midnight as "AM".
2230 * </simpara></listitem></varlistentry>
2231 * <varlistentry><term>
2232 * <literal>%%P</literal>:
2233 * </term><listitem><simpara>
2234 * like %%p but lowercase: "am" or "pm" or a corresponding string for
2235 * the current locale
2236 * </simpara></listitem></varlistentry>
2237 * <varlistentry><term>
2238 * <literal>%%r</literal>:
2239 * </term><listitem><simpara>
2240 * the time in a.m. or p.m. notation
2241 * </simpara></listitem></varlistentry>
2242 * <varlistentry><term>
2243 * <literal>%%R</literal>:
2244 * </term><listitem><simpara>
2245 * the time in 24-hour notation (<literal>%%H:%%M</literal>)
2246 * </simpara></listitem></varlistentry>
2247 * <varlistentry><term>
2248 * <literal>%%s</literal>:
2249 * </term><listitem><simpara>
2250 * the number of seconds since the Epoch, that is, since 1970-01-01
2252 * </simpara></listitem></varlistentry>
2253 * <varlistentry><term>
2254 * <literal>%%S</literal>:
2255 * </term><listitem><simpara>
2256 * the second as a decimal number (range 00 to 60)
2257 * </simpara></listitem></varlistentry>
2258 * <varlistentry><term>
2259 * <literal>%%t</literal>:
2260 * </term><listitem><simpara>
2262 * </simpara></listitem></varlistentry>
2263 * <varlistentry><term>
2264 * <literal>%%T</literal>:
2265 * </term><listitem><simpara>
2266 * the time in 24-hour notation with seconds (<literal>%%H:%%M:%%S</literal>)
2267 * </simpara></listitem></varlistentry>
2268 * <varlistentry><term>
2269 * <literal>%%u</literal>:
2270 * </term><listitem><simpara>
2271 * the day of the week as a decimal, range 1 to 7, Monday being 1
2272 * </simpara></listitem></varlistentry>
2273 * <varlistentry><term>
2274 * <literal>%%V</literal>:
2275 * </term><listitem><simpara>
2276 * the ISO 8601 week number of the current year as a decimal number,
2277 * range 01 to 53, where week 1 is the first week that has at least
2278 * 4 days in the new year. See g_date_time_get_week_of_year().
2279 * </simpara></listitem></varlistentry>
2280 * <varlistentry><term>
2281 * <literal>%%w</literal>:
2282 * </term><listitem><simpara>
2283 * the day of the week as a decimal, range 0 to 6, Sunday being 0
2284 * </simpara></listitem></varlistentry>
2285 * <varlistentry><term>
2286 * <literal>%%W</literal>:
2287 * </term><listitem><simpara>
2288 * the week number of the current year as a decimal number
2289 * </simpara></listitem></varlistentry>
2290 * <varlistentry><term>
2291 * <literal>%%x</literal>:
2292 * </term><listitem><simpara>
2293 * the preferred date representation for the current locale without
2295 * </simpara></listitem></varlistentry>
2296 * <varlistentry><term>
2297 * <literal>%%X</literal>:
2298 * </term><listitem><simpara>
2299 * the preferred time representation for the current locale without
2301 * </simpara></listitem></varlistentry>
2302 * <varlistentry><term>
2303 * <literal>%%y</literal>:
2304 * </term><listitem><simpara>
2305 * the year as a decimal number without the century
2306 * </simpara></listitem></varlistentry>
2307 * <varlistentry><term>
2308 * <literal>%%Y</literal>:
2309 * </term><listitem><simpara>
2310 * the year as a decimal number including the century
2311 * </simpara></listitem></varlistentry>
2312 * <varlistentry><term>
2313 * <literal>%%z</literal>:
2314 * </term><listitem><simpara>
2315 * the time-zone as hour offset from UTC
2316 * </simpara></listitem></varlistentry>
2317 * <varlistentry><term>
2318 * <literal>%%Z</literal>:
2319 * </term><listitem><simpara>
2320 * the time zone or name or abbreviation
2321 * </simpara></listitem></varlistentry>
2322 * <varlistentry><term>
2323 * <literal>%%%</literal>:
2324 * </term><listitem><simpara>
2325 * a literal <literal>%%</literal> character
2326 * </simpara></listitem></varlistentry>
2329 * Some conversion specifications can be modified by preceding the
2330 * conversion specifier by one or more modifier characters. The
2331 * following modifiers are supported for many of the numeric
2337 * Use alternative numeric symbols, if the current locale
2344 * Pad a numeric result with spaces.
2345 * This overrides the default padding for the specifier.
2351 * Do not pad a numeric result.
2352 * This overrides the default padding for the specifier.
2358 * Pad a numeric result with zeros.
2359 * This overrides the default padding for the specifier.
2364 * Returns: a newly allocated string formatted to the requested format
2365 * or %NULL in the case that there was an error. The string
2366 * should be freed with g_free().
2371 g_date_time_format (GDateTime *datetime,
2372 const gchar *format)
2377 gboolean in_mod = FALSE;
2378 gboolean alt_digits = FALSE;
2379 gboolean pad_set = FALSE;
2384 g_return_val_if_fail (datetime != NULL, NULL);
2385 g_return_val_if_fail (format != NULL, NULL);
2386 g_return_val_if_fail (g_utf8_validate (format, -1, NULL), NULL);
2388 outstr = g_string_sized_new (strlen (format) * 2);
2391 for (; *format; format = g_utf8_next_char (format))
2393 c = g_utf8_get_char (format);
2412 g_string_append (outstr, WEEKDAY_ABBR (datetime));
2415 g_string_append (outstr, WEEKDAY_FULL (datetime));
2418 g_string_append (outstr, MONTH_ABBR (datetime));
2421 g_string_append (outstr, MONTH_FULL (datetime));
2425 tmp = g_date_time_format (datetime, PREFERRED_DATE_TIME_FMT);
2426 g_string_append (outstr, tmp);
2431 get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : '0', 2);
2432 g_string_append_printf (outstr, fmt, g_date_time_get_year (datetime) / 100);
2434 get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : '0', 2);
2435 g_string_append_printf (outstr, fmt, g_date_time_get_day_of_month (datetime));
2438 get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : 0, 2);
2439 g_string_append_printf (outstr, fmt, g_date_time_get_day_of_month (datetime));
2442 g_string_append_printf (outstr, "%d-%02d-%02d",
2443 g_date_time_get_year (datetime),
2444 g_date_time_get_month (datetime),
2445 g_date_time_get_day_of_month (datetime));
2448 g_string_append (outstr, MONTH_ABBR (datetime));
2451 get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : '0', 2);
2452 g_string_append_printf (outstr, fmt, g_date_time_get_hour (datetime));
2456 gint hour = g_date_time_get_hour (datetime) % 12;
2459 get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : '0', 2);
2460 g_string_append_printf (outstr, fmt, hour);
2464 get_numeric_format (fmt, sizeof(fmt), FALSE, pad_set ? pad : '0', 3);
2465 g_string_append_printf (outstr, fmt, g_date_time_get_day_of_year (datetime));
2468 get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : ' ', 2);
2469 g_string_append_printf (outstr, fmt, g_date_time_get_hour (datetime));
2473 gint hour = g_date_time_get_hour (datetime) % 12;
2476 get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : ' ', 2);
2477 g_string_append_printf (outstr, fmt, hour);
2481 get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : '0', 2);
2482 g_string_append_printf (outstr, fmt, g_date_time_get_month (datetime));
2485 get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : '0', 2);
2486 g_string_append_printf (outstr, fmt, g_date_time_get_minute (datetime));
2492 ampm = g_utf8_strup (GET_AMPM (datetime), -1);
2493 g_string_append (outstr, ampm);
2497 ampm = g_utf8_strdown (GET_AMPM (datetime), -1);
2498 g_string_append (outstr, ampm);
2503 gint hour = g_date_time_get_hour (datetime) % 12;
2506 ampm = g_utf8_strup (GET_AMPM (datetime), -1);
2507 g_string_append_printf (outstr, "%02d:%02d:%02d %s",
2509 g_date_time_get_minute (datetime),
2510 g_date_time_get_second (datetime),
2516 g_string_append_printf (outstr, "%02d:%02d",
2517 g_date_time_get_hour (datetime),
2518 g_date_time_get_minute (datetime));
2521 g_string_append_printf (outstr, "%" G_GINT64_FORMAT, g_date_time_to_unix (datetime));
2524 get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : '0', 2);
2525 g_string_append_printf (outstr, fmt, g_date_time_get_second (datetime));
2528 g_string_append_c (outstr, '\t');
2531 g_string_append_printf (outstr, "%02d:%02d:%02d",
2532 g_date_time_get_hour (datetime),
2533 g_date_time_get_minute (datetime),
2534 g_date_time_get_second (datetime));
2537 get_numeric_format (fmt, sizeof(fmt), alt_digits, 0, 0);
2538 g_string_append_printf (outstr, fmt, g_date_time_get_day_of_week (datetime));
2541 get_numeric_format (fmt, sizeof(fmt), alt_digits, '0', 2);
2542 g_string_append_printf (outstr, fmt, g_date_time_get_week_of_year (datetime));
2546 gint day_of_week = g_date_time_get_day_of_week (datetime);
2547 if (day_of_week == 7)
2549 get_numeric_format (fmt, sizeof(fmt), alt_digits, 0, 0);
2550 g_string_append_printf (outstr, fmt, day_of_week);
2554 get_numeric_format (fmt, sizeof(fmt), alt_digits, 0, 0);
2555 g_string_append_printf (outstr, fmt, g_date_time_get_day_of_year (datetime) / 7);
2559 tmp = g_date_time_format (datetime, PREFERRED_DATE_FMT);
2560 g_string_append (outstr, tmp);
2566 tmp = g_date_time_format (datetime, PREFERRED_TIME_FMT);
2567 g_string_append (outstr, tmp);
2572 get_numeric_format (fmt, sizeof(fmt), alt_digits, pad_set ? pad : '0', 2);
2573 g_string_append_printf (outstr, fmt, g_date_time_get_year (datetime) % 100);
2576 get_numeric_format (fmt, sizeof(fmt), alt_digits, 0, 0);
2577 g_string_append_printf (outstr, fmt, g_date_time_get_year (datetime));
2580 if (datetime->tz != NULL)
2582 gint64 offset = g_date_time_get_utc_offset (datetime)
2585 g_string_append_printf (outstr, "%+03d%02d",
2586 (int) offset / 3600,
2587 (int) abs(offset) / 60 % 60);
2590 g_string_append (outstr, "+0000");
2593 g_string_append (outstr, g_date_time_get_timezone_abbreviation (datetime));
2596 g_string_append_c (outstr, '%');
2599 g_string_append_c (outstr, '\n');
2619 g_string_append_unichar (outstr, c);
2624 return g_string_free (outstr, FALSE);
2627 g_string_free (outstr, TRUE);
2633 /* vim:set foldmethod=marker: */