28 #include <glib/gprintf.h>
32 #include "qofdate-p.h"
35 #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
36 #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
38 static GHashTable *DateFormatTable = NULL;
39 static gboolean QofDateInit = FALSE;
41 static gchar locale_separator =
'\0';
45 static const guint16 days_in_year[2][14] =
47 { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
48 { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
50 static const guint8 days_in_months[2][13] =
52 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
53 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
57 typedef struct QofDateEntry_s
63 gboolean locale_specific;
71 DateFormatTable = g_hash_table_new (g_direct_hash, g_direct_equal);
74 QofDateEntry *d = g_new0 (QofDateEntry, 1);
75 d->format =
"%m/%d/%Y";
79 d->locale_specific = FALSE;
80 g_hash_table_insert (DateFormatTable, GINT_TO_POINTER (d->df), d);
83 QofDateEntry *d = g_new0 (QofDateEntry, 1);
84 d->format =
"%d/%m/%Y";
88 d->locale_specific = FALSE;
89 g_hash_table_insert (DateFormatTable, GINT_TO_POINTER (d->df), d);
92 QofDateEntry *d = g_new0 (QofDateEntry, 1);
93 d->format =
"%d.%m.%Y";
97 d->locale_specific = FALSE;
98 g_hash_table_insert (DateFormatTable, GINT_TO_POINTER (d->df), d);
101 QofDateEntry *d = g_new0 (QofDateEntry, 1);
106 d->locale_specific = FALSE;
107 g_hash_table_insert (DateFormatTable, GINT_TO_POINTER (d->df), d);
110 QofDateEntry *d = g_new0 (QofDateEntry, 1);
115 d->locale_specific = FALSE;
116 g_hash_table_insert (DateFormatTable, GINT_TO_POINTER (d->df), d);
119 QofDateEntry *d = g_new0 (QofDateEntry, 1);
122 d->separator = locale_separator;
124 d->locale_specific = TRUE;
125 g_hash_table_insert (DateFormatTable, GINT_TO_POINTER (d->df), d);
128 QofDateEntry *d = g_new0 (QofDateEntry, 1);
131 d->separator = locale_separator;
133 d->locale_specific = TRUE;
134 g_hash_table_insert (DateFormatTable, GINT_TO_POINTER (d->df), d);
137 QofDateEntry *d = g_new0(QofDateEntry,1);
138 d->format =
"%Y-%m-%d %H:%M:%S.%N %z";
142 d->locale_specific = FALSE;
143 g_hash_table_insert (DateFormatTable, GINT_TO_POINTER(d->df), d);
149 hash_value_free (gpointer key __attribute__ ((unused)), gpointer value,
150 gpointer data __attribute__ ((unused)))
160 g_hash_table_foreach (DateFormatTable, hash_value_free, NULL);
161 g_hash_table_destroy (DateFormatTable);
171 g_return_val_if_fail (mday != 0, 0);
172 g_return_val_if_fail (month != 0, 0);
173 g_return_val_if_fail (month <= 12, 0);
174 g_return_val_if_fail (month >= 1, 0);
175 g_return_val_if_fail (year != 0, 0);
177 g_return_val_if_fail (mday <=
179 return days_in_year[leap][month] + mday;
185 g_return_val_if_fail (month != 0, 0);
186 g_return_val_if_fail (month <= 12, 0);
187 g_return_val_if_fail (month >= 1, 0);
188 g_return_val_if_fail (year != 0, 0);
195 g_return_val_if_fail (qd, FALSE);
196 g_return_val_if_fail (qd->
qd_valid, FALSE);
210 g_return_val_if_fail (QofDateInit, FALSE);
211 g_return_val_if_fail (str, FALSE);
212 g_return_val_if_fail (strlen (str) != 0, FALSE);
214 ENTER (
" str=%s", str);
217 LEAVE (
" '%s' is too long! Max=%d str_len=%d",
224 check = *gmtime_r (&now, &check);
228 if (len == 0 && test[0] !=
'\0')
230 LEAVE (
" strftime could not understand '%s'", str);
236 LEAVE (
" %s creates a string '%s' that is too long!"
240 *identifier = g_hash_table_size (DateFormatTable) + 1;
242 QofDateEntry *d = g_new0 (QofDateEntry, 1);
245 d->separator = locale_separator;
247 g_hash_table_insert (DateFormatTable, GINT_TO_POINTER (d->df), d);
249 LEAVE (
" successful");
258 g_return_val_if_fail (QofDateInit, NULL);
259 d = g_hash_table_lookup (DateFormatTable, GINT_TO_POINTER (format));
262 PERR (
" unknown format: '%d'", format);
273 g_return_val_if_fail (QofDateInit, FALSE);
276 d = g_hash_table_lookup (DateFormatTable, GINT_TO_POINTER (format));
279 PERR (
" unknown format: '%d'", format);
283 g_hash_table_insert (DateFormatTable, GINT_TO_POINTER (format), d);
298 g_return_val_if_fail (QofDateInit, FALSE);
299 d = g_hash_table_lookup (DateFormatTable, GINT_TO_POINTER (df));
302 PERR (
" unknown format: '%d'", df);
314 g_return_val_if_fail (QofDateInit, NULL);
315 d = g_hash_table_lookup (DateFormatTable, GINT_TO_POINTER (df));
318 PERR (
" unknown format: '%d'", df);
329 g_return_val_if_fail (QofDateInit, locale_separator);
330 d = g_hash_table_lookup (DateFormatTable, GINT_TO_POINTER (df));
333 PERR (
" unknown format: '%d'", df);
334 return locale_separator;
344 g_return_val_if_fail (QofDateInit, FALSE);
347 DEBUG (
" Prevented attempt to override a default format");
350 if (g_ascii_isdigit (sep))
352 d = g_hash_table_lookup (DateFormatTable, GINT_TO_POINTER (df));
355 PERR (
" unknown format: '%d'", df);
359 g_hash_table_insert (DateFormatTable, GINT_TO_POINTER (df), d);
370 lookup_name (gpointer key __attribute__ ((unused)), gpointer value,
376 i = (
struct iter *) data;
377 d = (QofDateEntry *) value;
407 g_hash_table_foreach (DateFormatTable, lookup_name, &i);
412 date_normalise (
QofDate * date)
416 g_return_val_if_fail (date, NULL);
515 set_day_of_the_week (date);
533 error = ERR_NO_ERROR;
536 check = strptime_internal (str, format, date, &error);
537 if (error != ERR_NO_ERROR)
542 date = date_normalise (date);
553 g_return_val_if_fail (QofDateInit, NULL);
554 g_return_val_if_fail (date, NULL);
555 g_return_val_if_fail (date->
qd_valid, NULL);
556 d = g_hash_table_lookup (DateFormatTable,
557 GINT_TO_POINTER (df));
558 g_return_val_if_fail (d, NULL);
562 if (result == 0 && temp[0] !=
'\0')
564 PERR (
" qof extended strftime failed");
567 return g_strndup(temp, result);
610 g_return_if_fail (date);
618 g_return_val_if_fail (date, FALSE);
619 date = date_normalise (date);
622 PERR (
" unknown QofDate error");
683 g_return_val_if_fail (stm, NULL);
689 d->
qd_mon = stm->tm_mon + 1;
690 d->
qd_year = stm->tm_year + 1900;
697 d = date_normalise(d);
705 g_return_val_if_fail (qd, FALSE);
706 g_return_val_if_fail (stm, FALSE);
707 g_return_val_if_fail (qd->
qd_valid, FALSE);
710 PERR (
" date too large for struct tm");
717 stm->tm_mon = qd->
qd_mon - 1;
718 stm->tm_year = qd->
qd_year - 1900;
724 if (nanosecs != NULL)
732 g_return_val_if_fail (qd, FALSE);
733 g_return_val_if_fail (gd, FALSE);
734 g_return_val_if_fail (qd->
qd_valid, FALSE);
735 if (qd->
qd_year >= G_MAXUINT16)
737 PERR (
" QofDate out of range of GDate");
742 PERR (
" GDate failed to allow day, month and/or year");
754 g_return_val_if_fail (g_date_valid (date), NULL);
756 qd->
qd_year = g_date_get_year (date);
757 qd->
qd_mon = g_date_get_month (date);
758 qd->
qd_mday = g_date_get_day (date);
759 qd = date_normalise (qd);
771 g_return_if_fail (qd);
772 g_return_if_fail (time);
796 while (days < 0 || days >= (__isleap (y) ? 366 : 365))
799 yg = y + days / 365 - (days % 365 < 0);
801 days -= ((yg - y) * 365
802 + LEAPS_THRU_END_OF (yg - 1)
803 - LEAPS_THRU_END_OF (y - 1));
809 for (y = 12; days < (glong) ip[y]; --y)
819 count_leapseconds (time_t interval)
825 utc = *gmtime_r (&interval, &utc);
826 altered = mktime (&utc);
827 return altered - interval;
832 extract_interval (
const QofTime *qt)
843 leap_seconds = ((t > l) || (t < 0)) ?
844 count_leapseconds (l) :
845 count_leapseconds (t);
853 gint leap_extra_secs;
857 g_return_val_if_fail (qt, NULL);
858 g_return_val_if_fail (qof_time_is_valid (qt), NULL);
861 setenv (
"TZ",
"GMT", 1);
863 leap_extra_secs = extract_interval (qt);
864 qof_date_offset (qt, leap_extra_secs, qd);
875 days_between (gint64 year1, gint64 year2)
877 gint64 i, start, end, l;
882 start = (year1 < year2) ? year1 : year2;
883 end = (year2 < year1) ? year1: year2;
884 for (i = start; i < end; i++)
897 g_return_val_if_fail (qd, NULL);
898 g_return_val_if_fail (qd->
qd_valid, NULL);
968 g_return_val_if_fail (qd, FALSE);
976 gboolean track_last_day)
978 g_return_val_if_fail (qd, FALSE);
980 qd->
qd_mon += months % 12;
992 qof_date_set_day_end (
QofDate * qd)
1002 qof_date_set_day_start (
QofDate * qd)
1004 g_return_val_if_fail (qd, FALSE);
1013 qof_date_set_day_middle (
QofDate * qd)
1015 g_return_val_if_fail (qd, FALSE);