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>
7 * This is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 /* Algorithms within this file are based on the Calendar FAQ by
23 * Claus Tondering. It can be found at
24 * http://www.tondering.dk/claus/cal/calendar29.txt
26 * Copyright and disclaimer
27 * ------------------------
28 * This document is Copyright (C) 2008 by Claus Tondering.
29 * E-mail: claus@tondering.dk. (Please include the word
30 * "calendar" in the subject line.)
31 * The document may be freely distributed, provided this
32 * copyright notice is included and no money is charged for
35 * This document is provided "as is". No warranties are made as
51 #endif /* !G_OS_WIN32 */
53 #include "gdatetime.h"
56 #include "gfileutils.h"
59 #include "gmappedfile.h"
60 #include "gstrfuncs.h"
61 #include "gtestutils.h"
69 * @short_description: A structure representing Date and Time
71 * #GDateTime is a structure that combines a date and time into a single
72 * structure. It provides many conversion and methods to manipulate dates
73 * and times. Time precision is provided down to microseconds.
75 * #GDateTime is an immutable object: once it has been created it cannot be
76 * modified further. All modifiers will create a new #GDateTime.
78 * #GDateTime is reference counted: the reference count is increased by calling
79 * g_date_time_ref() and decreased by calling g_date_time_unref(). When the
80 * reference count drops to 0, the resources allocated by the #GDateTime
81 * structure are released.
83 * Internally, #GDateTime uses the Proleptic Gregorian Calendar, the first
84 * representable date is 0001-01-01. However, the public API uses the
85 * internationally accepted Gregorian Calendar.
87 * #GDateTime is available since GLib 2.26.
90 #define UNIX_EPOCH_START 719163
92 #define DAYS_IN_4YEARS 1461 /* days in 4 years */
93 #define DAYS_IN_100YEARS 36524 /* days in 100 years */
94 #define DAYS_IN_400YEARS 146097 /* days in 400 years */
96 #define USEC_PER_SECOND (G_GINT64_CONSTANT (1000000))
97 #define USEC_PER_MINUTE (G_GINT64_CONSTANT (60000000))
98 #define USEC_PER_HOUR (G_GINT64_CONSTANT (3600000000))
99 #define USEC_PER_MILLISECOND (G_GINT64_CONSTANT (1000))
100 #define USEC_PER_DAY (G_GINT64_CONSTANT (86400000000))
101 #define SEC_PER_DAY (G_GINT64_CONSTANT (86400))
103 #define GREGORIAN_LEAP(y) ((((y) % 4) == 0) && (!((((y) % 100) == 0) && (((y) % 400) != 0))))
104 #define JULIAN_YEAR(d) ((d)->julian / 365.25)
105 #define DAYS_PER_PERIOD (G_GINT64_CONSTANT (2914695))
107 #define GET_AMPM(d,l) ((g_date_time_get_hour (d) < 12) \
108 /* Translators: 'before midday' indicator */ \
109 ? (l ? C_("GDateTime", "am") \
110 /* Translators: 'before midday' indicator */ \
111 : C_("GDateTime", "AM")) \
112 /* Translators: 'after midday' indicator */ \
113 : (l ? C_("GDateTime", "pm") \
114 /* Translators: 'after midday' indicator */ \
115 : C_("GDateTime", "PM")))
117 #define WEEKDAY_ABBR(d) (get_weekday_name_abbr (g_date_time_get_day_of_week (datetime)))
118 #define WEEKDAY_FULL(d) (get_weekday_name (g_date_time_get_day_of_week (datetime)))
120 #define MONTH_ABBR(d) (get_month_name_abbr (g_date_time_get_month (datetime)))
121 #define MONTH_FULL(d) (get_month_name (g_date_time_get_month (datetime)))
123 /* Translators: this is the preferred format for expressing the date */
124 #define GET_PREFERRED_DATE(d) (g_date_time_printf ((d), C_("GDateTime", "%m/%d/%y")))
126 /* Translators: this is the preferred format for expressing the time */
127 #define GET_PREFERRED_TIME(d) (g_date_time_printf ((d), C_("GDateTime", "%H:%M:%S")))
129 #define SECS_PER_MINUTE (60)
130 #define SECS_PER_HOUR (60 * SECS_PER_MINUTE)
131 #define SECS_PER_DAY (24 * SECS_PER_HOUR)
132 #define SECS_PER_YEAR (365 * SECS_PER_DAY)
133 #define SECS_PER_JULIAN (DAYS_PER_PERIOD * SECS_PER_DAY)
135 typedef struct _GTimeZoneFile GTimeZoneFile;
139 /* 1 is 0001-01-01 in Proleptic Gregorian */
142 /* Microsecond timekeeping within Day */
145 /* TimeZone information, NULL is UTC */
148 volatile gint ref_count;
153 GTimeZoneFile *tz_file;
161 guint is_floating : 1;
164 struct _GTimeZoneFile
170 volatile gint ref_count;
173 G_LOCK_DEFINE_STATIC (time_zone_files);
174 static GHashTable *time_zone_files = NULL;
176 static const guint16 days_in_months[2][13] =
178 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
179 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
182 static const guint16 days_in_year[2][13] =
184 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
185 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
189 get_month_name (gint month)
194 return C_("full month name", "January");
196 return C_("full month name", "February");
198 return C_("full month name", "March");
200 return C_("full month name", "April");
202 return C_("full month name", "May");
204 return C_("full month name", "June");
206 return C_("full month name", "July");
208 return C_("full month name", "August");
210 return C_("full month name", "September");
212 return C_("full month name", "October");
214 return C_("full month name", "November");
216 return C_("full month name", "December");
219 g_warning ("Invalid month number %d", month);
226 get_month_name_abbr (gint month)
231 return C_("abbreviated month name", "Jan");
233 return C_("abbreviated month name", "Feb");
235 return C_("abbreviated month name", "Mar");
237 return C_("abbreviated month name", "Apr");
239 return C_("abbreviated month name", "May");
241 return C_("abbreviated month name", "Jun");
243 return C_("abbreviated month name", "Jul");
245 return C_("abbreviated month name", "Aug");
247 return C_("abbreviated month name", "Sep");
249 return C_("abbreviated month name", "Oct");
251 return C_("abbreviated month name", "Nov");
253 return C_("abbreviated month name", "Dec");
256 g_warning ("Invalid month number %d", month);
263 get_weekday_name (gint day)
268 return C_("full weekday name", "Monday");
270 return C_("full weekday name", "Tuesday");
272 return C_("full weekday name", "Wednesday");
274 return C_("full weekday name", "Thursday");
276 return C_("full weekday name", "Friday");
278 return C_("full weekday name", "Saturday");
280 return C_("full weekday name", "Sunday");
283 g_warning ("Invalid week day number %d", day);
290 get_weekday_name_abbr (gint day)
295 return C_("abbreviated weekday name", "Mon");
297 return C_("abbreviated weekday name", "Tue");
299 return C_("abbreviated weekday name", "Wed");
301 return C_("abbreviated weekday name", "Thu");
303 return C_("abbreviated weekday name", "Fri");
305 return C_("abbreviated weekday name", "Sat");
307 return C_("abbreviated weekday name", "Sun");
310 g_warning ("Invalid week day number %d", day);
317 date_to_proleptic_gregorian (gint year,
323 days = (year - 1) * 365 + ((year - 1) / 4) - ((year - 1) / 100)
324 + ((year - 1) / 400);
326 days += days_in_year[0][month - 1];
327 if (GREGORIAN_LEAP (year) && month > 2)
336 g_date_time_add_days_internal (GDateTime *datetime,
339 datetime->days += days;
343 g_date_time_add_usec (GDateTime *datetime,
346 gint64 u = datetime->usec + usecs;
347 gint d = u / USEC_PER_DAY;
353 g_date_time_add_days_internal (datetime, d);
356 datetime->usec = USEC_PER_DAY + (u % USEC_PER_DAY);
358 datetime->usec = u % USEC_PER_DAY;
362 * g_date_time_add_ymd:
363 * @datetime: a #GDateTime
364 * @years: years to add, in the Gregorian calendar
365 * @months: months to add, in the Gregorian calendar
366 * @days: days to add, in the Gregorian calendar
368 * Updates @datetime by adding @years, @months and @days to it
370 * This function modifies the passed #GDateTime so public accessors
371 * should make always pass a copy
374 g_date_time_add_ymd (GDateTime *datetime,
379 gint y = g_date_time_get_year (datetime);
380 gint m = g_date_time_get_month (datetime);
381 gint d = g_date_time_get_day_of_month (datetime);
383 const guint16 *max_days;
387 /* subtract one day for leap years */
388 if (GREGORIAN_LEAP (y) && m == 2)
395 step = months > 0 ? 1 : -1;
396 for (i = 0; i < ABS (months); i++)
413 max_days = days_in_months[GREGORIAN_LEAP (y) ? 1 : 0];
417 datetime->days = date_to_proleptic_gregorian (y, m, d);
418 g_date_time_add_days_internal (datetime, days);
421 #define ZONEINFO_DIR "zoneinfo"
422 #define TZ_MAGIC "TZif"
423 #define TZ_MAGIC_LEN (strlen (TZ_MAGIC))
424 #define TZ_HEADER_SIZE 44
425 #define TZ_TIMECNT_OFFSET 32
426 #define TZ_TYPECNT_OFFSET 36
427 #define TZ_TRANSITIONS_OFFSET 44
428 #define TZ_TTINFO_SIZE 6
429 #define TZ_TTINFO_GMTOFF_OFFSET 0
430 #define TZ_TTINFO_ISDST_OFFSET 4
431 #define TZ_TTINFO_NAME_OFFSET 5
434 get_tzdata_path (const gchar *tz_name)
436 gchar *retval = NULL;
437 const gchar *tz_dir = g_getenv ("TZDIR");
440 retval = g_build_filename (tz_dir, tz_name, NULL);
443 if (strcmp (tz_name, "localtime") == 0)
444 retval = g_build_filename ("/", "etc", "localtime", NULL);
446 retval = g_build_filename ("/", "usr", "share", ZONEINFO_DIR, tz_name, NULL);
453 parse_tzdata (GTimeZoneFile *tz_file,
462 guint32 timecnt, typecnt;
463 gint transitions_size, ttinfo_map_size;
464 guint8 *ttinfo_map, *ttinfos;
465 gint start_transition = -1;
466 guint32 *transitions;
472 contents = g_mapped_file_get_contents (tz_file->file);
473 length = g_mapped_file_get_length (tz_file->file);
475 if (length < TZ_HEADER_SIZE ||
476 (strncmp (contents, TZ_MAGIC, TZ_MAGIC_LEN) != 0))
481 timecnt = GUINT32_FROM_BE (*(guint32 *)(contents + TZ_TIMECNT_OFFSET));
482 typecnt = GUINT32_FROM_BE (*(guint32 *)(contents + TZ_TYPECNT_OFFSET));
484 transitions = (guint32 *)(contents + TZ_TRANSITIONS_OFFSET);
485 transitions_size = timecnt * sizeof (*transitions);
486 ttinfo_map = (void *)(contents + TZ_TRANSITIONS_OFFSET + transitions_size);
487 ttinfo_map_size = timecnt;
488 ttinfos = (void *)(ttinfo_map + ttinfo_map_size);
491 * Find the first transition that contains the 'start' time
493 for (i = 1; i < timecnt && start_transition == -1; i++)
495 gint32 transition_time = GINT32_FROM_BE (transitions[i]);
497 /* if is_utc is not set, we need to add this time offset to compare with
498 * start, because it is already on the timezone time */
503 off = *(gint32 *)(ttinfos + ttinfo_map[i] * TZ_TTINFO_SIZE +
504 TZ_TTINFO_GMTOFF_OFFSET);
505 off = GINT32_FROM_BE (off);
507 transition_time += off;
510 if (transition_time > start)
512 start_transition = ttinfo_map[i - 1];
517 if (start_transition == -1)
520 start_transition = ttinfo_map[timecnt - 1];
522 start_transition = 0;
525 /* Copy the data out of the corresponding ttinfo structs */
526 offset = *(gint32 *)(ttinfos + start_transition * TZ_TTINFO_SIZE +
527 TZ_TTINFO_GMTOFF_OFFSET);
528 offset = GINT32_FROM_BE (offset);
529 isdst = *(ttinfos + start_transition * TZ_TTINFO_SIZE +
530 TZ_TTINFO_ISDST_OFFSET);
531 name_offset = *(ttinfos + start_transition * TZ_TTINFO_SIZE +
532 TZ_TTINFO_NAME_OFFSET);
535 *_name = g_strdup ((gchar*) (ttinfos + TZ_TTINFO_SIZE * typecnt + name_offset));
546 static GTimeZoneFile *
547 g_time_zone_file_new (const gchar *filename)
549 GMappedFile *tz_file;
550 GTimeZoneFile *retval;
552 tz_file = g_mapped_file_new (filename, FALSE, NULL);
556 retval = g_slice_new (GTimeZoneFile);
557 retval->filename = g_strdup (filename);
558 retval->file = tz_file;
559 retval->ref_count = 1;
564 static GTimeZoneFile *
565 g_time_zone_file_ref (GTimeZoneFile *tz_file)
570 g_atomic_int_inc (&tz_file->ref_count);
576 g_time_zone_file_unref (GTimeZoneFile *tz_file)
581 if (g_atomic_int_dec_and_test (&tz_file->ref_count))
583 /* remove the TimeZoneFile from the hash table of known files */
584 G_LOCK (time_zone_files);
585 g_hash_table_remove (time_zone_files, tz_file->filename);
586 G_UNLOCK (time_zone_files);
588 g_mapped_file_unref (tz_file->file);
589 g_free (tz_file->filename);
590 g_slice_free (GTimeZoneFile, tz_file);
595 * g_time_zone_file_get_for_path:
596 * @path: the full path for a time zone file
598 * Retrieves a #GTimeZoneFile for the given path.
600 * If a time zone file for the same path has been already requested,
601 * this function will return the same #GTimeZoneFile with its reference
602 * count increased by one; otherwise, a new #GTimeZoneFile will be created
603 * and added to the known time zone files.
605 * The time zone files are removed from the list of known files when their
606 * reference count reaches 0.
608 * This function holds the lock on the time_zone_files hash table.
610 * Return value: a #GTimeZoneFile or %NULL
612 static GTimeZoneFile *
613 g_time_zone_file_get_for_path (const gchar *path)
615 GTimeZoneFile *retval;
617 G_LOCK (time_zone_files);
619 if (G_LIKELY (time_zone_files != NULL))
621 retval = g_hash_table_lookup (time_zone_files, path);
624 retval = g_time_zone_file_ref (retval);
629 retval = g_time_zone_file_new (path);
632 if (G_UNLIKELY (time_zone_files == NULL))
633 time_zone_files = g_hash_table_new (g_str_hash, g_str_equal);
635 g_hash_table_insert (time_zone_files, retval->filename, retval);
639 G_UNLOCK (time_zone_files);
646 * @offset: the timezone offset from UTC, in seconds
647 * @is_dst: whether the timezone is in Daylight Saving Time or not
649 * Creates a new #GTimeZone for the given @offset, to be used when
650 * creating a #GDateTime.
652 * The #GTimeZone created will not be floating.
654 * Return value: (transfer full): the newly allocated #GTimeZone
659 g_time_zone_new (gint offset,
664 g_return_val_if_fail (offset >= -12 * SECS_PER_HOUR && offset <= 12 * SECS_PER_HOUR, NULL);
666 tz = g_slice_new (GTimeZone);
670 tz->is_floating = FALSE;
673 tz->name = g_strdup_printf ("UTC");
675 tz->name = g_strdup_printf ("UTC%c%02d:%02d",
676 tz->offset > 0 ? '+' : '-',
677 (int) tz->offset / 3600,
678 (int) tz->offset / 60 % 60);
684 * g_time_zone_new_for_name:
685 * @name: an ASCII string containing the Olson's database name of the
686 * timezone, e.g. "America/New_York" or "Europe/London"
688 * Creates a new #GTimeZone for the given @name.
690 * The returned timezone is "floating": if queried, it will return invalid
691 * values. A floating #GTimeZone is "sunk" when it is bound to a #GDateTime
697 * /* the time zone is "floating" */
698 * GTimeZone *tz = g_time_zone_new_for_name ("Europe/London");
700 * /* this will print: "UTC offset: 0 seconds" */
701 * g_print ("UTC offset: %d seconds\n", g_time_zone_get_offset (tz));
703 * /* the GDateTime object copies the time zone */
704 * GDateTime *dt = g_date_time_new_full (2010, 9, 15, 12, 0, 0, tz);
706 * /* this will print: "UTC offset: 3600 seconds", because Europe/London
707 * * on that date is in daylight saving time
709 * g_print ("UTC offset: %d seconds\n",
710 * g_date_time_get_utc_offset (dt) / G_USEC_PER_SEC);
713 * Return value: (transfer full): the newly created, floating #GTimeZone
714 * object for the given name, or %NULL if none was found
719 g_time_zone_new_for_name (const gchar *name)
723 GTimeZoneFile *tz_file;
725 g_return_val_if_fail (name != NULL, NULL);
727 filename = get_tzdata_path (name);
728 if (filename == NULL)
731 tz_file = g_time_zone_file_get_for_path (filename);
737 tz = g_slice_new (GTimeZone);
738 tz->tz_file = tz_file;
742 tz->is_utc = (strcmp (name, "UTC") == 0);
743 tz->is_floating = TRUE;
749 * g_time_zone_new_utc:
751 * Creates a new #GTimeZone for UTC.
753 * Return value: (transfer full): a newly created #GTimeZone for UTC.
754 * Use g_time_zone_free() when done.
759 g_time_zone_new_utc (void)
761 return g_time_zone_new (0, FALSE);
765 * g_time_zone_new_local:
767 * Creates a new #GTimeZone for the local timezone.
769 * The returned #GTimeZone is floating.
771 * Return value: (transfer full): a newly created, floating #GTimeZone.
772 * Use g_time_zone_free() when done.
777 g_time_zone_new_local (void)
779 return g_time_zone_new_for_name ("localtime");
784 * @time_zone: a #GTimeZone
786 * Copies a #GTimeZone. If @time_zone is floating, the returned copy
787 * will be floating as well.
789 * Return value: (transfer full): the newly created #GTimeZone
794 g_time_zone_copy (const GTimeZone *time_zone)
798 g_return_val_if_fail (time_zone != NULL, NULL);
800 retval = g_slice_dup (GTimeZone, time_zone);
802 if (time_zone->tz_file != NULL)
803 retval->tz_file = g_time_zone_file_ref (time_zone->tz_file);
805 if (time_zone->name != NULL)
806 retval->name = g_strdup (time_zone->name);
813 * @time_zone: a #GTimeZone
815 * Frees the resources associated with a #GTimeZone
820 g_time_zone_free (GTimeZone *time_zone)
822 g_return_if_fail (time_zone != NULL);
824 if (time_zone->tz_file != NULL)
825 g_time_zone_file_unref (time_zone->tz_file);
827 g_free (time_zone->name);
828 g_slice_free (GTimeZone, time_zone);
832 * g_time_zone_get_name:
833 * @time_zone: a #GTimeZone
835 * Retrieves the name of the @time_zone, or %NULL if the #GTimeZone is
838 * Return value: (transfer none): the name of the #GTimeZone. The returned
839 * string is owned by the #GTimeZone and it should never be modified or
844 G_CONST_RETURN gchar *
845 g_time_zone_get_name (const GTimeZone *time_zone)
847 g_return_val_if_fail (time_zone != NULL, NULL);
849 if (!time_zone->is_floating)
850 return time_zone->name;
856 * g_time_zone_get_offset:
857 * @time_zone: a #GTimeZone
859 * Retrieves the offset of the @time_zone, in seconds from UTC, or 0
860 * if the #GTimeZone is floating.
862 * Return value: the offset from UTC, in seconds
867 g_time_zone_get_offset (const GTimeZone *time_zone)
869 g_return_val_if_fail (time_zone != NULL, 0);
871 if (!time_zone->is_floating)
872 return time_zone->offset;
878 * g_time_zone_get_is_dst:
879 * @time_zone: a #GTimeZone
881 * Checks whether the @time_zone is in Daylight Saving Time.
882 * If the #GTimeZone is floating, %FALSE is always returned.
884 * Return value: %TRUE if the #GTimeZone is in DST, or %FALSE.
889 g_time_zone_get_is_dst (const GTimeZone *time_zone)
891 g_return_val_if_fail (time_zone != NULL, FALSE);
893 if (!time_zone->is_floating)
894 return time_zone->is_dst;
900 * g_time_zone_is_floating:
901 * @time_zone: a #GTimeZone
903 * Checks whether @time_zone is floating
905 * Return value: %TRUE if the #GTimeZone is floating, and %FALSE otherwise
910 g_time_zone_is_floating (const GTimeZone *time_zone)
912 g_return_val_if_fail (time_zone != NULL, FALSE);
914 return time_zone->is_floating;
919 * @time_zone: a #GTimeZone
920 * @datetime: a #GDateTime
922 * Sinks the floating state of @time_zone by associating it with the
925 * If @time_zone is not floating, this function does not do anything
928 g_time_zone_sink (GTimeZone *time_zone,
931 gint64 offset, epoch;
932 gboolean is_dst, is_utc;
935 if (!time_zone->is_floating)
938 epoch = g_date_time_to_epoch (datetime);
939 is_utc = time_zone->is_utc;
943 if (parse_tzdata (time_zone->tz_file, epoch, is_utc, &offset, &is_dst, &abbrev))
945 time_zone->offset = offset;
946 time_zone->is_dst = is_dst;
947 time_zone->name = abbrev;
948 time_zone->is_utc = (offset == 0);
949 time_zone->is_floating = FALSE;
954 g_date_time_new (void)
958 datetime = g_slice_new0 (GDateTime);
959 datetime->ref_count = 1;
966 * @datetime: a #GDateTime
968 * Creates a copy of @datetime.
970 * Return value: the newly created #GDateTime which should be freed with
971 * g_date_time_unref().
974 g_date_time_copy (const GDateTime *datetime)
978 g_return_val_if_fail (datetime != NULL, NULL);
980 copied = g_date_time_new ();
981 copied->days = datetime->days;
982 copied->usec = datetime->usec;
984 if (datetime->tz != NULL)
985 copied->tz = g_time_zone_copy (datetime->tz);
991 g_date_time_free (GDateTime *datetime)
993 if (G_UNLIKELY (datetime == NULL))
996 if (datetime->tz != NULL)
997 g_time_zone_free (datetime->tz);
999 g_slice_free (GDateTime, datetime);
1004 * @datetime: a #GDateTime
1006 * Atomically increments the reference count of @datetime by one.
1008 * Return value: the #GDateTime with the reference count increased
1013 g_date_time_ref (GDateTime *datetime)
1015 g_return_val_if_fail (datetime != NULL, NULL);
1016 g_return_val_if_fail (datetime->ref_count > 0, NULL);
1018 g_atomic_int_inc (&datetime->ref_count);
1024 * g_date_time_unref:
1025 * @datetime: a #GDateTime
1027 * Atomically decrements the reference count of @datetime by one.
1029 * When the reference count reaches zero, the resources allocated by
1030 * @datetime are freed
1035 g_date_time_unref (GDateTime *datetime)
1037 g_return_if_fail (datetime != NULL);
1038 g_return_if_fail (datetime->ref_count > 0);
1040 if (g_atomic_int_dec_and_test (&datetime->ref_count))
1041 g_date_time_free (datetime);
1045 g_date_time_get_week_number (const GDateTime *datetime,
1050 gint a, b, c, d, e, f, g, n, s, month, day, year;
1052 g_date_time_get_dmy (datetime, &day, &month, &year);
1056 a = g_date_time_get_year (datetime) - 1;
1057 b = (a / 4) - (a / 100) + (a / 400);
1058 c = ((a - 1) / 4) - ((a - 1) / 100) + ((a - 1) / 400);
1061 f = day - 1 + (31 * (month - 1));
1066 b = (a / 4) - (a / 100) + (a / 400);
1067 c = ((a - 1) / 4) - ((a - 1) / 100) + ((a - 1) / 400);
1070 f = day + (((153 * (month - 3)) + 2) / 5) + 58 + s;
1074 d = (f + g - e) % 7;
1080 *week_number = 53 - ((g - s) / 5);
1081 else if (n > 364 + s)
1084 *week_number = (n / 7) + 1;
1088 *day_of_week = d + 1;
1091 *day_of_year = f + 1;
1096 * @datetime: a #GDateTime
1097 * @timespan: a #GTimeSpan
1099 * Creates a copy of @datetime and adds the specified timespan to the copy.
1101 * Return value: the newly created #GDateTime which should be freed with
1102 * g_date_time_unref().
1107 g_date_time_add (const GDateTime *datetime,
1112 g_return_val_if_fail (datetime != NULL, NULL);
1114 dt = g_date_time_copy (datetime);
1115 g_date_time_add_usec (dt, timespan);
1121 * g_date_time_add_years:
1122 * @datetime: a #GDateTime
1123 * @years: the number of years
1125 * Creates a copy of @datetime and adds the specified number of years to the
1128 * Return value: the newly created #GDateTime which should be freed with
1129 * g_date_time_unref().
1134 g_date_time_add_years (const GDateTime *datetime,
1139 g_return_val_if_fail (datetime != NULL, NULL);
1141 dt = g_date_time_copy (datetime);
1142 g_date_time_add_ymd (dt, years, 0, 0);
1148 * g_date_time_add_months:
1149 * @datetime: a #GDateTime
1150 * @months: the number of months
1152 * Creates a copy of @datetime and adds the specified number of months to the
1155 * Return value: the newly created #GDateTime which should be freed with
1156 * g_date_time_unref().
1161 g_date_time_add_months (const GDateTime *datetime,
1166 g_return_val_if_fail (datetime != NULL, NULL);
1168 dt = g_date_time_copy (datetime);
1169 g_date_time_add_ymd (dt, 0, months, 0);
1175 * g_date_time_add_weeks:
1176 * @datetime: a #GDateTime
1177 * @weeks: the number of weeks
1179 * Creates a copy of @datetime and adds the specified number of weeks to the
1182 * Return value: the newly created #GDateTime which should be freed with
1183 * g_date_time_unref().
1188 g_date_time_add_weeks (const GDateTime *datetime,
1191 g_return_val_if_fail (datetime != NULL, NULL);
1193 return g_date_time_add_days (datetime, weeks * 7);
1197 * g_date_time_add_days:
1198 * @datetime: a #GDateTime
1199 * @days: the number of days
1201 * Creates a copy of @datetime and adds the specified number of days to the
1204 * Return value: the newly created #GDateTime which should be freed with
1205 * g_date_time_unref().
1210 g_date_time_add_days (const GDateTime *datetime,
1215 g_return_val_if_fail (datetime != NULL, NULL);
1217 dt = g_date_time_copy (datetime);
1218 g_date_time_add_ymd (dt, 0, 0, days);
1224 * g_date_time_add_hours:
1225 * @datetime: a #GDateTime
1226 * @hours: the number of hours to add
1228 * Creates a copy of @datetime and adds the specified number of hours
1230 * Return value: the newly created #GDateTime which should be freed with
1231 * g_date_time_unref().
1236 g_date_time_add_hours (const GDateTime *datetime,
1241 g_return_val_if_fail (datetime != NULL, NULL);
1243 dt = g_date_time_copy (datetime);
1244 g_date_time_add_usec (dt, (gint64) hours * USEC_PER_HOUR);
1250 * g_date_time_add_seconds:
1251 * @datetime: a #GDateTime
1252 * @seconds: the number of seconds to add
1254 * Creates a copy of @datetime and adds the specified number of seconds.
1256 * Return value: the newly created #GDateTime which should be freed with
1257 * g_date_time_unref().
1262 g_date_time_add_seconds (const GDateTime *datetime,
1267 g_return_val_if_fail (datetime != NULL, NULL);
1269 dt = g_date_time_copy (datetime);
1270 g_date_time_add_usec (dt, (gint64) seconds * USEC_PER_SECOND);
1276 * g_date_time_add_milliseconds:
1277 * @datetime: a #GDateTime
1278 * @milliseconds: the number of milliseconds to add
1280 * Creates a copy of @datetime adding the specified number of milliseconds.
1282 * Return value: the newly created #GDateTime which should be freed with
1283 * g_date_time_unref().
1288 g_date_time_add_milliseconds (const GDateTime *datetime,
1293 g_return_val_if_fail (datetime != NULL, NULL);
1295 dt = g_date_time_copy (datetime);
1296 g_date_time_add_usec (dt, (gint64) milliseconds * USEC_PER_MILLISECOND);
1302 * g_date_time_add_minutes:
1303 * @datetime: a #GDateTime
1304 * @minutes: the number of minutes to add
1306 * Creates a copy of @datetime adding the specified number of minutes.
1308 * Return value: the newly created #GDateTime which should be freed with
1309 * g_date_time_unref().
1314 g_date_time_add_minutes (const GDateTime *datetime,
1319 g_return_val_if_fail (datetime != NULL, NULL);
1321 dt = g_date_time_copy (datetime);
1322 g_date_time_add_usec (dt, (gint64) minutes * USEC_PER_MINUTE);
1328 * g_date_time_add_full:
1329 * @datetime: a #GDateTime
1330 * @years: the number of years to add
1331 * @months: the number of months to add
1332 * @days: the number of days to add
1333 * @hours: the number of hours to add
1334 * @minutes: the number of minutes to add
1335 * @seconds: the number of seconds to add
1337 * Creates a new #GDateTime adding the specified values to the current date and
1338 * time in @datetime.
1340 * Return value: the newly created #GDateTime that should be freed with
1341 * g_date_time_unref().
1346 g_date_time_add_full (const GDateTime *datetime,
1357 g_return_val_if_fail (datetime != NULL, NULL);
1359 dt = g_date_time_copy (datetime);
1362 g_date_time_add_ymd (dt, years, months, days);
1365 usecs = (hours * USEC_PER_HOUR)
1366 + (minutes * USEC_PER_MINUTE)
1367 + (seconds * USEC_PER_SECOND);
1368 g_date_time_add_usec (dt, usecs);
1374 * g_date_time_compare:
1375 * @dt1: first #GDateTime to compare
1376 * @dt2: second #GDateTime to compare
1378 * qsort()-style comparison for #GDateTime<!-- -->'s. Both #GDateTime<-- -->'s
1379 * must be non-%NULL.
1381 * Return value: 0 for equal, less than zero if dt1 is less than dt2, greater
1382 * than zero if dt2 is greator than dt1.
1387 g_date_time_compare (gconstpointer dt1,
1390 const GDateTime *a, *b;
1395 if ((a->days == b->days )&&
1396 (a->usec == b->usec))
1400 else if ((a->days > b->days) ||
1401 ((a->days == b->days) && a->usec > b->usec))
1411 * @datetime: a #GDateTime
1413 * Creates a new #GDateTime at Midnight on the date represented by @datetime.
1415 * Return value: the newly created #GDateTime which should be freed with
1416 * g_date_time_unref().
1421 g_date_time_day (const GDateTime *datetime)
1425 g_return_val_if_fail (datetime != NULL, NULL);
1427 date = g_date_time_copy (datetime);
1434 * g_date_time_difference:
1435 * @begin: a #GDateTime
1436 * @end: a #GDateTime
1438 * Calculates the known difference in time between @begin and @end.
1440 * Since the exact precision cannot always be known due to incomplete
1441 * historic information, an attempt is made to calculate the difference.
1443 * Return value: the difference between the two #GDateTime, as a time
1444 * span expressed in microseconds.
1449 g_date_time_difference (const GDateTime *begin,
1450 const GDateTime *end)
1452 g_return_val_if_fail (begin != NULL, 0);
1453 g_return_val_if_fail (end != NULL, 0);
1455 return (GTimeSpan) (((gint64) end->days - (gint64) begin->days)
1456 * USEC_PER_DAY) + ((gint64) end->usec - (gint64) begin->usec);
1460 * g_date_time_equal:
1461 * @dt1: a #GDateTime
1462 * @dt2: a #GDateTime
1464 * Checks to see if @dt1 and @dt2 are equal.
1466 * Equal here means that they represent the same moment after converting
1467 * them to the same timezone.
1469 * Return value: %TRUE if @dt1 and @dt2 are equal
1474 g_date_time_equal (gconstpointer dt1,
1477 const GDateTime *a, *b;
1478 GDateTime *a_utc, *b_utc;
1479 gint64 a_epoch, b_epoch;
1484 a_utc = g_date_time_to_utc (a);
1485 b_utc = g_date_time_to_utc (b);
1487 a_epoch = g_date_time_to_epoch (a_utc);
1488 b_epoch = g_date_time_to_epoch (b_utc);
1490 g_date_time_unref (a_utc);
1491 g_date_time_unref (b_utc);
1493 return a_epoch == b_epoch;
1497 * g_date_time_get_day_of_week:
1498 * @datetime: a #GDateTime
1500 * Retrieves the day of the week represented by @datetime within the gregorian
1501 * calendar. 1 is Sunday, 2 is Monday, etc.
1503 * Return value: the day of the week
1508 g_date_time_get_day_of_week (const GDateTime *datetime)
1516 g_return_val_if_fail (datetime != NULL, 0);
1519 * See Calendar FAQ Section 2.6 for algorithm information
1520 * http://www.tondering.dk/claus/cal/calendar29.txt
1523 g_date_time_get_dmy (datetime, &day, &month, &year);
1524 a = (14 - month) / 12;
1526 m = month + (12 * a) - 2;
1527 dow = ((day + y + (y / 4) - (y / 100) + (y / 400) + (31 * m) / 12) % 7);
1529 /* 1 is Monday and 7 is Sunday */
1530 return (dow == 0) ? 7 : dow;
1534 * g_date_time_get_day_of_month:
1535 * @datetime: a #GDateTime
1537 * Retrieves the day of the month represented by @datetime in the gregorian
1540 * Return value: the day of the month
1545 g_date_time_get_day_of_month (const GDateTime *datetime)
1549 const guint16 *days;
1552 g_return_val_if_fail (datetime != NULL, 0);
1554 days = days_in_year[g_date_time_is_leap_year (datetime) ? 1 : 0];
1555 g_date_time_get_week_number (datetime, NULL, NULL, &day_of_year);
1557 for (i = 1; i <= 12; i++)
1559 if (days [i] >= day_of_year)
1560 return day_of_year - last;
1564 g_warn_if_reached ();
1569 * g_date_time_get_day_of_year:
1570 * @datetime: a #GDateTime
1572 * Retrieves the day of the year represented by @datetime in the Gregorian
1575 * Return value: the day of the year
1580 g_date_time_get_day_of_year (const GDateTime *datetime)
1584 g_return_val_if_fail (datetime != NULL, 0);
1586 g_date_time_get_week_number (datetime, NULL, NULL, &doy);
1591 * g_date_time_get_dmy:
1592 * @datetime: a #GDateTime.
1593 * @day: (out): the return location for the day of the month, or %NULL.
1594 * @month: (out): the return location for the monty of the year, or %NULL.
1595 * @year: (out): the return location for the gregorian year, or %NULL.
1597 * Retrieves the Gregorian day, month, and year of a given #GDateTime.
1602 g_date_time_get_dmy (const GDateTime *datetime,
1610 gint remaining_days;
1617 g_return_if_fail (datetime != NULL);
1619 remaining_days = datetime->days;
1622 * We need to convert an offset in days to its year/month/day representation.
1623 * Leap years makes this a little trickier than it should be, so we use
1624 * 400, 100 and 4 years cycles here to get to the correct year.
1627 /* Our days offset starts sets 0001-01-01 as day 1, if it was day 0 our
1628 * math would be simpler, so let's do it */
1631 the_year = (remaining_days / DAYS_IN_400YEARS) * 400 + 1;
1632 remaining_days = remaining_days % DAYS_IN_400YEARS;
1634 y100_cycles = remaining_days / DAYS_IN_100YEARS;
1635 remaining_days = remaining_days % DAYS_IN_100YEARS;
1636 the_year += y100_cycles * 100;
1638 y4_cycles = remaining_days / DAYS_IN_4YEARS;
1639 remaining_days = remaining_days % DAYS_IN_4YEARS;
1640 the_year += y4_cycles * 4;
1642 y1_cycles = remaining_days / 365;
1643 the_year += y1_cycles;
1644 remaining_days = remaining_days % 365;
1646 if (y1_cycles == 4 || y100_cycles == 4) {
1647 g_assert (remaining_days == 0);
1649 /* special case that indicates that the date is actually one year before,
1650 * in the 31th of December */
1657 /* now get the month and the day */
1658 leap = y1_cycles == 3 && (y4_cycles != 24 || y100_cycles == 3);
1660 g_assert (leap == GREGORIAN_LEAP(the_year));
1662 the_month = (remaining_days + 50) >> 5;
1663 preceding = (days_in_year[0][the_month - 1] + (the_month > 2 && leap));
1664 if (preceding > remaining_days)
1666 /* estimate is too large */
1668 preceding -= leap ? days_in_months[1][the_month]
1669 : days_in_months[0][the_month];
1672 remaining_days -= preceding;
1673 g_assert(0 <= remaining_days);
1675 the_day = remaining_days + 1;
1687 * g_date_time_get_hour:
1688 * @datetime: a #GDateTime
1690 * Retrieves the hour of the day represented by @datetime
1692 * Return value: the hour of the day
1697 g_date_time_get_hour (const GDateTime *datetime)
1699 g_return_val_if_fail (datetime != NULL, 0);
1701 return (datetime->usec / USEC_PER_HOUR);
1705 * g_date_time_get_julian:
1706 * @datetime: a #GDateTime
1707 * @period: (out): a location for the Julian period
1708 * @julian: (out): a location for the day in the Julian period
1709 * @hour: (out): a location for the hour of the day
1710 * @minute: (out): a location for the minute of the hour
1711 * @second: (out): a location for hte second of the minute
1713 * Retrieves the Julian period, day, hour, minute, and second which @datetime
1714 * represents in the Julian calendar.
1719 g_date_time_get_julian (const GDateTime *datetime,
1726 gint y, m, d, a, b, c, e, f, j;
1727 g_return_if_fail (datetime != NULL);
1729 g_date_time_get_dmy (datetime, &d, &m, &y);
1731 /* FIXME: This is probably not optimal and doesn't handle the fact that the
1732 * julian calendar has its 0 hour on midday */
1737 e = 365.25 * (y + 4716);
1738 f = 30.6001 * (m + 1);
1739 j = c + d + e + f - 1524;
1748 *hour = (datetime->usec / USEC_PER_HOUR);
1751 *minute = (datetime->usec % USEC_PER_HOUR) / USEC_PER_MINUTE;
1754 *second = (datetime->usec % USEC_PER_MINUTE) / USEC_PER_SECOND;
1758 * g_date_time_get_microsecond:
1759 * @datetime: a #GDateTime
1761 * Retrieves the microsecond of the date represented by @datetime
1763 * Return value: the microsecond of the second
1768 g_date_time_get_microsecond (const GDateTime *datetime)
1770 g_return_val_if_fail (datetime != NULL, 0);
1772 return (datetime->usec % USEC_PER_SECOND);
1776 * g_date_time_get_millisecond:
1777 * @datetime: a #GDateTime
1779 * Retrieves the millisecond of the date represented by @datetime
1781 * Return value: the millisecond of the second
1786 g_date_time_get_millisecond (const GDateTime *datetime)
1788 g_return_val_if_fail (datetime != NULL, 0);
1790 return (datetime->usec % USEC_PER_SECOND) / USEC_PER_MILLISECOND;
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 (const 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_month:
1813 * @datetime: a #GDateTime
1815 * Retrieves the month of the year represented by @datetime in the Gregorian
1818 * Return value: the month represented by @datetime
1823 g_date_time_get_month (const GDateTime *datetime)
1827 g_return_val_if_fail (datetime != NULL, 0);
1829 g_date_time_get_dmy (datetime, NULL, &month, NULL);
1835 * g_date_time_get_second:
1836 * @datetime: a #GDateTime
1838 * Retrieves the second of the minute represented by @datetime
1840 * Return value: the second represented by @datetime
1845 g_date_time_get_second (const GDateTime *datetime)
1847 g_return_val_if_fail (datetime != NULL, 0);
1849 return (datetime->usec % USEC_PER_MINUTE) / USEC_PER_SECOND;
1853 * g_date_time_get_utc_offset:
1854 * @datetime: a #GDateTime
1856 * Retrieves the offset from UTC that the local timezone specified by
1857 * @datetime represents.
1859 * If @datetime represents UTC time, then the offset is zero.
1861 * Return value: the offset, expressed as a time span expressed in
1867 g_date_time_get_utc_offset (const GDateTime *datetime)
1871 g_return_val_if_fail (datetime != NULL, 0);
1873 if (datetime->tz != NULL)
1874 offset = g_time_zone_get_offset (datetime->tz);
1876 return (gint64) offset * USEC_PER_SECOND;
1880 * g_date_time_get_timezone_name:
1881 * @datetime: a #GDateTime
1883 * Retrieves the name of the timezone specified by @datetime, if any.
1885 * Return value: (transfer none): the name of the timezone. The returned
1886 * string is owned by the #GDateTime and it should not be modified or
1891 G_CONST_RETURN gchar *
1892 g_date_time_get_timezone_name (const GDateTime *datetime)
1894 g_return_val_if_fail (datetime != NULL, NULL);
1896 if (datetime->tz != NULL)
1897 return g_time_zone_get_name (datetime->tz);
1903 * g_date_time_get_year:
1904 * @datetime: A #GDateTime
1906 * Retrieves the year represented by @datetime in the Gregorian calendar.
1908 * Return value: the year represented by @datetime
1913 g_date_time_get_year (const GDateTime *datetime)
1917 g_return_val_if_fail (datetime != NULL, 0);
1919 g_date_time_get_dmy (datetime, NULL, NULL, &year);
1926 * @datetime: a #GDateTime
1928 * Hashes @datetime into a #guint, suitable for use within #GHashTable.
1930 * Return value: a #guint containing the hash
1935 g_date_time_hash (gconstpointer datetime)
1937 return (guint) (*((guint64 *) datetime));
1941 * g_date_time_is_leap_year:
1942 * @datetime: a #GDateTime
1944 * Determines if @datetime represents a date known to fall within
1945 * a leap year in the Gregorian calendar.
1947 * Return value: %TRUE if @datetime is a leap year.
1952 g_date_time_is_leap_year (const GDateTime *datetime)
1956 g_return_val_if_fail (datetime != NULL, FALSE);
1958 year = g_date_time_get_year (datetime);
1960 return GREGORIAN_LEAP (year);
1964 * g_date_time_is_daylight_savings:
1965 * @datetime: a #GDateTime
1967 * Determines if @datetime represents a date known to fall within daylight
1968 * savings time in the gregorian calendar.
1970 * Return value: %TRUE if @datetime falls within daylight savings time.
1975 g_date_time_is_daylight_savings (const GDateTime *datetime)
1977 g_return_val_if_fail (datetime != NULL, FALSE);
1979 if (datetime->tz == NULL)
1982 return datetime->tz->is_dst;
1986 * g_date_time_new_from_date:
1987 * @year: the Gregorian year
1988 * @month: the Gregorian month
1989 * @day: the day in the Gregorian month
1991 * Creates a new #GDateTime using the specified date within the Gregorian
1994 * Return value: the newly created #GDateTime or %NULL if it is outside of
1995 * the representable range.
2000 g_date_time_new_from_date (gint year,
2006 g_return_val_if_fail (year > -4712 && year <= 3268, NULL);
2007 g_return_val_if_fail (month > 0 && month <= 12, NULL);
2008 g_return_val_if_fail (day > 0 && day <= 31, NULL);
2010 dt = g_date_time_new ();
2012 dt->days = date_to_proleptic_gregorian (year, month, day);
2013 dt->tz = g_time_zone_new_local ();
2014 g_time_zone_sink (dt->tz, dt);
2020 * g_date_time_new_from_epoch:
2021 * @t: seconds from the Unix epoch
2023 * Creates a new #GDateTime using the time since Jan 1, 1970 specified by @t.
2025 * The timezone of the returned #GDateTime is the local time.
2027 * Return value: the newly created #GDateTime
2032 g_date_time_new_from_epoch (gint64 t)
2034 GDateTime *datetime;
2040 memset (&tm, 0, sizeof (tm));
2042 /* XXX: GLib should probably have a wrapper for this */
2043 #ifdef HAVE_LOCALTIME_R
2044 localtime_r (&tt, &tm);
2047 struct tm *ptm = localtime (&tt);
2051 /* Happens at least in Microsoft's C library if you pass a
2052 * negative time_t. Use 2000-01-01 as default date.
2054 #ifndef G_DISABLE_CHECKS
2055 g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, "ptm != NULL");
2063 memcpy ((void *) &tm, (void *) ptm, sizeof (struct tm));
2065 #endif /* HAVE_LOCALTIME_R */
2067 tz = g_time_zone_new_local ();
2068 datetime = g_date_time_new_full (tm.tm_year + 1900,
2075 g_time_zone_free (tz);
2081 * g_date_time_new_from_timeval:
2084 * Creates a new #GDateTime using the date and time specified by #GTimeVal.
2086 * The timezone of the returned #GDateTime is UTC.
2088 * Return value: the newly created #GDateTime
2093 g_date_time_new_from_timeval (GTimeVal *tv)
2095 GDateTime *datetime;
2097 g_return_val_if_fail (tv != NULL, NULL);
2099 datetime = g_date_time_new_from_epoch (tv->tv_sec);
2100 datetime->usec += tv->tv_usec;
2101 datetime->tz = g_time_zone_new_local ();
2102 g_time_zone_sink (datetime->tz, datetime);
2108 * g_date_time_new_full:
2109 * @year: the Gregorian year
2110 * @month: the Gregorian month
2111 * @day: the day of the Gregorian month
2112 * @hour: the hour of the day
2113 * @minute: the minute of the hour
2114 * @second: the second of the minute, with eventual fractionary parts
2115 * @time_zone: (allow-none): a #GTimeZone, or %NULL for UTC
2117 * Creates a new #GDateTime using the date and times in the Gregorian
2120 * If @time_zone is not %NULL, the #GDateTime will copy the #GTimeZone
2121 * and sink it, if floating.
2123 * Return value: the newly created #GDateTime
2128 g_date_time_new_full (gint year,
2134 const GTimeZone *time_zone)
2138 g_return_val_if_fail (hour >= 0 && hour < 24, NULL);
2139 g_return_val_if_fail (minute >= 0 && minute < 60, NULL);
2140 g_return_val_if_fail (second >= 0.0 && second <= 60.0, NULL);
2142 dt = g_date_time_new ();
2143 dt->days = date_to_proleptic_gregorian (year, month, day);
2144 dt->usec = (hour * USEC_PER_HOUR)
2145 + (minute * USEC_PER_MINUTE)
2146 + (second * USEC_PER_SECOND);
2148 if (time_zone != NULL)
2150 dt->tz = g_time_zone_copy (time_zone);
2151 g_time_zone_sink (dt->tz, dt);
2160 * g_date_time_new_now:
2162 * Creates a new #GDateTime representing the current date and time.
2164 * Return value: the newly created #GDateTime which should be freed with
2165 * g_date_time_unref().
2170 g_date_time_new_now (void)
2174 g_get_current_time (&tv);
2176 return g_date_time_new_from_timeval (&tv);
2180 * g_date_time_printf:
2181 * @datetime: A #GDateTime
2182 * @format: a valid UTF-8 string, containing the format for the #GDateTime
2184 * Creates a newly allocated string representing the requested @format.
2186 * The following format specifiers are supported:
2188 * %%a The abbreviated weekday name according to the current locale.
2189 * %%A The full weekday name according to the current locale.
2190 * %%b The abbreviated month name according to the current locale.
2191 * %%B The full month name according to the current locale.
2192 * %%d The day of the month as a decimal number (range 01 to 31).
2193 * %%e The day of the month as a decimal number (range 1 to 31).
2194 * %%F Equivalent to %Y-%m-%d (the ISO 8601 date format).
2195 * %%h Equivalent to %b.
2196 * %%H The hour as a decimal number using a 24-hour clock (range 00 to 23).
2197 * %%I The hour as a decimal number using a 12-hour clock (range 01 to 12).
2198 * %%j The day of the year as a decimal number (range 001 to 366).
2199 * %%k The hour (24-hour clock) as a decimal number (range 0 to 23);
2200 * single digits are preceded by a blank.
2201 * %%l The hour (12-hour clock) as a decimal number (range 1 to 12);
2202 * single digits are preceded by a blank.
2203 * %%m The month as a decimal number (range 01 to 12).
2204 * %%M The minute as a decimal number (range 00 to 59).
2205 * %%N The micro-seconds as a decimal number.
2206 * %%p Either "AM" or "PM" according to the given time value, or the
2207 * corresponding strings for the current locale. Noon is treated
2208 * as "PM" and midnight as "AM".
2209 * %%P Like %%p but lowercase: "am" or "pm" or a corresponding string for
2210 * the current locale.
2211 * %%r The time in a.m. or p.m. notation.
2212 * %%R The time in 24-hour notation (%H:%M).
2213 * %%s The number of seconds since the Epoch, that is, since 1970-01-01
2215 * %%S The second as a decimal number (range 00 to 60).
2216 * %%t A tab character.
2217 * %%u The day of the week as a decimal, range 1 to 7, Monday being 1.
2218 * %%W The week number of the current year as a decimal number.
2219 * %%x The preferred date representation for the current locale without
2221 * %%X The preferred date representation for the current locale without
2223 * %%y The year as a decimal number without the century.
2224 * %%Y The year as a decimal number including the century.
2225 * %%z The time-zone as hour offset from UTC
2226 * %%Z The timezone or name or abbreviation
2227 * %%% A literal %% character.
2229 * Return value: a newly allocated string formatted to the requested format or
2230 * %NULL in the case that there was an error. The string should be freed
2236 g_date_time_printf (const GDateTime *datetime,
2237 const gchar *format)
2245 g_return_val_if_fail (datetime != NULL, NULL);
2246 g_return_val_if_fail (format != NULL, NULL);
2247 g_return_val_if_fail (g_utf8_validate (format, -1, NULL), NULL);
2249 outstr = g_string_sized_new (strlen (format) * 2);
2250 utf8len = g_utf8_strlen (format, -1);
2253 for (; *format; format = g_utf8_next_char(format))
2255 c = g_utf8_get_char (format);
2272 g_string_append (outstr, WEEKDAY_ABBR (datetime));
2275 g_string_append (outstr, WEEKDAY_FULL (datetime));
2278 g_string_append (outstr, MONTH_ABBR (datetime));
2281 g_string_append (outstr, MONTH_FULL (datetime));
2284 g_string_append_printf (outstr, "%02d", g_date_time_get_day_of_month (datetime));
2287 g_string_append_printf (outstr, "%2d", g_date_time_get_day_of_month (datetime));
2290 g_string_append_printf (outstr, "%d-%02d-%02d",
2291 g_date_time_get_year (datetime),
2292 g_date_time_get_month (datetime),
2293 g_date_time_get_day_of_month (datetime));
2296 g_string_append (outstr, MONTH_ABBR (datetime));
2299 g_string_append_printf (outstr, "%02d", g_date_time_get_hour (datetime));
2302 if (g_date_time_get_hour (datetime) == 0)
2303 g_string_append (outstr, "12");
2305 g_string_append_printf (outstr, "%02d", g_date_time_get_hour (datetime) % 12);
2308 g_string_append_printf (outstr, "%03d", g_date_time_get_day_of_year (datetime));
2311 g_string_append_printf (outstr, "%2d", g_date_time_get_hour (datetime));
2314 if (g_date_time_get_hour (datetime) == 0)
2315 g_string_append (outstr, "12");
2317 g_string_append_printf (outstr, "%2d", g_date_time_get_hour (datetime) % 12);
2320 g_string_append_printf (outstr, "%02d", g_date_time_get_month (datetime));
2323 g_string_append_printf (outstr, "%02d", g_date_time_get_minute (datetime));
2326 g_string_append_printf (outstr, "%"G_GUINT64_FORMAT, datetime->usec % USEC_PER_SECOND);
2329 g_string_append (outstr, GET_AMPM (datetime, FALSE));
2332 g_string_append (outstr, GET_AMPM (datetime, TRUE));
2336 gint hour = g_date_time_get_hour (datetime) % 12;
2339 g_string_append_printf (outstr, "%02d:%02d:%02d %s",
2341 g_date_time_get_minute (datetime),
2342 g_date_time_get_second (datetime),
2343 GET_AMPM (datetime, FALSE));
2347 g_string_append_printf (outstr, "%02d:%02d",
2348 g_date_time_get_hour (datetime),
2349 g_date_time_get_minute (datetime));
2352 g_string_append_printf (outstr, "%" G_GINT64_FORMAT, g_date_time_to_epoch (datetime));
2355 g_string_append_printf (outstr, "%02d", g_date_time_get_second (datetime));
2358 g_string_append_c (outstr, '\t');
2361 g_string_append_printf (outstr, "%d", g_date_time_get_day_of_week (datetime));
2364 g_string_append_printf (outstr, "%d", g_date_time_get_day_of_year (datetime) / 7);
2368 tmp = GET_PREFERRED_DATE (datetime);
2369 g_string_append (outstr, tmp);
2375 tmp = GET_PREFERRED_TIME (datetime);
2376 g_string_append (outstr, tmp);
2381 g_string_append_printf (outstr, "%02d", g_date_time_get_year (datetime) % 100);
2384 g_string_append_printf (outstr, "%d", g_date_time_get_year (datetime));
2387 if (datetime->tz != NULL)
2389 gint64 offset = g_date_time_get_utc_offset (datetime)
2392 g_string_append_printf (outstr, "%c%02d%02d",
2393 offset >= 0 ? '+' : '-',
2394 (int) offset / 3600,
2395 (int) offset / 60 % 60);
2398 g_string_append (outstr, "+0000");
2401 if (datetime->tz != NULL)
2402 g_string_append (outstr, g_date_time_get_timezone_name (datetime));
2404 g_string_append (outstr, "UTC");
2407 g_string_append_c (outstr, '%');
2410 g_string_append_c (outstr, '\n');
2418 g_string_append_unichar (outstr, c);
2422 return g_string_free (outstr, FALSE);
2425 g_string_free (outstr, TRUE);
2430 * g_date_time_to_local:
2431 * @datetime: a #GDateTime
2433 * Creates a new #GDateTime with @datetime converted to local time.
2435 * Return value: the newly created #GDateTime
2440 g_date_time_to_local (const GDateTime *datetime)
2444 g_return_val_if_fail (datetime != NULL, NULL);
2446 dt = g_date_time_copy (datetime);
2449 dt->tz = g_time_zone_new_local ();
2453 g_time_zone_sink (dt->tz, dt);
2454 g_date_time_add_usec (dt, dt->tz->offset * USEC_PER_SECOND);
2461 * g_date_time_to_epoch:
2462 * @datetime: a #GDateTime
2464 * Converts @datetime into an integer representing seconds since the
2467 * Return value: @datetime as seconds since the Unix epoch
2472 g_date_time_to_epoch (const GDateTime *datetime)
2476 g_return_val_if_fail (datetime != NULL, 0);
2478 if (datetime->days <= 0)
2481 result = (datetime->days - UNIX_EPOCH_START) * SEC_PER_DAY
2482 + datetime->usec / USEC_PER_SECOND
2483 - g_date_time_get_utc_offset (datetime) / USEC_PER_SECOND;
2489 * g_date_time_to_timeval:
2490 * @datetime: a #GDateTime
2493 * Converts @datetime into a #GTimeVal and stores the result into @timeval.
2498 g_date_time_to_timeval (const GDateTime *datetime,
2501 g_return_if_fail (datetime != NULL);
2502 g_return_if_fail (tv != NULL);
2504 tv->tv_sec = g_date_time_to_epoch (datetime);
2505 tv->tv_usec = datetime->usec % USEC_PER_SECOND;
2509 * g_date_time_to_utc:
2510 * @datetime: a #GDateTime
2512 * Creates a new #GDateTime that reprents @datetime in Universal coordinated
2515 * Return value: the newly created #GDateTime which should be freed with
2516 * g_date_time_unref().
2521 g_date_time_to_utc (const GDateTime *datetime)
2526 g_return_val_if_fail (datetime != NULL, NULL);
2528 ts = g_date_time_get_utc_offset (datetime) * -1;
2529 dt = g_date_time_add (datetime, ts);
2532 g_time_zone_free (dt->tz);
2540 * g_date_time_new_today:
2542 * Createsa new #GDateTime that represents Midnight on the current day.
2544 * Return value: the newly created #GDateTime which should be freed with
2545 * g_date_time_unref().
2550 g_date_time_new_today (void)
2554 dt = g_date_time_new_now ();
2561 * g_date_time_new_utc_now:
2563 * Creates a new #GDateTime that represents the current instant in Universal
2564 * Coordinated Time (UTC).
2566 * Return value: the newly created #GDateTime which should be freed with
2567 * g_date_time_unref().
2572 g_date_time_new_utc_now (void)
2574 GDateTime *utc, *now;
2576 now = g_date_time_new_now ();
2577 utc = g_date_time_to_utc (now);
2578 g_date_time_unref (now);
2584 * g_date_time_get_week_of_year:
2586 * Returns the numeric week of the respective year.
2588 * Return value: the week of the year
2593 g_date_time_get_week_of_year (const GDateTime *datetime)
2597 g_return_val_if_fail (datetime != NULL, 0);
2599 g_date_time_get_week_number (datetime, &weeknum, NULL, NULL);