Date: Date and Time Printing, Parsing and Manipulation
[Query Object Framework]


Detailed Description

Utility functions to handle date and time (adjusting, getting the current date, printing the date and time, etc.)

Overall, this file is quite a mess. Note, however, that other applications, besides just GnuCash, use this file. In particular, GnoTime (gttr.sourcefore.net) uses this file, and this file is formally a part of QOF (qof.sourceforge.net).

An important note about time-keeping: The general goal of any program that works with numeric time values SHOULD BE to always stores and use UNIVERSAL TIME internally. Universal time is the 'one true time' that is independent of one's location on planet Earth. It is measured in seconds from midnight January 1, 1970 in localtime-Grenwich (GMT). If one wants to display the local time, then the display-print routine should make all final tweaks to print the local time. The local time *must not* be kept as a numeric value anywhere in the program. If one wants to parse a user's input string as if it were local time, then the output of the parse routine MUST BE universal time. A sane program must never ever store (to file or db) a time that is not Universal Time. Break these rules, and you will rue the day...

Warning:
HACK ALERT -- the scan and print routines should probably be moved to somewhere else. The engine really isn't involved with things like printing formats. This is needed mostly by the GUI and so on. If a file-io backend needs date handling, it should do it itself, instead of depending on the routines here.
Author:
Copyright (C) 1997 Robin D. Clark <rclark@cs.hmc.edu>

Copyright (C) 1998-2001,2003 Linas Vepstas <linas@linas.org>


Data Structures

struct  timespec64
 Use a 64-bit signed int timespec. More...

String / DateFormat conversion.

const char * gnc_date_dateformat_to_string (QofDateFormat format)
 The string->value versions return FALSE on success and TRUE on failure.
gboolean gnc_date_string_to_dateformat (const char *format_string, QofDateFormat *format)
 Converts the date format to a printable string.
const char * gnc_date_monthformat_to_string (GNCDateMonthFormat format)
gboolean gnc_date_string_to_monthformat (const char *format_string, GNCDateMonthFormat *format)
 Converts the month format to a printable string.

Timespec functions

gboolean timespec_equal (const Timespec *ta, const Timespec *tb)
int timespec_cmp (const Timespec *ta, const Timespec *tb)
Timespec timespec_diff (const Timespec *ta, const Timespec *tb)
Timespec timespec_abs (const Timespec *t)
Timespec timespecCanonicalDayTime (Timespec t)
 Converts any time on a day to midday that day.
void timespecFromTime_t (Timespec *ts, time_t t)
time_t timespecToTime_t (Timespec ts)
Timespec gnc_dmy2timespec (int day, int month, int year)
Timespec gnc_dmy2timespec_end (int day, int month, int year)
Timespec gnc_iso8601_to_timespec_gmt (const char *)
char * gnc_timespec_to_iso8601_buff (Timespec ts, char *buff)
void gnc_timespec2dmy (Timespec ts, int *day, int *month, int *year)
void date_add_months (struct tm *tm, int months, gboolean track_last_day)
time_t xaccDMYToSec (int day, int month, int year)
long int gnc_timezone (struct tm *tm)

QofDateFormat functions

QofDateFormat qof_date_format_get (void)
void qof_date_format_set (QofDateFormat df)
const gchar * qof_date_format_get_string (QofDateFormat df)
const gchar * qof_date_format_get_format (QofDateFormat df)

Date Printing/Scanning functions

size_t qof_print_date_dmy_buff (char *buff, size_t buflen, int day, int month, int year)
size_t qof_print_date_buff (char *buff, size_t buflen, time_t secs)
size_t qof_print_gdate (char *buf, size_t bufflen, GDate *gd)
char * qof_print_date (time_t secs)
const char * gnc_print_date (Timespec ts)
size_t qof_print_hours_elapsed_buff (char *buff, size_t len, int secs, gboolean show_secs)
size_t qof_print_minutes_elapsed_buff (char *buff, size_t len, int secs, gboolean show_secs)
size_t qof_print_time_buff (char *buff, size_t len, time_t secs)
size_t qof_print_date_time_buff (char *buff, size_t len, time_t secs)
gboolean qof_is_same_day (time_t, time_t)
char * xaccDateUtilGetStamp (time_t thyme)
gboolean qof_scan_date (const char *buff, int *day, int *month, int *year)
gboolean qof_scan_date_secs (const char *buff, time_t *secs)

Date Start/End Adjustment routines

Given a time value, adjust it to be the beginning or end of that day.

void gnc_tm_get_day_start (struct tm *tm, time_t time_val)
void gnc_tm_get_day_end (struct tm *tm, time_t time_val)
time_t gnc_timet_get_day_start (time_t time_val)
time_t gnc_timet_get_day_end (time_t time_val)
time_t gnc_timet_get_day_start_gdate (GDate *date)
time_t gnc_timet_get_day_end_gdate (GDate *date)
int date_get_last_mday (struct tm *tm)
gboolean date_is_last_mday (struct tm *tm)
int gnc_date_my_last_mday (int month, int year)
int gnc_timespec_last_mday (Timespec ts)

Today's Date

void gnc_tm_get_today_start (struct tm *tm)
void gnc_tm_get_today_end (struct tm *tm)
time_t gnc_timet_get_today_start (void)
time_t gnc_timet_get_today_end (void)
char * xaccDateUtilGetStampNow (void)

Defines

#define MAX_DATE_LENGTH   31
#define QOF_UTC_DATE_FORMAT   "%Y-%m-%dT%H:%M:%SZ"
 UTC date format string.
