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