00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "config.h"
00026 #include <glib.h>
00027 #include <math.h>
00028 #include <ctype.h>
00029 #include <time.h>
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include "qof.h"
00034 #include "qofdate-p.h"
00035
00036 static QofLogModule log_module = QOF_MOD_TIME;
00037
00038 struct QofTime64
00039 {
00040 QofTimeSecs qt_sec;
00041 glong qt_nsec;
00042 gboolean valid;
00043 };
00044
00045 QofTime *
00046 qof_time_new (void)
00047 {
00048 QofTime *qt;
00049
00050 qt = g_new0 (QofTime, 1);
00051 qt->valid = FALSE;
00052 return qt;
00053 }
00054
00055 void
00056 qof_time_free (QofTime * qt)
00057 {
00058 if (qt == NULL)
00059 return;
00060 g_free (qt);
00061 qt = NULL;
00062 }
00063
00064 void
00065 qof_time_add_secs (QofTime * qt, QofTimeSecs secs)
00066 {
00067 g_return_if_fail (qt);
00068 g_return_if_fail (qt->valid);
00069 qt->qt_sec += secs;
00070 }
00071
00072 QofTime *
00073 qof_time_add_secs_copy (QofTime * qt, QofTimeSecs secs)
00074 {
00075 QofTime *copy;
00076
00077 g_return_val_if_fail (qt, NULL);
00078 g_return_val_if_fail (qt->valid, NULL);
00079 copy = qof_time_copy (qt);
00080 copy->qt_sec += secs;
00081 return copy;
00082 }
00083
00084 static QofTime *
00085 time_normalize (QofTime * qt)
00086 {
00087 g_return_val_if_fail (qt->valid, NULL);
00088 if ((qt->qt_sec < 0) && (qt->qt_nsec > QOF_NSECS))
00089 {
00090 qt->qt_sec -= (qt->qt_nsec / QOF_NSECS);
00091 qt->qt_nsec = qt->qt_nsec % QOF_NSECS;
00092 }
00093 if ((qt->qt_sec >= 0) && (qt->qt_nsec > QOF_NSECS))
00094 {
00095 qt->qt_sec += (qt->qt_nsec / QOF_NSECS);
00096 qt->qt_nsec = qt->qt_nsec % QOF_NSECS;
00097 }
00098 if ((qt->qt_sec < 0) && (qt->qt_nsec < -QOF_NSECS))
00099 {
00100 qt->qt_sec -= -(-qt->qt_nsec / QOF_NSECS);
00101 qt->qt_nsec = -(-qt->qt_nsec % QOF_NSECS);
00102 }
00103 if ((qt->qt_sec >= 0) && (qt->qt_nsec < -QOF_NSECS))
00104 {
00105 qt->qt_sec += -(-qt->qt_nsec / QOF_NSECS);
00106 qt->qt_nsec = -(-qt->qt_nsec % QOF_NSECS);
00107 }
00108 if (qt->qt_sec >= 0 && qt->qt_nsec < 0)
00109 {
00110 qt->qt_sec--;
00111 qt->qt_nsec = QOF_NSECS + qt->qt_nsec;
00112 }
00113 return qt;
00114 }
00115
00116 void
00117 qof_time_set_secs (QofTime * qt, QofTimeSecs secs)
00118 {
00119 qt->qt_sec = secs;
00120 qt->valid = TRUE;
00121 time_normalize (qt);
00122 }
00123
00124 void
00125 qof_time_set_nanosecs (QofTime * qt, glong nano)
00126 {
00127 qt->qt_nsec = nano;
00128 qt->valid = TRUE;
00129 time_normalize (qt);
00130 }
00131
00132 QofTimeSecs
00133 qof_time_get_secs (const QofTime * qt)
00134 {
00135 g_return_val_if_fail (qt, 0);
00136 g_return_val_if_fail (qt->valid == TRUE, 0);
00137 return qt->qt_sec;
00138 }
00139
00140 glong
00141 qof_time_get_nanosecs (const QofTime * qt)
00142 {
00143 g_return_val_if_fail (qt->valid == TRUE, 0);
00144 return qt->qt_nsec;
00145 }
00146
00147 gboolean
00148 qof_time_equal (const QofTime * ta, const QofTime * tb)
00149 {
00150 if (ta == tb)
00151 return TRUE;
00152 if (!ta)
00153 return FALSE;
00154 if (!tb)
00155 return FALSE;
00156 g_return_val_if_fail (ta->valid && tb->valid, FALSE);
00157 if (ta->qt_sec != tb->qt_sec)
00158 return FALSE;
00159 if (ta->qt_nsec != tb->qt_nsec)
00160 return FALSE;
00161 return TRUE;
00162 }
00163
00164 gint
00165 qof_time_cmp (const QofTime * ta, const QofTime * tb)
00166 {
00167 g_return_val_if_fail (ta->valid && tb->valid, -1);
00168 if (ta == tb)
00169 return 0;
00170 if (ta->qt_sec < tb->qt_sec)
00171 return -1;
00172 if (ta->qt_sec > tb->qt_sec)
00173 return 1;
00174 if (ta->qt_nsec < tb->qt_nsec)
00175 return -1;
00176 if (ta->qt_nsec > tb->qt_nsec)
00177 return 1;
00178 return 0;
00179 }
00180
00181 QofTime *
00182 qof_time_diff (const QofTime * ta, const QofTime * tb)
00183 {
00184 QofTime *retval;
00185
00186 g_return_val_if_fail (ta->valid && tb->valid, NULL);
00187 retval = g_new0 (QofTime, 1);
00188 retval->qt_sec = ta->qt_sec - tb->qt_sec;
00189 retval->qt_nsec = ta->qt_nsec - tb->qt_nsec;
00190 retval->valid = TRUE;
00191 time_normalize (retval);
00192 return retval;
00193 }
00194
00195 QofTime *
00196 qof_time_abs (QofTime * qt)
00197 {
00198 g_return_val_if_fail (qt, NULL);
00199 return time_normalize (qt);
00200 }
00201
00202 gboolean
00203 qof_time_is_valid (const QofTime * qt)
00204 {
00205 g_return_val_if_fail (qt, FALSE);
00206 return qt->valid;
00207 }
00208
00209 QofTime *
00210 qof_time_set (QofTimeSecs t, glong nanosecs)
00211 {
00212 QofTime *qt;
00213
00214 qt = qof_time_new ();
00215 qt->qt_sec = t;
00216 qt->qt_nsec = nanosecs;
00217 qt->valid = TRUE;
00218 time_normalize (qt);
00219 return qt;
00220 }
00221
00222 QofTime *
00223 qof_time_copy (const QofTime *qt)
00224 {
00225 g_return_val_if_fail (qt, NULL);
00226 g_return_val_if_fail (qt->valid, NULL);
00227 return qof_time_set (qt->qt_sec, qt->qt_nsec);
00228 }
00229
00230 QofTime *
00231 qof_time_from_time_t (time_t t, glong nanosecs)
00232 {
00233 return qof_time_set (t, nanosecs);
00234 }
00235
00236 gboolean
00237 qof_time_to_time_t (QofTime * qt, time_t * t, glong * nanosecs)
00238 {
00239 if (!qt->valid)
00240 return FALSE;
00241 if (qt->qt_sec < 0)
00242 return FALSE;
00243 if (qt->qt_nsec > 0)
00244 {
00245 *nanosecs = qt->qt_nsec;
00246 }
00247 if ((sizeof (qt->qt_sec) > sizeof (time_t))
00248 && (qt->qt_sec > G_MAXINT32))
00249 {
00250 PERR (" QofTime too large for time_t on this platform.");
00251 return FALSE;
00252 }
00253 *t = qt->qt_sec;
00254 return TRUE;
00255 }
00256
00257 QofTime *
00258 qof_time_from_tm (struct tm * qtm, glong nanosecs)
00259 {
00260 QofDate *qd;
00261 QofTime *qt;
00262
00263
00264 qd = qof_date_from_struct_tm (qtm);
00265 qd->qd_nanosecs = nanosecs;
00266 qt = qof_date_to_qtime (qd);
00267 qof_date_free (qd);
00268 return qt;
00269 }
00270
00271 gboolean
00272 qof_time_to_gtimeval (QofTime * qt, GTimeVal * gtv)
00273 {
00274 if (!qt->valid)
00275 {
00276 PERR (" invalid QofTime passed");
00277 return FALSE;
00278 }
00279 if (qt->qt_sec > G_MAXLONG)
00280 {
00281 PERR (" QofTime out of range for GTimeVal");
00282 return FALSE;
00283 }
00284 gtv->tv_sec = (glong) qt->qt_sec;
00285 gtv->tv_usec = qt->qt_nsec;
00286 return TRUE;
00287 }
00288
00289 void
00290 qof_time_from_gtimeval (QofTime * qt, GTimeVal * gtv)
00291 {
00292 qt->qt_sec = (QofTimeSecs) gtv->tv_sec;
00293 qt->qt_nsec = gtv->tv_usec * 1000;
00294 qt->valid = TRUE;
00295 time_normalize (qt);
00296 }
00297
00298 GDate *
00299 qof_time_to_gdate (QofTime * qt)
00300 {
00301 QofDate *qd;
00302 GDate *d;
00303
00304 qd = qof_date_from_qtime (qt);
00305 d = g_date_new_dmy (qd->qd_mday, qd->qd_mon, qd->qd_year);
00306 if (g_date_valid (d))
00307 return d;
00308 return NULL;
00309 }
00310
00311 QofTime *
00312 qof_time_from_gdate (GDate * date)
00313 {
00314 struct tm gtm;
00315 QofTime *qt;
00316 QofDate *qd;
00317
00318 g_return_val_if_fail (date, NULL);
00319 g_date_to_struct_tm (date, >m);
00320 qd = qof_date_from_struct_tm (>m);
00321 qt = qof_date_to_qtime (qd);
00322 qof_date_free (qd);
00323 return qt;
00324 }
00325
00326 gboolean
00327 qof_time_set_day_end (QofTime * qt)
00328 {
00329 if (!qof_time_set_day_start (qt))
00330 return FALSE;
00331 qt->qt_sec += (SECS_PER_DAY - 1);
00332 return TRUE;
00333 }
00334
00335 gboolean
00336 qof_time_set_day_middle (QofTime * qt)
00337 {
00338 if (!qof_time_set_day_start (qt))
00339 return FALSE;
00340 qt->qt_sec += (SECS_PER_DAY / 2);
00341 return TRUE;
00342 }
00343
00344 GTimeVal *
00345 qof_time_get_current_start (void)
00346 {
00347 GTimeVal *current;
00348 struct tm tm;
00349
00351 current = g_new0 (GTimeVal, 1);
00352 g_get_current_time (current);
00353
00354 tm = *gmtime_r (¤t->tv_sec, &tm);
00355 current->tv_sec -= tm.tm_sec;
00356 current->tv_sec -= tm.tm_min * 60;
00357 current->tv_sec -= tm.tm_hour * 60 * 60;
00358 return current;
00359 }
00360
00361 QofTime *
00362 qof_time_get_current (void)
00363 {
00364 QofTime *now;
00365 GTimeVal gnow;
00366
00367 now = qof_time_new ();
00368 g_get_current_time (&gnow);
00369 qof_time_from_gtimeval (now, &gnow);
00370 return now;
00371 }
00372
00373 gboolean
00374 qof_time_set_day_start (QofTime * qt)
00375 {
00376 QofDate *qd;
00377 QofTimeSecs c;
00378
00379 g_return_val_if_fail (qt, FALSE);
00380 qd = qof_date_from_qtime (qt);
00381 if (qd->qd_year < 1970)
00382 {
00383 c = QOF_DAYS_TO_SEC(qd->qd_yday);
00384 c -= QOF_DAYS_TO_SEC(days_between (1970, qd->qd_year));
00385 c -= qd->qd_gmt_off;
00386 qt->qt_sec = c;
00387 qt->qt_nsec = 0;
00388 }
00389 if (qd->qd_year >= 1970)
00390 {
00391 c = QOF_DAYS_TO_SEC(qd->qd_yday);
00392 c += QOF_DAYS_TO_SEC(days_between (1970, qd->qd_year));
00393 c -= qd->qd_gmt_off;
00394 qt->qt_sec = c;
00395 qt->qt_nsec = 0;
00396 }
00397 qof_date_free (qd);
00398 return TRUE;
00399 }
00400
00401 QofTime *
00402 qof_time_get_today_start (void)
00403 {
00404 QofTime *qt;
00405
00406 qt = qof_time_get_current ();
00407 if (!qof_time_set_day_start (qt))
00408 return NULL;
00409 return qt;
00410 }
00411
00412 QofTime *
00413 qof_time_get_today_end (void)
00414 {
00415 QofTime *qt;
00416
00417 qt = qof_time_get_today_start ();
00418 qt->qt_sec += SECS_PER_DAY - 1;
00419 return qt;
00420 }
00421
00422 guint8
00423 qof_time_last_mday (QofTime * qt)
00424 {
00425 GDate *d;
00426 GDateMonth m;
00427 GDateYear y;
00428
00429 g_return_val_if_fail (qt, 0);
00430 d = qof_time_to_gdate (qt);
00431 if (!d)
00432 return 0;
00433 m = g_date_get_month (d);
00434 y = g_date_get_year (d);
00435 return g_date_get_days_in_month (m, y);
00436 }
00437
00438 gboolean
00439 qof_time_to_dmy (QofTime * qt, guint8 * day, guint8 * month,
00440 guint16 * year)
00441 {
00442 GDate *d;
00443
00444 d = qof_time_to_gdate (qt);
00445 if (!d)
00446 return FALSE;
00447 if (day)
00448 *day = g_date_get_day (d);
00449 if (month)
00450 *month = g_date_get_month (d);
00451 if (year)
00452 *year = g_date_get_year (d);
00453 return TRUE;
00454 }
00455
00456 QofTime *
00457 qof_time_dmy_to_time (guint8 day, guint8 month, guint16 year)
00458 {
00459 GDate *d;
00460 QofTime *qt;
00461
00462 g_return_val_if_fail (g_date_valid_dmy (day, month, year), NULL);
00463 d = g_date_new_dmy (day, month, year);
00464 qt = qof_time_from_gdate (d);
00465 return qt;
00466 }
00467
00468 gchar *
00469 qof_time_stamp_now (void)
00470 {
00471 gint len;
00472 struct tm qtm;
00473 time_t t;
00474 gchar test[MAX_DATE_LENGTH];
00475 const gchar *fmt;
00476
00477 ENTER (" ");
00478 t = time (NULL);
00479 qtm = *gmtime_r (&t, &qtm);
00480 fmt = qof_date_format_get_format (QOF_DATE_FORMAT_UTC);
00481 len = strftime (test, MAX_DATE_LENGTH, fmt, &qtm);
00482 if (len == 0 && test[0] != '\0')
00483 {
00484 LEAVE (" strftime failed.");
00485 return NULL;
00486 }
00487 LEAVE (" ");
00488 return g_strdup (test);
00489 }