#define DATE_FORMAT_FIRST   QOF_DATE_FORMAT_US
#define DATE_FORMAT_LAST   QOF_DATE_FORMAT_LOCALE

Typedefs

typedef timespec64 Timespec

Enumerations

enum  QofDateFormat {
  QOF_DATE_FORMAT_US, QOF_DATE_FORMAT_UK, QOF_DATE_FORMAT_CE, QOF_DATE_FORMAT_ISO,
  QOF_DATE_FORMAT_UTC, QOF_DATE_FORMAT_LOCALE, QOF_DATE_FORMAT_CUSTOM
}
enum  GNCDateMonthFormat { GNCDATE_MONTH_NUMBER, GNCDATE_MONTH_ABBREV, GNCDATE_MONTH_NAME }

Functions

char dateSeparator (void)


Define Documentation

#define MAX_DATE_LENGTH   31
 

The maximum length of a string created by the date printers

Definition at line 65 of file gnc-date.h.

#define QOF_UTC_DATE_FORMAT   "%Y-%m-%dT%H:%M:%SZ"
 

UTC date format string.

Timezone independent, date and time inclusive, as used in the QSF backend. The T and Z characters are from xsd:dateTime format in coordinated universal time, UTC. You can reproduce the string from the GNU/Linux command line using the date utility: date -u +Y-m-dTH:M:SZ = 2004-12-12T23:39:11Z The datestring must be timezone independent and include all specified fields. Remember to use gmtime() NOT localtime()!

Definition at line 77 of file gnc-date.h.


Typedef Documentation

typedef struct timespec64 Timespec
 

The Timespec is just like the unix 'struct timespec' except that we use a 64-bit signed int to store the seconds. This should adequately cover dates in the distant future as well as the distant past, as long as they're not more than a couple dozen times the age of the universe. Note that both gcc and the IBM Toronto xlC compiler (aka CSet, VisualAge, etc) correctly handle long long as a 64 bit quantity, even on the 32-bit Intel x86 and PowerPC architectures. I'm assuming that all the other modern compilers are clean on this issue too.

Definition at line 163 of file gnc-date.h.


Enumeration Type Documentation

enum GNCDateMonthFormat
 

This is how to format the month, as a number, an abbreviated string, or the full name.

Definition at line 99 of file gnc-date.h.

00099              {
00100   GNCDATE_MONTH_NUMBER,
00101   GNCDATE_MONTH_ABBREV,
00102   GNCDATE_MONTH_NAME
00103 } GNCDateMonthFormat;

enum QofDateFormat
 

Enum for determining a date format

Enumerator:
QOF_DATE_FORMAT_US  United states: mm/dd/yyyy
QOF_DATE_FORMAT_UK  Britain: dd/mm/yyyy
QOF_DATE_FORMAT_CE  Continental Europe: dd.mm.yyyy
QOF_DATE_FORMAT_ISO  ISO: yyyy-mm-dd
QOF_DATE_FORMAT_UTC  UTC: 2004-12-12T23:39:11Z
QOF_DATE_FORMAT_LOCALE  Take from locale information
QOF_DATE_FORMAT_CUSTOM  Used by the check printing code

Definition at line 80 of file gnc-date.h.


Function Documentation

void date_add_months struct tm *  tm,
int  months,
gboolean  track_last_day
 

Add a number of months to a time value and normalize. Optionally also track the last day of the month, i.e. 1/31 -> 2/28 -> 3/30.

Definition at line 313 of file gnc-date.c.

00314 {
00315   gboolean was_last_day;
00316   int new_last_mday;
00317 
00318   /* Have to do this now */
00319   was_last_day = date_is_last_mday(tm);
00320 
00321   /* Add in the months and normalize */
00322   tm->tm_mon += months;
00323   while (tm->tm_mon > 11) {
00324     tm->tm_mon -= 12;
00325     tm->tm_year++;
00326   }
00327 
00328   if (!track_last_day)
00329     return;
00330 
00331   /* Track last day of the month, i.e. 1/31 -> 2/28 -> 3/30 */
00332   new_last_mday = date_get_last_mday(tm);
00333   if (was_last_day || (tm->tm_mday > new_last_mday))
00334     tm->tm_mday = new_last_mday;
00335 }

int date_get_last_mday struct tm *  tm  ) 
 

Get the numerical last date of the month. (28, 29, 30, 31)

Definition at line 285 of file gnc-date.c.

00286 {
00287   return gnc_date_my_last_mday (tm->tm_mon+1, tm->tm_year+1900);
00288 }

gboolean date_is_last_mday struct tm *  tm  ) 
 

Is the mday field the last day of the specified month.

Definition at line 297 of file gnc-date.c.

00298 {
00299   return(tm->tm_mday == date_get_last_mday(tm));
00300 }

char dateSeparator void   ) 
 

dateSeparator Return the field separator for the current date format

Args: none

Return: date character

Globals: global dateFormat value

Definition at line 922 of file gnc-date.c.

00923 {
00924   static char locale_separator = '\0';
00925 
00926   switch (dateFormat)
00927   {
00928     case QOF_DATE_FORMAT_CE:
00929       return '.';
00930     case QOF_DATE_FORMAT_ISO:
00931     case QOF_DATE_FORMAT_UTC:
00932       return '-';
00933     case QOF_DATE_FORMAT_US:
00934     case QOF_DATE_FORMAT_UK:
00935     default:
00936       return '/';
00937     case QOF_DATE_FORMAT_LOCALE:
00938       if (locale_separator != '\0')
00939         return locale_separator;
00940       else
00941       { /* Make a guess */
00942         char string[256];
00943         struct tm *tm;
00944         time_t secs;
00945         char *s;
00946 
00947         secs = time(NULL);
00948         tm = localtime(&secs);
00949         strftime(string, sizeof(string), GNC_D_FMT, tm);
00950 
00951         for (s = string; s != '\0'; s++)
00952           if (!isdigit(*s))
00953             return (locale_separator = *s);
00954       }
00955   }
00956 
00957   return '\0';
00958 }

