HTTPS SSH

tmdiff

Copyright 2012-2013 Joergen Ibsen

http://www.ibsensoftware.com/

About

This is an attempt at solving the problem of formatting the difference between two points in time in a manner similar to the strftime() function. It was based on a discussion about PBoL.

The problem is; given a start date and time, and an end date and time, format a string with values showing the difference in years, months, days, hours, minutes, and seconds between the two.

Because months and years contain a varying number of days, we cannot simply compute these from difftime().

For instance, the difference between Jan 31st and Mar 1st is sometimes 29 days, sometimes 30 days, but always one month and one day. The difference between Jul 2nd and Aug 1st is 30 days, but not a month.

tmdiff()

unsigned long long tmdiff( struct tm_d *d,
                           struct tm *end,
                           struct tm *start );

tmdiff() takes two tm structs and computes the difference between them in a tm_d struct:

struct tm_d {
    int year_d; /* difference in years */
    int mon_d;  /* difference in months of the year */
    int mday_d; /* difference in days of the month */
    int yday_d; /* difference in days of the year */
    int hour_d; /* difference in hours of the day */
    int min_d;  /* difference in minutes of the hour */
    int sec_d;  /* difference in seconds of the minute */
};

Both start and end must point to tm structs that are valid input to mktime(). The time represented by end must be equal to or after the time represented by start.

tmdiff() calls mktime() on both start and end, so they may be modified in the process.

The return value is the total number of seconds between start and end, or (unsigned long long)(-1) on error.

If d is NULL, then only the absolute difference in seconds is computed and returned.

The difference in calendar time is year_d years, mon_d months, mday_d days, hour_d hours, min_d minutes, sec_d seconds.

The total difference in calendar moths is 12 * year_d + mon_d.

The total difference in clock weeks, days, hours and minutes is the return value divided by the respective macro (WEEKSEC, DAYSEC, HOURSEC, MINSEC).

The difference in weeks of the year is yday_d / 7.

The difference in weeks of the month is mday_d / 7.

The difference in days of the week is mday_d % 7.

If the calendar time is below one day, hour_d is the clock time difference. This means that the day where DST starts may have less than 24 hours, and the day it ends more.

sftmdiff()

size_t sftmdiff( char *strDest,
                 size_t maxsize,
                 const char *format,
                 const struct tm *end,
                 const struct tm *start );

sftmdiff() computes the difference between two tm structs and provides formatted output of the result.

It uses tmdiff(), but on copies of start and end, so they are not modified.

Writes at most maxsize characters to strDest.

The return value is the number of characters written, not including the terminating null, or 0 on error.

Supported formatting codes:

%%  insert a %
%y  difference in years
%m  difference in months of the year
%w  difference in weeks of the year
%d  difference in days of the month
%H  difference in hours of the day (%0H zero-pad to width 2)
%M  difference in minutes of the hour (%0M zero-pad to width 2)
%S  difference in seconds of the minute (%0S zero-pad to width 2)

%Mw  difference in weeks of the month
%Yd  difference in days of the year
%Wd  difference in days of the week

%#m  total difference in months
%#w  total difference in weeks
%#d  total difference in days
%#H  total difference in hours
%#M  total difference in minutes
%#S  total difference in seconds

wsftmdiff()

size_t wsftmdiff( wchar_t *strDest,
                  size_t maxsize,
                  const wchar_t *format,
                  const struct tm *end,
                  const struct tm *start );

Wide character version of sftmdiff().

asctmdiff()

size_t asctmdiff( char *strDest,
                  size_t maxsize,
                  const struct tm *end,
                  const struct tm *start,
                  int max_fields,
                  int allow_convert,
                  const char *str_p,
                  const char *str_s );

asctmdiff() computes the difference between two tm structs and creates a string with a textual representation.

It uses tmdiff(), but on copies of start and end, so they are not modified.

Writes at most maxsize characters to strDest.

The possible fields used are year, month, week, day, hour, minute, and second. At most max_fields consecutive fields are used in the output string. So if max_fields is 3 and the first field used is month, then only week and day are potentially used as well.

If allow_convert is non-zero, the first field used may be converted down to the next if the value is relatively small. For instance if the first field would be year and the difference is 18 months or less, then the year is output as months instead.

If the seconds field is used, it is included even if the difference is 0 to avoid a large shift in the length of the string.

str_p and str_s are double-null terminated strings containing the 7 strings to be used for the fields. str_p is the plural, str_s the singular forms. If NULL, default long English strings are used.

The return value is the number of characters written, not including the terminating null, or 0 on error.

wasctmdiff()

size_t wasctmdiff( wchar_t *strDest,
                   size_t maxsize,
                   const struct tm *end,
                   const struct tm *start,
                   int max_fields,
                   int allow_convert,
                   const wchar_t *str_p,
                   const wchar_t *str_s );

Wide character version of asctmdiff().