From f49b80de01a630911a81cda94a95c66bad8cc0cc Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Tue, 21 Aug 2007 09:54:51 +0000 Subject: [PATCH] Add iso8601_difference() --- src/libiso8601/400_manip.c | 32 ++++++++++++++++++++++++++++++++ src/libiso8601/400_manip.h | 21 +++++++++++++++++++-- src/tests/manip.c | 17 +++++++++++++++-- 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/libiso8601/400_manip.c b/src/libiso8601/400_manip.c index 92185ea..964cf0e 100644 --- a/src/libiso8601/400_manip.c +++ b/src/libiso8601/400_manip.c @@ -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 kate: replace-trailing-space-save true; space-indent true; tab-width 4; vim: expandtab:ts=4:sw=4 diff --git a/src/libiso8601/400_manip.h b/src/libiso8601/400_manip.h index f4d0821..eac24da 100644 --- a/src/libiso8601/400_manip.h +++ b/src/libiso8601/400_manip.h @@ -9,8 +9,8 @@ /*! \defgroup manip Manipulation routines. -This set of functions is useful for converting dates and times into formats understood by humans, -and vice versa. +This set of functions is useful for performing arithmetic etc. on dates. It uses +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 |d1 - d2|, 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 > \a d1 or +1 if \a d2 <= \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 kate: replace-trailing-space-save true; space-indent true; tab-width 4; diff --git a/src/tests/manip.c b/src/tests/manip.c index 61fab4c..32b3127 100644 --- a/src/tests/manip.c +++ b/src/tests/manip.c @@ -159,6 +159,7 @@ void usage(void) "Operators:\n" " + (date, period) Advance 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 or equal to second.\n" " == (date, date) Prints 1 if dates equal.\n" @@ -177,8 +178,7 @@ int parse_command(char* cmd) struct iso8601_elapsed period; double period_d; char date_str[40]; - - int ret = 0; + int ret = 0, sign; cmd = strtok(cmd, " \n"); 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, "<")) { if(date_stack_pop_date(&date, &details) || date_stack_pop_date(&date2, &details2)) { ret = 1;