int gnc_date_my_last_mday int  month,
int  year
 

DOCUMENT ME! Probably the same as date_get_last_mday()

Definition at line 259 of file gnc-date.c.

00260 {
00261   gboolean is_leap;
00262   static int days_in_month[2][12] =
00263     {/* non leap */ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
00264      /*   leap   */ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
00265 
00266   /* Is this a leap year? */
00267   if (year % 2000 == 0)
00268     is_leap = TRUE;
00269   else if (year % 400 == 0)
00270       is_leap = FALSE;
00271   else
00272     is_leap = (year % 4 == 0);
00273 
00274   return days_in_month[is_leap][month-1];
00275 }

gboolean gnc_date_string_to_dateformat const char *  format_string,
QofDateFormat format
 

Converts the date format to a printable string.

Note the reversed return values!

Returns:
FALSE on success, TRUE on failure.

Definition at line 102 of file gnc-date.c.

00103 {
00104   if (!fmt_str)
00105     return TRUE;
00106 
00107   if (!strcmp(fmt_str, "us"))
00108     *format = QOF_DATE_FORMAT_US;
00109   else if (!strcmp(fmt_str, "uk"))
00110     *format = QOF_DATE_FORMAT_UK;
00111   else if (!strcmp(fmt_str, "ce"))
00112     *format = QOF_DATE_FORMAT_CE;
00113   else if (!strcmp(fmt_str, "utc"))
00114     *format = QOF_DATE_FORMAT_UTC;
00115   else if (!strcmp(fmt_str, "iso"))
00116     *format = QOF_DATE_FORMAT_ISO;
00117   else if (!strcmp(fmt_str, "locale"))
00118     *format = QOF_DATE_FORMAT_LOCALE;
00119   else if (!strcmp(fmt_str, "custom"))
00120     *format = QOF_DATE_FORMAT_CUSTOM;
00121   else
00122     return TRUE;
00123 
00124   return FALSE;
00125 }

gboolean gnc_date_string_to_monthformat const char *  format_string,
GNCDateMonthFormat format
 

Converts the month format to a printable string.

Note the reversed return values!

Returns:
FALSE on success, TRUE on failure.

Definition at line 144 of file gnc-date.c.

00145 {
00146   if (!fmt_str)
00147     return TRUE;
00148 
00149   if (!strcmp(fmt_str, "number"))
00150     *format = GNCDATE_MONTH_NUMBER;
00151   else if (!strcmp(fmt_str, "abbrev"))
00152     *format = GNCDATE_MONTH_ABBREV;
00153   else if (!strcmp(fmt_str, "name"))
00154     *format = GNCDATE_MONTH_NAME;
00155   else
00156     return TRUE;
00157 
00158   return FALSE;
00159 }

Timespec gnc_dmy2timespec int  day,
int  month,
int  year
 

Convert a day, month, and year to a Timespec

Definition at line 1245 of file gnc-date.c.

01246 {
01247   return gnc_dmy2timespec_internal (day, month, year, TRUE);
01248 }

Timespec gnc_dmy2timespec_end int  day,
int  month,
int  year
 

Same as gnc_dmy2timespec, but last second of the day

Definition at line 1251 of file gnc-date.c.

01252 {
01253   return gnc_dmy2timespec_internal (day, month, year, FALSE);
01254 }

Timespec gnc_iso8601_to_timespec_gmt const char *   ) 
 

The gnc_iso8601_to_timespec_gmt() routine converts an ISO-8601 style date/time string to Timespec. Please note that ISO-8601 strings are a representation of Universal Time (UTC), and as such, they 'store' UTC. To make them human readable, they show timezone information along with a local-time string. But fundamentally, they *are* UTC. Thus, thir routine takes a UTC input, and returns a UTC output.

For example: 1998-07-17 11:00:00.68-0500 is 680 milliseconds after 11 o'clock, central daylight time It is also 680 millisecs after 16:00:00 hours UTC.

Returns:
The universl time.
XXX Caution: this routine does not handle strings that specify times before January 1 1970.

Definition at line 1014 of file gnc-date.c.

