Add iso8601_difference()

This commit is contained in:
Laurence Withers 2007-08-21 09:54:51 +00:00
parent 4deda83c58
commit f49b80de01
3 changed files with 66 additions and 4 deletions

View File

@ -98,6 +98,38 @@ void iso8601_subtract_elapsed(struct iso8601_date* date, const struct iso8601_el
void iso8601_difference(const struct iso8601_date* d1, const struct iso8601_date* d2,
struct iso8601_elapsed* per, int* sign)
{
const struct iso8601_date* e1, * e2;
/* compute sign */
if(iso8601_lt(d1, d2)) {
if(sign) *sign = -1;
e1 = d2;
e2 = d1;
} else {
if(sign) *sign = 1;
e1 = d1;
e2 = d2;
}
if(!per) return;
/* compute difference, knowing that e1 >= e2 */
per->sec = (e1->day - e2->day) * 86400
+ iso8601_leap_elapsed(e2, e1 /* start, end */)
+ (e1->sec - e2->sec);
if(e1->nsec < e2->nsec) {
--per->sec;
per->nsec = BILLION + e1->nsec - e2->nsec;
} else {
per->nsec = e1->nsec - e2->nsec;
}
}
/* options for text editors /* options for text editors
kate: replace-trailing-space-save true; space-indent true; tab-width 4; kate: replace-trailing-space-save true; space-indent true; tab-width 4;
vim: expandtab:ts=4:sw=4 vim: expandtab:ts=4:sw=4

View File

@ -9,8 +9,8 @@
/*! \defgroup manip Manipulation routines. /*! \defgroup manip Manipulation routines.
This set of functions is useful for converting dates and times into formats understood by humans, This set of functions is useful for performing arithmetic etc. on dates. It uses
and vice versa. struct iso8601_elapsed to represent the magnitude of time differences.
*/ */
/*!@{*/ /*!@{*/
@ -73,6 +73,23 @@ void iso8601_subtract_elapsed(struct iso8601_date* date, const struct iso8601_el
/*! \brief Find difference between dates.
\param d1 First date.
\param d2 Second date.
\param[out] per Magnitude of period elapsed between two dates. Pointer may be 0.
\param[out] sign Set to sign of difference (-1 or +1). Pointer may be 0.
This function will perform the calculation <code>|d1 - d2|</code>, storing the result in \a per (if
it is not a null pointer). The sign of the result is stored in \a sign (if it is not a null
pointer), i.e. -1 if \a d2 &gt; \a d1 or +1 if \a d2 &lt;= \a d1.
*/
void iso8601_difference(const struct iso8601_date* d1, const struct iso8601_date* d2,
struct iso8601_elapsed* per, int* sign);
/*!@}*/ /*!@}*/
/* options for text editors /* options for text editors
kate: replace-trailing-space-save true; space-indent true; tab-width 4; kate: replace-trailing-space-save true; space-indent true; tab-width 4;

View File

@ -159,6 +159,7 @@ void usage(void)
"Operators:\n" "Operators:\n"
" + (date, period) Advance date by elapsed time, push date.\n" " + (date, period) Advance date by elapsed time, push date.\n"
" - (date, period) Regress date by elapsed time, push date.\n" " - (date, period) Regress date by elapsed time, push date.\n"
" dp (date, date) Compute difference, print elapsed time.\n"
" < (date, date) Prints 1 if first date less than second.\n" " < (date, date) Prints 1 if first date less than second.\n"
" <= (date, date) Prints 1 if first date less than or equal to second.\n" " <= (date, date) Prints 1 if first date less than or equal to second.\n"
" == (date, date) Prints 1 if dates equal.\n" " == (date, date) Prints 1 if dates equal.\n"
@ -177,8 +178,7 @@ int parse_command(char* cmd)
struct iso8601_elapsed period; struct iso8601_elapsed period;
double period_d; double period_d;
char date_str[40]; char date_str[40];
int ret = 0, sign;
int ret = 0;
cmd = strtok(cmd, " \n"); cmd = strtok(cmd, " \n");
while(cmd) { while(cmd) {
@ -209,6 +209,19 @@ int parse_command(char* cmd)
} }
} else if(!strcmp(cmd, "dp")) {
if(date_stack_pop_date(&date, &details) || date_stack_pop_date(&date2, &details2)) {
ret = 1;
} else {
iso8601_difference(&date2, &date, &period, &sign);
printf("Difference: %c %lu.%09lu\n",
(sign < 0) ? '-' : '+',
(unsigned long)period.sec,
(unsigned long)period.nsec);
}
} else if(!strcmp(cmd, "<")) { } else if(!strcmp(cmd, "<")) {
if(date_stack_pop_date(&date, &details) || date_stack_pop_date(&date2, &details2)) { if(date_stack_pop_date(&date, &details) || date_stack_pop_date(&date2, &details2)) {
ret = 1; ret = 1;