01015 {
01016   char buf[4];
01017   Timespec ts;
01018   struct tm stm;
01019   long int nsec =0;
01020 
01021   ts.tv_sec=0;
01022   ts.tv_nsec=0;
01023   if (!str) return ts;
01024 
01025   stm.tm_year = atoi(str) - 1900;
01026   str = strchr (str, '-'); if (str) { str++; } else { return ts; }
01027   stm.tm_mon = atoi(str) - 1;
01028   str = strchr (str, '-'); if (str) { str++; } else { return ts; }
01029   stm.tm_mday = atoi(str);
01030 
01031   str = strchr (str, ' '); if (str) { str++; } else { return ts; }
01032   stm.tm_hour = atoi(str);
01033   str = strchr (str, ':'); if (str) { str++; } else { return ts; }
01034   stm.tm_min = atoi(str);
01035   str = strchr (str, ':'); if (str) { str++; } else { return ts; }
01036   stm.tm_sec = atoi (str);
01037 
01038   /* The decimal point, optionally present ... */
01039   /* hack alert -- this algo breaks if more than 9 decimal places present */
01040   if (strchr (str, '.')) 
01041   { 
01042      int decimals, i, multiplier=1000000000;
01043      str = strchr (str, '.') +1;
01044      decimals = strcspn (str, "+- ");
01045      for (i=0; i<decimals; i++) multiplier /= 10;
01046      nsec = atoi(str) * multiplier;
01047   }
01048   stm.tm_isdst = -1;
01049 
01050   /* Timezone format can be +hh or +hhmm or +hh.mm (or -) (or not present) */
01051   str += strcspn (str, "+-");
01052   if (str)
01053   {
01054     buf[0] = str[0];
01055     buf[1] = str[1];
01056     buf[2] = str[2];
01057     buf[3] = 0;
01058     stm.tm_hour -= atoi(buf);
01059 
01060     str +=3;
01061     if ('.' == *str) str++;
01062     if (isdigit (*str) && isdigit (*(str+1)))
01063     {
01064       int cyn;
01065       /* copy sign from hour part */
01066       if ('+' == buf[0]) { cyn = -1; } else { cyn = +1; } 
01067       buf[0] = str[0];
01068       buf[1] = str[1];
01069       buf[2] = str[2];
01070       buf[3] = 0;
01071       stm.tm_min += cyn * atoi(buf);
01072     }
01073   }
01074 
01075   /* Note that mktime returns 'local seconds' which is the true time
01076    * minus the timezone offset.  We don't want to work with local 
01077    * seconds, since they swim around acording to daylight savings, etc. 
01078    * We want to work with universal time.  Thus, add an offset
01079    * to undo the damage that mktime causes.
01080    */
01081   {
01082     struct tm tmp_tm;
01083     struct tm *tm;
01084     long int tz;
01085     int tz_hour;
01086     time_t secs;
01087 
01088     /* Use a temporary tm struct so the mktime call below
01089      * doesn't mess up stm. */
01090     tmp_tm = stm;
01091     tmp_tm.tm_isdst = -1;
01092 
01093     secs = mktime (&tmp_tm);
01094 
01095     /* The call to localtime is 'bogus', but it forces 'timezone' to
01096      * be set. Note that we must use the accurate date, since the
01097      * value of 'gnc_timezone' includes daylight savings corrections
01098      * for that date. */
01099     tm = localtime (&secs);
01100 
01101     tz = gnc_timezone (tm);
01102 
01103     tz_hour = tz / 3600;
01104     stm.tm_hour -= tz_hour;
01105     stm.tm_min -= (tz - (3600 * tz_hour)) / 60;
01106     stm.tm_isdst = tmp_tm.tm_isdst;
01107   }
01108 
01109   ts.tv_sec = mktime (&stm);
01110   ts.tv_nsec = nsec;
01111 
01112   return ts;
01113 }

const char* gnc_print_date Timespec  ts  ) 
 

Convenience; calls through to qof_print_date_dmy_buff(). Return: static global string.

Warning:
This routine is not thread-safe, because it uses a single global buffer to store the return value. Use qof_print_date_buff() or qof_print_date() instead.

Definition at line 530 of file gnc-date.c.

00531 {
00532   static char buff[MAX_DATE_LENGTH];
00533   time_t t;
00534 
00535   t = ts.tv_sec + (ts.tv_nsec / 1000000000.0);
00536 
00537   qof_print_date_buff (buff, MAX_DATE_LENGTH, t);
00538 
00539   return buff;
00540 }

void gnc_timespec2dmy Timespec  ts,
int *  day,
int *  month,
int *  year
 

DOCUMENT ME! FIXME: Probably similar to xaccDMYToSec() this date routine might return incorrect values for dates before 1970.

Definition at line 1168 of file gnc-date.c.

01169 {
01170   struct tm *result;
01171   time_t t_secs = t.tv_sec + (t.tv_nsec / NANOS_PER_SECOND);
01172   result = localtime(&t_secs);
01173 
01174   if (day) *day = result->tm_mday;
01175   if (month) *month = result->tm_mon+1;
01176   if (year) *year = result->tm_year+1900;
01177 }

int gnc_timespec_last_mday Timespec  ts  ) 
 

DOCUMENT ME! Probably the same as date_get_last_mday()

Definition at line 1159 of file gnc-date.c.

01160 {
01161   struct tm *result;
01162   time_t t_secs = t.tv_sec + (t.tv_nsec / NANOS_PER_SECOND);
01163   result = localtime(&t_secs);
01164   return date_get_last_mday (result);
01165 }

char* gnc_timespec_to_iso8601_buff Timespec  ts,
char *  buff
 

The gnc_timespec_to_iso8601_buff() routine takes the input UTC Timespec value and prints it as an ISO-8601 style string. The buffer must be long enough to contain the NULL-terminated string (32 characters + NUL). This routine returns a pointer to the null terminator (and can thus be used in the 'stpcpy' metaphor of string concatenation).

Please note that ISO-8601 strings are a representation of Universal Time (UTC), and as such, they 'store' UTC. To make them human readable, they show timezone information along with a local-time string. But fundamentally, they *are* UTC. Thus, this routine takes a UTC input, and returns a UTC output.

The string generated by this routine uses the local timezone on the machine on which it is executing to create the timestring.

Definition at line 1119 of file gnc-date.c.

01120 {
01121   int len;
01122   int tz_hour, tz_min;
01123   char cyn;
01124   time_t tmp;
01125   struct tm parsed;
01126 
01127   tmp = ts.tv_sec;
01128   localtime_r(&tmp, &parsed);
01129 
01130   tz_hour = gnc_timezone (&parsed) / 3600;
01131   tz_min = (gnc_timezone (&parsed) - 3600*tz_hour) / 60;
01132   if (0>tz_min) { tz_min +=60; tz_hour --; }
01133   if (60<=tz_min) { tz_min -=60; tz_hour ++; }
01134 
01135   /* We also have to print the sign by hand, to work around a bug
01136    * in the glibc 2.1.3 printf (where %+02d fails to zero-pad).
01137    */
01138   cyn = '-';
01139   if (0>tz_hour) { cyn = '+'; tz_hour = -tz_hour; }
01140 
01141   len = sprintf (buff, "%4d-%02d-%02d %02d:%02d:%02d.%06ld %c%02d%02d",
01142                  parsed.tm_year + 1900,
01143                  parsed.tm_mon + 1,
01144                  parsed.tm_mday,
01145                  parsed.tm_hour,
01146                  parsed.tm_min,
01147                  parsed.tm_sec,
01148                  ts.tv_nsec / 1000,
01149                  cyn,
01150                  tz_hour,
01151                  tz_min);
01152 
01153   /* Return pointer to end of string. */
01154   buff += len;
01155   return buff;
01156 }

time_t gnc_timet_get_day_end time_t  time_val  ) 
 

The gnc_timet_get_day_end() routine will take the given time in seconds and adjust it to the last second of that day.

Definition at line 1316 of file gnc-date.c.

01317 {
01318   struct tm tm;
01319 
01320   gnc_tm_get_day_end(&tm, time_val);
01321   return mktime(&tm);
01322 }

time_t gnc_timet_get_day_end_gdate GDate *  date  ) 
 

The gnc_timet_get_day_end() routine will take the given time in GLib GDate format and adjust it to the last second of that day.

Definition at line 1341 of file gnc-date.c.

01342 {
01343   struct tm stm;
01344   time_t secs;
01345 
01346   stm.tm_year = g_date_year (date) - 1900;
01347   stm.tm_mon = g_date_month (date) - 1;
01348   stm.tm_mday = g_date_day (date);
01349   gnc_tm_set_day_end(&stm);
01350 
01351   /* Compute number of seconds */
01352   secs = mktime (&stm);
01353   return secs;
01354 }

time_t gnc_timet_get_day_start time_t  time_val  ) 
 

The gnc_timet_get_day_start() routine will take the given time in seconds and adjust it to the last second of that day.

Definition at line 1307 of file gnc-date.c.

01308 {
01309   struct tm tm;
01310 
01311   gnc_tm_get_day_start(&tm, time_val);
01312   return mktime(&tm);
01313 }

time_t gnc_timet_get_day_start_gdate GDate *  date  ) 
 

The gnc_timet_get_day_start() routine will take the given time in GLib GDate format and adjust it to the last second of that day.

Definition at line 1325 of file gnc-date.c.

01326 {
01327   struct tm stm;
01328   time_t secs;
01329 
01330   stm.tm_year = g_date_year (date) - 1900;
01331   stm.tm_mon = g_date_month (date) - 1;
01332   stm.tm_mday = g_date_day (date);
01333   gnc_tm_set_day_start(&stm);
01334 
01335   /* Compute number of seconds */
01336   secs = mktime (&stm);
01337   return secs;
01338 }

time_t gnc_timet_get_today_end void   ) 
 

The gnc_timet_get_today_end() routine returns a time_t value corresponding to the last second of today.

Definition at line 1380 of file gnc-date.c.

01381 {
01382   struct tm tm;
01383 
01384   gnc_tm_get_day_end(&tm, time(NULL));
01385   return mktime(&tm);
01386 }

time_t gnc_timet_get_today_start void   ) 
 

The gnc_timet_get_today_start() routine returns a time_t value corresponding to the first second of today.

Definition at line 1371 of file gnc-date.c.

01372 {
01373   struct tm tm;
01374 
01375   gnc_tm_get_day_start(&tm, time(NULL));
01376   return mktime(&tm);
01377 }

long int gnc_timezone struct tm *  tm  ) 
 

The gnc_timezone function returns the number of seconds *west* of UTC represented by the tm argument, adjusted for daylight savings time.

This function requires a tm argument returned by localtime or set by mktime. This is a strange function! It requires that localtime or mktime be called before use. Subsequent calls to localtime or mktime *may* invalidate the result! The actual contents of tm *may* be used for both timezone offset and daylight savings time, or only daylight savings time! Timezone stuff under unix is not standardized and is a big mess.

Definition at line 1260 of file gnc-date.c.

01261 {
01262   g_return_val_if_fail (tm != NULL, 0);
01263 
01264 #ifdef HAVE_STRUCT_TM_GMTOFF
01265   /* tm_gmtoff is seconds *east* of UTC and is
01266    * already adjusted for daylight savings time. */
01267   return -(tm->tm_gmtoff);
01268 #else
01269   /* timezone is seconds *west* of UTC and is
01270    * not adjusted for daylight savings time.
01271    * In Spring, we spring forward, wheee! */
01272   return timezone - (tm->tm_isdst > 0 ? 60 * 60 : 0);
01273 #endif
01274 }

void gnc_tm_get_day_end struct tm *  tm,
time_t  time_val
 

The gnc_tm_get_day_end() routine will convert the given time in seconds to the struct tm format, and then adjust it to the last second of that day.

Definition at line 1299 of file gnc-date.c.

01300 {
01301   /* Get the equivalent time structure */
01302   tm = localtime_r(&time_val, tm);
01303   gnc_tm_set_day_end(tm);
01304 }

void gnc_tm_get_day_start struct tm *  tm,
time_t  time_val
 

The gnc_tm_get_day_start() routine will convert the given time in seconds to the struct tm format, and then adjust it to the first second of that day.

Definition at line 1291 of file gnc-date.c.

01292 {
01293   /* Get the equivalent time structure */
01294   tm = localtime_r(&time_val, tm);
01295   gnc_tm_set_day_start(tm);
01296 }

void gnc_tm_get_today_end struct tm *  tm  ) 
 

The gnc_tm_get_today_end() routine takes a pointer to a struct tm and fills it in with the last second of the today.

Definition at line 1365 of file gnc-date.c.

01366 {
01367   gnc_tm_get_day_end(tm, time(NULL));
01368 }

void gnc_tm_get_today_start struct tm *  tm  ) 
 

The gnc_tm_get_today_start() routine takes a pointer to a struct tm and fills it in with the first second of the today.

Definition at line 1359 of file gnc-date.c.

01360 {
01361   gnc_tm_get_day_start(tm, time(NULL));
01362 }

QofDateFormat qof_date_format_get void   ) 
 

The qof_date_format_get routine returns the date format that the date printing will use when printing a date, and the scaning routines will assume when parsing a date.

Returns:
: the one of the enumerated date formats.

Definition at line 343 of file gnc-date.c.

00344 {
00345   return dateFormat;
00346 }

const gchar* qof_date_format_get_format QofDateFormat  df  ) 
 

DOCUMENT ME!

Definition at line 411 of file gnc-date.c.

00412 {
00413   switch(df) {
00414    case QOF_DATE_FORMAT_US:
00415     return "%b %d, %y";
00416    case QOF_DATE_FORMAT_UK:
00417    case QOF_DATE_FORMAT_CE:
00418     return "%d %b, %y";
00419    case QOF_DATE_FORMAT_UTC:
00420     return "%Y-%m-%dT%H:%M:%SZ";
00421    case QOF_DATE_FORMAT_ISO:
00422     return "%y-%b-%d";
00423    case QOF_DATE_FORMAT_LOCALE:
00424    default:
00425     return GNC_D_FMT;
00426   };
00427 }

const gchar* qof_date_format_get_string QofDateFormat  df  ) 
 

DOCUMENT ME!

Definition at line 383 of file gnc-date.c.

00384 {
00385   switch(df) {
00386    case QOF_DATE_FORMAT_US:
00387     return "%m/%d/%y";
00388    case QOF_DATE_FORMAT_UK:
00389     return "%d/%m/%y";
00390    case QOF_DATE_FORMAT_CE:
00391     return "%d.%m.%y";
00392    case QOF_DATE_FORMAT_UTC:
00393     return "%Y-%m-%dT%H:%M:%SZ";
00394    case QOF_DATE_FORMAT_ISO:
00395     return "%y-%m-%d";
00396    case QOF_DATE_FORMAT_LOCALE:
00397    default:
00398     return GNC_D_FMT;
00399   };
00400 }

void qof_date_format_set QofDateFormat  df  ) 
 

The qof_date_format_set() routine sets date format to one of US, UK, CE, OR ISO. Checks to make sure it's a legal value. Args: QofDateFormat: enumeration indicating preferred format

Definition at line 359 of file gnc-date.c.

00360 {
00361   if(df >= DATE_FORMAT_FIRST && df <= DATE_FORMAT_LAST)
00362   {
00363     prevQofDateFormat = dateFormat;
00364     dateFormat = df;
00365   }
00366   else
00367   {    /* hack alert - Use a neutral default. */
00368     PERR("non-existent date format set attempted. Setting ISO default");
00369     prevQofDateFormat = dateFormat;
00370     dateFormat = QOF_DATE_FORMAT_ISO;
00371   }
00372 
00373   return;
00374 }

gboolean qof_is_same_day time_t  ,
time_t 
 

The qof_is_same_day() routine returns 0 if both times are in the same day.

Definition at line 697 of file gnc-date.c.

00698 {
00699   struct tm lta, ltb;
00700   lta = *localtime (&ta);
00701   ltb = *localtime (&tb);
00702   if (lta.tm_year == ltb.tm_year)
00703   {
00704     return (ltb.tm_yday - lta.tm_yday);
00705   }
00706   return (ltb.tm_year - lta.tm_year)*365;  /* very approximate */
00707 }

char* qof_print_date time_t  secs  ) 
 

Convenience; calls through to qof_print_date_dmy_buff(). Return: string, which should be freed when no longer needed.

Definition at line 522 of file gnc-date.c.

00523 {
00524    char buff[MAX_DATE_LENGTH];
00525    qof_print_date_buff (buff, MAX_DATE_LENGTH, t);
00526    return g_strdup (buff);
00527 }

size_t qof_print_date_buff char *  buff,
size_t  buflen,
time_t  secs
 

Convenience: calls through to qof_print_date_dmy_buff().

Definition at line 498 of file gnc-date.c.

00499 {
00500   struct tm *theTime;
00501 
00502   if (!buff) return 0 ;
00503 
00504   theTime = localtime (&t);
00505 
00506   return qof_print_date_dmy_buff (buff, len,
00507                    theTime->tm_mday, 
00508                    theTime->tm_mon + 1,
00509                    theTime->tm_year + 1900);
00510 }

size_t qof_print_date_dmy_buff char *  buff,
size_t  buflen,
int  day,
int  month,
int  year
 

qof_print_date_dmy_buff Convert a date as day / month / year integers into a localized string representation

Args: buff - pointer to previously allocated character array; its size must be at lease MAX_DATE_LENTH bytes. len - length of the buffer, in bytes. day - day of the month as 1 ... 31 month - month of the year as 1 ... 12 year - year (4-digit)

Returns: number of characters printed

Globals: global dateFormat value

Definition at line 445 of file gnc-date.c.

00446 {
00447   int flen;
00448   if (!buff) return 0;
00449 
00450   /* Note that when printing year, we use %-4d in format string;
00451    * this causes a one, two or three-digit year to be left-adjusted
00452    * when printed (i.e. padded with blanks on the right).  This is 
00453    * important while the user is editing the year, since erasing a 
00454    * digit can temporarily cause a three-digit year, and having the 
00455    * blank on the left is a real pain for the user.  So pad on the 
00456    * right.
00457    */
00458   switch(dateFormat)
00459   {
00460     case QOF_DATE_FORMAT_UK:
00461       flen = g_snprintf (buff, len, "%2d/%2d/%-4d", day, month, year);
00462       break;
00463     case QOF_DATE_FORMAT_CE:
00464       flen = g_snprintf (buff, len, "%2d.%2d.%-4d", day, month, year);
00465       break;
00466     case QOF_DATE_FORMAT_LOCALE:
00467       {
00468         struct tm tm_str;
00469         time_t t;
00470 
00471         tm_str.tm_mday = day;
00472         tm_str.tm_mon = month - 1;    /* tm_mon = 0 through 11 */
00473         tm_str.tm_year = year - 1900; /* this is what the standard 
00474                                        * says, it's not a Y2K thing */
00475 
00476         gnc_tm_set_day_start (&tm_str);
00477         t = mktime (&tm_str);
00478         localtime_r (&t, &tm_str);
00479         flen = strftime (buff, len, GNC_D_FMT, &tm_str);
00480        if (flen != 0)
00481          break;
00482       }
00483       /* FALLTHROUGH */
00484     case QOF_DATE_FORMAT_ISO:
00485     case QOF_DATE_FORMAT_UTC:
00486       flen = g_snprintf (buff, len, "%04d-%02d-%02d", year, month, day);
00487       break;
00488     case QOF_DATE_FORMAT_US:
00489     default:
00490       flen = g_snprintf (buff, len, "%2d/%2d/%-4d", month, day, year);
00491       break;
00492   }
00493 
00494   return flen;
00495 }

size_t qof_print_gdate char *  buf,
size_t  bufflen,
GDate *  gd
 

Convenience; calls through to qof_print_date_dmy_buff().

Definition at line 513 of file gnc-date.c.

00514 {
00515   return qof_print_date_dmy_buff( buf, len,
00516              g_date_day(gd),
00517              g_date_month(gd),
00518              g_date_year(gd) );
00519 }

size_t qof_print_hours_elapsed_buff char *  buff,
size_t  len,
int  secs,
gboolean  show_secs
 

The qof_print_hours_elapsed_buff() routine will print the 'secs' argument as HH:MM, and will print the seconds if show_secs is true. Thus, for example, secs=3599 will print as 0:59 Returns the number of bytes copied.

Definition at line 545 of file gnc-date.c.

00546 {
00547         size_t flen;
00548         if (0 <= secs)
00549         {
00550                 if (show_secs)
00551                 {
00552                         flen = g_snprintf(buff, len,
00553                            "%02d:%02d:%02d", (int)(secs / 3600),
00554                            (int)((secs % 3600) / 60), (int)(secs % 60));
00555                 }
00556                 else
00557                 {
00558                         flen = g_snprintf(buff, len, 
00559                            "%02d:%02d", (int)(secs / 3600),
00560                            (int)((secs % 3600) / 60));
00561                 }
00562         } 
00563         else 
00564         {
00565                 if (show_secs)
00566                 {
00567                         flen = g_snprintf(buff, len,
00568                            "-%02d:%02d:%02d", (int)(-secs / 3600),
00569                            (int)((-secs % 3600) / 60), (int)(-secs % 60));
00570                 }
00571                 else
00572                 {
00573                         flen = g_snprintf(buff, len,
00574                            "-%02d:%02d", (int)(-secs / 3600),
00575                            (int)((-secs % 3600) / 60));
00576                 }
00577         }
00578         return flen;
00579 }

size_t qof_print_time_buff char *  buff,
size_t  len,
time_t  secs
 

The qof_print_time_buff() routine prints only the hour-part of the date. Thus, if secs is ... Returns the number of bytes printed.

Definition at line 676 of file gnc-date.c.

00677 {
00678         int flen;
00679         struct tm ltm, gtm;
00680         
00681         if (!buff) return 0;
00682         if(dateFormat == QOF_DATE_FORMAT_UTC)
00683         {
00684                 gtm = *gmtime (&secs);
00685                 flen = strftime(buff, len, QOF_UTC_DATE_FORMAT, &gtm);
00686                 return flen;
00687         }
00688         ltm = *localtime (&secs);
00689         flen = strftime (buff, len, GNC_T_FMT, &ltm);
00690         
00691         return flen;
00692 }

gboolean qof_scan_date const char *  buff,
int *  day,
int *  month,
int *  year
 

qof_scan_date Convert a string into day / month / year integers according to the current dateFormat value.

Args: buff - pointer to date string day - will store day of the month as 1 ... 31 month - will store month of the year as 1 ... 12 year - will store the year (4-digit)

Return: TRUE if the string seemed to be a valid date; else FALSE.

Globals: uses global dateFormat value to assist in parsing.

Definition at line 902 of file gnc-date.c.

00903 {
00904   return qof_scan_date_internal(buff, day, month, year, dateFormat);
00905 }

gboolean qof_scan_date_secs const char *  buff,
time_t *  secs
 

as above, but returns seconds

Definition at line 908 of file gnc-date.c.

00909 {
00910   gboolean rc;
00911   int day, month, year;
00912   
00913   rc = qof_scan_date_internal(buff, &day, &month, &year, dateFormat);
00914   if (secs) *secs = xaccDMYToSec (day, month, year);
00915 
00916   return rc;
00917 }

Timespec timespec_abs const Timespec t  ) 
 

absolute value, also normalised

Definition at line 225 of file gnc-date.c.

00226 {
00227   Timespec retval = *t;
00228 
00229   timespec_normalize(&retval);
00230   if (retval.tv_sec < 0)
00231   {
00232     retval.tv_sec = - retval.tv_sec;
00233     retval.tv_nsec = - retval.tv_nsec;
00234   }
00235   
00236   return retval;
00237 }

int timespec_cmp const Timespec ta,
const Timespec tb
 

comparison: if (ta < tb) -1; else if (ta > tb) 1; else 0;

Definition at line 204 of file gnc-date.c.

00205 {
00206   if(ta == tb) return 0;
00207   if(ta->tv_sec < tb->tv_sec) return -1;
00208   if(ta->tv_sec > tb->tv_sec) return 1;
00209   if(ta->tv_nsec < tb->tv_nsec) return -1;
00210   if(ta->tv_nsec > tb->tv_nsec) return 1;
00211   return 0;
00212 }

Timespec timespec_diff const Timespec ta,
const Timespec tb
 

difference between ta and tb, results are normalised ie tv_sec and tv_nsec of the result have the same size abs(result.tv_nsec) <= 1000000000

Definition at line 215 of file gnc-date.c.

00216 {
00217   Timespec retval;
00218   retval.tv_sec = ta->tv_sec - tb->tv_sec;
00219   retval.tv_nsec = ta->tv_nsec - tb->tv_nsec;
00220   timespec_normalize(&retval);
00221   return retval;
00222 }

gboolean timespec_equal const Timespec ta,
const Timespec tb
 

strict equality

Definition at line 195 of file gnc-date.c.

00196 {
00197   if(ta == tb) return TRUE;
00198   if(ta->tv_sec != tb->tv_sec) return FALSE;
00199   if(ta->tv_nsec != tb->tv_nsec) return FALSE;
00200   return TRUE;
00201 }

Timespec timespecCanonicalDayTime Timespec  t  ) 
 

Converts any time on a day to midday that day.

given a timepair contains any time on a certain day (local time) converts it to be midday that day.

Definition at line 246 of file gnc-date.c.

00247 {
00248   struct tm tm, *result;
00249   Timespec retval;
00250   time_t t_secs = t.tv_sec + (t.tv_nsec / NANOS_PER_SECOND);
00251   result = localtime(&t_secs);
00252   tm = *result;
00253   gnc_tm_set_day_middle(&tm);
00254   retval.tv_sec = mktime(&tm);
00255   retval.tv_nsec = 0;
00256   return retval;
00257 }

void timespecFromTime_t Timespec ts,
time_t  t
 

Turns a time_t into a Timespec

Definition at line 1278 of file gnc-date.c.

01279 {
01280     ts->tv_sec = t;
01281     ts->tv_nsec = 0;
01282 }

time_t timespecToTime_t Timespec  ts  ) 
 

Turns a Timespec into a time_t

Definition at line 1285 of file gnc-date.c.

01286 {
01287     return ts.tv_sec;
01288 }

char* xaccDateUtilGetStamp time_t  thyme  ) 
 

The xaccDateUtilGetStamp() routine will take the given time in seconds and return a buffer containing a textual for the date.

Parameters:
thyme The time in seconds to convert.
Returns:
A pointer to the generated string.
Note:
The caller owns this buffer and must free it when done.

Definition at line 973 of file gnc-date.c.

00974 {
00975    struct tm *stm;
00976                                                                                 
00977    stm = localtime (&thyme);
00978                                                                                 
00979    return g_strdup_printf("%04d%02d%02d%02d%02d%02d",
00980       (stm->tm_year + 1900),
00981       (stm->tm_mon +1),
00982       stm->tm_mday,
00983       stm->tm_hour,
00984       stm->tm_min,
00985       stm->tm_sec
00986    );
00987 }

char* xaccDateUtilGetStampNow void   ) 
 

The xaccDateUtilGetStampNow() routine returns the current time in seconds in textual format.

Returns:
A pointer to the generated string.
Note:
The caller owns this buffer and must free it when done.

Definition at line 1000 of file gnc-date.c.

01001 {
01002    time_t now;
01003    time (&now);
01004    return xaccDateUtilGetStamp (now);
01005 }

time_t xaccDMYToSec int  day,
int  month,
int  year
 

Warning:
hack alert XXX FIXME -- these date routines return incorrect values for dates before 1970. Most of them are good only up till 2038. This needs fixing ...
XXX This routine should be modified to assume that the the user wanted the time at noon, localtime. The returned time_t should be seconds (at GMT) of the local noon-time.

Definition at line 1185 of file gnc-date.c.

01186 {
01187   struct tm stm;
01188   time_t secs;
01189 
01190   stm.tm_year = year - 1900;
01191   stm.tm_mon = month - 1;
01192   stm.tm_mday = day;
01193   gnc_tm_set_day_start(&stm);
01194 
01195   /* compute number of seconds */
01196   secs = mktime (&stm);
01197 
01198   return secs;
01199 }


Generated on Sun Sep 4 18:09:12 2005 for GnuCash by  doxygen 1.4.3-20050530