From 4e3bb53d658d1acadea5a22f4f25a7d70d20aa41 Mon Sep 17 00:00:00 2001 From: Neel Date: Thu, 29 Jan 2026 11:59:56 -0500 Subject: [PATCH 01/11] Maintainibility: Refactor this function to reduce its Cognitive Complexity from 68 to the 25 allowed. --- lib/datetime/change.c | 130 +++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 70 deletions(-) diff --git a/lib/datetime/change.c b/lib/datetime/change.c index e2e7f3765cc..517b40c6a4d 100644 --- a/lib/datetime/change.c +++ b/lib/datetime/change.c @@ -101,78 +101,68 @@ int datetime_change_from_to(DateTime *dt, int from, int to, int round) } } - /* if losing precision, round - * round > 0 force up if any lost values not zero - * round ==0 increment by all lost values - */ - if (to < dt->to) { - if (round > 0) { - int x; - - x = datetime_is_absolute(dt) ? 1 : 0; - - for (carry = 0, pos = dt->to; carry == 0 && pos > to; pos--) { - switch (pos) { - case DATETIME_MONTH: - if (dt->month != x) - carry = 1; - break; - case DATETIME_DAY: - if (dt->day != x) - carry = 1; - break; - case DATETIME_HOUR: - if (dt->hour != 0) - carry = 1; - break; - case DATETIME_MINUTE: - if (dt->minute != 0) - carry = 1; - break; - case DATETIME_SECOND: - if (dt->second != 0) - carry = 1; - break; - } - } - - if (carry) { - make_incr(&incr, to, to, dt); - - incr.year = 1; - incr.month = 1; - incr.day = 1; - incr.hour = 1; - incr.minute = 1; - incr.second = 1.0; - - datetime_increment(dt, &incr); - } - } - - if (round == 0) { - /*NEW*/ if (datetime_is_absolute(dt)) - /*NEW*/ ndays = datetime_days_in_year(dt->year, dt->positive); - /*NEW*/ - else - /*NEW*/ ndays = 0; - - for (pos = dt->to; pos > to; pos--) { - make_incr(&incr, pos, pos, dt); - - incr.year = dt->year; - incr.month = dt->month; - /*NEW*/ incr.day = dt->day + ndays / 2; - incr.hour = dt->hour; - incr.minute = dt->minute; - incr.second = dt->second; - - datetime_increment(dt, &incr); - /*NEW*/ if (ndays > 0 && pos == DATETIME_DAY) - /*NEW*/ break; - } +static void round_lost_precision(DateTime *dt, int to, int round) + { + DateTime incr; + int pos, carry, ndays; + + if (to >= dt->to) + return; + + if (round > 0) { + int x = datetime_is_absolute(dt) ? 1 : 0; + + for (carry = 0, pos = dt->to; carry == 0 && pos > to; pos--) { + switch (pos) { + case DATETIME_MONTH: + if (dt->month != x) carry = 1; + break; + case DATETIME_DAY: + if (dt->day != x) carry = 1; + break; + case DATETIME_HOUR: + if (dt->hour != 0) carry = 1; + break; + case DATETIME_MINUTE: + if (dt->minute != 0) carry = 1; + break; + case DATETIME_SECOND: + if (dt->second != 0) carry = 1; + break; + } + } + + if (carry) { + make_incr(&incr, to, to, dt); + incr.year = 1; incr.month = 1; incr.day = 1; + incr.hour = 1; incr.minute = 1; incr.second = 1.0; + datetime_increment(dt, &incr); + } + } + + if (round == 0) { + ndays = datetime_is_absolute(dt) + ? datetime_days_in_year(dt->year, dt->positive) + : 0; + + for (pos = dt->to; pos > to; pos--) { + make_incr(&incr, pos, pos, dt); + incr.year = dt->year; + incr.month = dt->month; + incr.day = dt->day + ndays / 2; + incr.hour = dt->hour; + incr.minute = dt->minute; + incr.second = dt->second; + datetime_increment(dt, &incr); + + if (ndays > 0 && pos == DATETIME_DAY) + break; } } + } + + + round_lost_precision(dt, to, round); /* set the new elements to zero */ for (pos = from; pos < dtfrom; pos++) From 23d1282381dacd0d583783103fd294325e5bb591 Mon Sep 17 00:00:00 2001 From: Neel Date: Fri, 6 Feb 2026 19:23:20 -0500 Subject: [PATCH 02/11] Maintainibility: Refactor this code to not nest more than 3 if|for|do|while|switch statements --- lib/datetime/change.c | 52 +++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/lib/datetime/change.c b/lib/datetime/change.c index 517b40c6a4d..ad2bceb644e 100644 --- a/lib/datetime/change.c +++ b/lib/datetime/change.c @@ -5,9 +5,40 @@ * Read the file GPL.TXT coming with GRASS for details. */ #include - static void make_incr(DateTime *, int, int, DateTime *); +/* Returns 1 if any “lost” component between dt->to down to (to+1) is non-default */ +static int has_lost_non_default(const DateTime *dt, int to, int x) +{ + int pos; + + for (pos = dt->to; pos > to; pos--) { + switch (pos) { + case DATETIME_MONTH: + if (dt->month != x) + return 1; + break; + case DATETIME_DAY: + if (dt->day != x) + return 1; + break; + case DATETIME_HOUR: + if (dt->hour != x) + return 1; + break; + case DATETIME_MINUTE: + if (dt->minute != x) + return 1; + break; + case DATETIME_SECOND: + if (dt->second != (double)x) + return 1; + break; + } + } + return 0; +} + /*! * \brief * @@ -112,24 +143,7 @@ static void round_lost_precision(DateTime *dt, int to, int round) if (round > 0) { int x = datetime_is_absolute(dt) ? 1 : 0; - for (carry = 0, pos = dt->to; carry == 0 && pos > to; pos--) { - switch (pos) { - case DATETIME_MONTH: - if (dt->month != x) carry = 1; - break; - case DATETIME_DAY: - if (dt->day != x) carry = 1; - break; - case DATETIME_HOUR: - if (dt->hour != 0) carry = 1; - break; - case DATETIME_MINUTE: - if (dt->minute != 0) carry = 1; - break; - case DATETIME_SECOND: - if (dt->second != 0) carry = 1; - break; - } + carry = has_lost_non_default(dt, to, x); } if (carry) { From f90c85b20731f3e5a82fdf89d15c0c6ed96ac036 Mon Sep 17 00:00:00 2001 From: Neel Date: Fri, 6 Feb 2026 19:27:07 -0500 Subject: [PATCH 03/11] Maintainibility: Refactor this code to not nest more than 3 if|for|do|while|switch statements --- lib/datetime/change.c | 44 ++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/lib/datetime/change.c b/lib/datetime/change.c index ad2bceb644e..a3d883e2ad6 100644 --- a/lib/datetime/change.c +++ b/lib/datetime/change.c @@ -7,6 +7,32 @@ #include static void make_incr(DateTime *, int, int, DateTime *); +/* Handles the "round == 0" branch for (to < dt->to): increment using all lost values */ +static void apply_round0_lost(DateTime *dt, int to, DateTime *incr) +{ + int pos; + int ndays; + + if (datetime_is_absolute(dt)) + ndays = datetime_days_in_year(dt->year, dt->positive); + else + ndays = 0; + + for (pos = dt->to; pos > to; pos--) { + make_incr(incr, pos, pos, dt); + incr->year = dt->year; + incr->month = dt->month; + incr->day = dt->day + ndays / 2; + incr->hour = dt->hour; + incr->minute = dt->minute; + incr->second = dt->second; + + datetime_increment(dt, incr); + + if (ndays > 0 && pos == DATETIME_DAY) + break; + } +} /* Returns 1 if any “lost” component between dt->to down to (to+1) is non-default */ static int has_lost_non_default(const DateTime *dt, int to, int x) { @@ -155,23 +181,7 @@ static void round_lost_precision(DateTime *dt, int to, int round) } if (round == 0) { - ndays = datetime_is_absolute(dt) - ? datetime_days_in_year(dt->year, dt->positive) - : 0; - - for (pos = dt->to; pos > to; pos--) { - make_incr(&incr, pos, pos, dt); - incr.year = dt->year; - incr.month = dt->month; - incr.day = dt->day + ndays / 2; - incr.hour = dt->hour; - incr.minute = dt->minute; - incr.second = dt->second; - datetime_increment(dt, &incr); - - if (ndays > 0 && pos == DATETIME_DAY) - break; - } + apply_round0_lost(dt, to, &incr); } } From 2d352bc9fe8e28d26abd1209a13294c4d48a74cf Mon Sep 17 00:00:00 2001 From: Neel Date: Fri, 6 Feb 2026 19:32:29 -0500 Subject: [PATCH 04/11] Maintainibility: Refactor this function to reduce its Cognitive Complexity from 41 to the 25 allowed --- lib/datetime/diff.c | 60 +++++++++++++-------------------------------- 1 file changed, 17 insertions(+), 43 deletions(-) diff --git a/lib/datetime/diff.c b/lib/datetime/diff.c index e0c09cd9a2d..6a51cf45041 100644 --- a/lib/datetime/diff.c +++ b/lib/datetime/diff.c @@ -183,68 +183,42 @@ static int _datetime_compare(const DateTime *a, const DateTime *b) int i; if (a->positive && !b->positive) - return (1); - else if (b->positive && !a->positive) - return (-1); + return 1; + if (b->positive && !a->positive) + return -1; - /* same signs */ for (i = a->from; i <= a->to; i++) { - switch (i) { + int c = 0; + switch (i) { case DATETIME_SECOND: - if (a->second > b->second) - return (1); - else if (a->second < b->second) - return (-1); + c = (a->second > b->second) - (a->second < b->second); break; - case DATETIME_MINUTE: - if (a->minute > b->minute) - return (1); - else if (a->minute < b->minute) - return (-1); + c = cmp_int(a->minute, b->minute); break; - case DATETIME_HOUR: - if (a->hour > b->hour) - return (1); - else if (a->hour < b->hour) - return (-1); + c = cmp_int(a->hour, b->hour); break; - case DATETIME_DAY: - if (a->day > b->day) - return (1); - else if (a->day < b->day) - return (-1); + c = cmp_int(a->day, b->day); break; - case DATETIME_MONTH: - if (a->month > b->month) - return (1); - else if (a->month < b->month) - return (-1); + c = cmp_int(a->month, b->month); break; - case DATETIME_YEAR: /* only place sign matters */ - if (a->positive) { - if (a->year > b->year) - return (1); - else if (a->year < b->year) - return (-1); - } - else { - if (a->year < b->year) - return (1); - else if (a->year > b->year) - return (-1); - } + c = cmp_year_signed(a, b); break; } + + if (c != 0) + return c; } - return (0); + + return 0; } + /*************************************************************/ static int _datetime_ymd_to_ddays(const DateTime *dtymd, double *days) From e6b04d03a730f0c95d3eabd438c9307aa79a650c Mon Sep 17 00:00:00 2001 From: Neel Date: Fri, 6 Feb 2026 19:43:58 -0500 Subject: [PATCH 05/11] Maintainibility: Refactor this function to reduce its Cognitive Complexity from 98 to the 25 allowed --- lib/datetime/format.c | 226 ++++++++++++++++++++++-------------------- 1 file changed, 120 insertions(+), 106 deletions(-) diff --git a/lib/datetime/format.c b/lib/datetime/format.c index 618ffc88ecc..6d26bf798ab 100644 --- a/lib/datetime/format.c +++ b/lib/datetime/format.c @@ -22,6 +22,121 @@ static char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", * \param buf * \return int */ +static void append_sep_if_needed(char *buf, const char *sep) +{ + if (*buf) + strcat(buf, sep); +} + +static void format_absolute(const DateTime *dt, char *buf, char *temp, + size_t tempsz) +{ + int n; + double sec; + + if (datetime_get_day(dt, &n) == 0) { + snprintf(temp, tempsz, "%d", n); + strcat(buf, temp); + } + + if (datetime_get_month(dt, &n) == 0) { + append_sep_if_needed(buf, " "); + strcat(buf, months[n - 1]); + } + + if (datetime_get_year(dt, &n) == 0) { + append_sep_if_needed(buf, " "); + snprintf(temp, tempsz, "%d", n); + strcat(buf, temp); + + if (datetime_is_negative(dt)) + strcat(buf, " bc"); + } + + if (datetime_get_hour(dt, &n) == 0) { + append_sep_if_needed(buf, " "); + snprintf(temp, tempsz, "%02d", n); + strcat(buf, temp); + } + + if (datetime_get_minute(dt, &n) == 0) { + append_sep_if_needed(buf, ":"); + snprintf(temp, tempsz, "%02d", n); + strcat(buf, temp); + } + + if (datetime_get_second(dt, &sec) == 0) { + append_sep_if_needed(buf, ":"); + + if (datetime_get_fracsec(dt, &n) != 0) + n = 0; + + snprintf(temp, tempsz, "%02.*f", n, sec); + strcat(buf, temp); + } + + if (datetime_get_timezone(dt, &n) == 0) { + int hour, minute; + + append_sep_if_needed(buf, " "); + datetime_decompose_timezone(n, &hour, &minute); + snprintf(temp, tempsz, "%s%02d%02d", n < 0 ? "-" : "+", hour, minute); + strcat(buf, temp); + } +} + +static void format_relative(const DateTime *dt, char *buf, char *temp, + size_t tempsz) +{ + int n; + double sec; + + if (datetime_is_negative(dt)) + strcat(buf, "-"); + + if (datetime_get_year(dt, &n) == 0) { + append_sep_if_needed(buf, " "); + snprintf(temp, tempsz, "%d year%s", n, n == 1 ? "" : "s"); + strcat(buf, temp); + } + + if (datetime_get_month(dt, &n) == 0) { + append_sep_if_needed(buf, " "); + snprintf(temp, tempsz, "%d month%s", n, n == 1 ? "" : "s"); + strcat(buf, temp); + } + + if (datetime_get_day(dt, &n) == 0) { + append_sep_if_needed(buf, " "); + snprintf(temp, tempsz, "%d day%s", n, n == 1 ? "" : "s"); + strcat(buf, temp); + } + + if (datetime_get_hour(dt, &n) == 0) { + append_sep_if_needed(buf, " "); + snprintf(temp, tempsz, "%d hour%s", n, n == 1 ? "" : "s"); + strcat(buf, temp); + } + + if (datetime_get_minute(dt, &n) == 0) { + append_sep_if_needed(buf, " "); + snprintf(temp, tempsz, "%d minute%s", n, n == 1 ? "" : "s"); + strcat(buf, temp); + } + + if (datetime_get_second(dt, &sec) == 0) { + append_sep_if_needed(buf, " "); + + if (datetime_get_fracsec(dt, &n) != 0) + n = 0; + + snprintf(temp, tempsz, "%.*f second%s", n, sec, + (sec == 1.0 && n == 0) ? "" : "s"); + strcat(buf, temp); + } +} + + int datetime_format(const DateTime *dt, char *buf) { /* Format the DateTime structure as a human-readable string */ @@ -31,118 +146,17 @@ int datetime_format(const DateTime *dt, char *buf) structure is not valid. */ char temp[128]; - int n; - double sec; *buf = 0; + if (!datetime_is_valid_type(dt)) return datetime_error_code(); - if (datetime_is_absolute(dt)) { - if (datetime_get_day(dt, &n) == 0) { - snprintf(temp, sizeof(temp), "%d", n); - strcat(buf, temp); - } - - if (datetime_get_month(dt, &n) == 0) { - if (*buf) - strcat(buf, " "); - strcat(buf, months[n - 1]); - } - - if (datetime_get_year(dt, &n) == 0) { - if (*buf) - strcat(buf, " "); - snprintf(temp, sizeof(temp), "%d", n); - strcat(buf, temp); - if (datetime_is_negative(dt)) - strcat(buf, " bc"); - } - - if (datetime_get_hour(dt, &n) == 0) { - if (*buf) - strcat(buf, " "); - snprintf(temp, sizeof(temp), "%02d", n); - strcat(buf, temp); - } - - if (datetime_get_minute(dt, &n) == 0) { - if (*buf) - strcat(buf, ":"); - snprintf(temp, sizeof(temp), "%02d", n); - strcat(buf, temp); - } - - if (datetime_get_second(dt, &sec) == 0) { - if (*buf) - strcat(buf, ":"); - if (datetime_get_fracsec(dt, &n) != 0) - n = 0; - snprintf(temp, sizeof(temp), "%02.*f", n, sec); - strcat(buf, temp); - } - - if (datetime_get_timezone(dt, &n) == 0) { - int hour, minute; - - if (*buf) - strcat(buf, " "); - datetime_decompose_timezone(n, &hour, &minute); - snprintf(temp, sizeof(temp), "%s%02d%02d", n < 0 ? "-" : "+", hour, - minute); - strcat(buf, temp); - } - } + if (datetime_is_absolute(dt)) + format_absolute(dt, buf, temp, sizeof(temp)); - if (datetime_is_relative(dt)) { - if (datetime_is_negative(dt)) - strcat(buf, "-"); - - if (datetime_get_year(dt, &n) == 0) { - if (*buf) - strcat(buf, " "); - snprintf(temp, sizeof(temp), "%d year%s", n, n == 1 ? "" : "s"); - strcat(buf, temp); - } - - if (datetime_get_month(dt, &n) == 0) { - if (*buf) - strcat(buf, " "); - snprintf(temp, sizeof(temp), "%d month%s", n, n == 1 ? "" : "s"); - strcat(buf, temp); - } - - if (datetime_get_day(dt, &n) == 0) { - if (*buf) - strcat(buf, " "); - snprintf(temp, sizeof(temp), "%d day%s", n, n == 1 ? "" : "s"); - strcat(buf, temp); - } - - if (datetime_get_hour(dt, &n) == 0) { - if (*buf) - strcat(buf, " "); - snprintf(temp, sizeof(temp), "%d hour%s", n, n == 1 ? "" : "s"); - strcat(buf, temp); - } - - if (datetime_get_minute(dt, &n) == 0) { - if (*buf) - strcat(buf, " "); - snprintf(temp, sizeof(temp), "%d minute%s", n, n == 1 ? "" : "s"); - strcat(buf, temp); - } - - if (datetime_get_second(dt, &sec) == 0) { - if (*buf) - strcat(buf, " "); - if (datetime_get_fracsec(dt, &n) != 0) - n = 0; - snprintf(temp, sizeof(temp), "%.*f second%s", n, sec, - (sec == 1.0 && n == 0) ? "" : "s"); - strcat(buf, temp); - } - } + if (datetime_is_relative(dt)) + format_relative(dt, buf, temp, sizeof(temp)); return 0; } From 3fc1d2f5ab85cbe795d05a8ce62b343c1ab1417d Mon Sep 17 00:00:00 2001 From: Neel Date: Sun, 8 Feb 2026 14:20:22 -0500 Subject: [PATCH 06/11] Maintainibility: Refactor this function to reduce its Cognitive Complexity from 101 to the 25 allowed --- lib/datetime/incr1.c | 557 +++++++++++++++++++++++++++---------------- 1 file changed, 345 insertions(+), 212 deletions(-) diff --git a/lib/datetime/incr1.c b/lib/datetime/incr1.c index 73c161ab1cc..fa57599ec68 100644 --- a/lib/datetime/incr1.c +++ b/lib/datetime/incr1.c @@ -9,6 +9,23 @@ static int _datetime_add_field(DateTime *, DateTime *, int); static int _datetime_subtract_field(DateTime *, DateTime *, int); +/* NEW helpers to reduce cognitive complexity */ +static int subtract_relative_field(DateTime *src, DateTime *incr, int field); +static int subtract_absolute_field(DateTime *src, DateTime *incr, int field); + +static int subtract_rel_second(DateTime *src, DateTime *incr); +static int subtract_rel_minute(DateTime *src, DateTime *incr); +static int subtract_rel_hour(DateTime *src, DateTime *incr); +static int subtract_rel_day(DateTime *src, DateTime *incr); +static int subtract_rel_month(DateTime *src, DateTime *incr); +static int subtract_rel_year(DateTime *src, DateTime *incr); + +static int subtract_abs_second(DateTime *src, DateTime *incr); +static int subtract_abs_minute(DateTime *src, DateTime *incr); +static int subtract_abs_hour(DateTime *src, DateTime *incr); +static int subtract_abs_day(DateTime *src, DateTime *incr); +static int subtract_abs_month(DateTime *src, DateTime *incr); +static int subtract_abs_year(DateTime *src, DateTime *incr); /*****************************************************************/ #if 0 /* unused */ static double _debug_decimal(DateTime * dt) @@ -152,219 +169,11 @@ int datetime_increment(DateTime *src, DateTime *incr) */ static int _datetime_subtract_field(DateTime *src, DateTime *incr, int field) { + if (src->mode == DATETIME_RELATIVE) + return subtract_relative_field(src, incr, field); - if (src->mode == DATETIME_RELATIVE) { - DateTime srcinc, tinc; - int borrow = 0; - - datetime_copy(&tinc, src); - datetime_copy(&srcinc, incr); - switch (field) { - case DATETIME_SECOND: - /* no "-1" here - remember seconds is floating point */ - /* might result in over borrowing, so have to check */ - if (src->second < incr->second) { - if ((int)(incr->second - src->second) == - (incr->second - src->second)) { /* diff is integer */ - borrow = 1 + (incr->second - src->second - 1) / 60; - } - else - borrow = 1 + (incr->second - src->second) / 60; - src->second += borrow * 60; - } - src->second -= incr->second; - if (borrow) { - srcinc.minute = borrow; - _datetime_subtract_field(src, &srcinc, DATETIME_MINUTE); - } - break; - - case DATETIME_MINUTE: - if (src->minute < incr->minute) { - borrow = 1 + (incr->minute - src->minute - 1) / 60; - src->minute += borrow * 60; - } - src->minute -= incr->minute; - if (borrow) { - srcinc.hour = borrow; - _datetime_subtract_field(src, &srcinc, DATETIME_HOUR); - } - break; - - case DATETIME_HOUR: - if (src->hour < incr->hour) { - borrow = 1 + (incr->hour - src->hour - 1) / 24; - src->hour += borrow * 24; - } - src->hour -= incr->hour; - if (borrow) { - srcinc.day = borrow; - _datetime_subtract_field(src, &srcinc, DATETIME_DAY); - } - break; - - case DATETIME_DAY: - if (src->day < incr->day) { /* SIGN CHANGE */ - src->day = incr->day - src->day; - datetime_invert_sign(src); - tinc.day = 0; - src->hour = 0; - src->minute = 0; - src->second = 0.0; - datetime_increment(src, &tinc); /* no sign change */ - } - else - src->day -= incr->day; - break; - - case DATETIME_MONTH: - if (src->month < incr->month) { - borrow = 1 + (incr->month - src->month - 1) / 12; - src->month += borrow * 12; - } - src->month -= incr->month; - if (borrow) { - srcinc.year = borrow; - _datetime_subtract_field(src, &srcinc, DATETIME_YEAR); - } - break; - - case DATETIME_YEAR: - if (src->year < incr->year) { /* SIGN CHANGE */ - src->year = incr->year - src->year; - datetime_invert_sign(src); - tinc.year = 0; - src->month = 0; - datetime_increment(src, &tinc); /* no sign change */ - } - else - src->year -= incr->year; - break; - } - } - - else if (src->mode == DATETIME_ABSOLUTE) { - DateTime srcinc, tinc, cpsrc; - int i, newdays, borrow = 0; - - datetime_copy(&srcinc, incr); /* makes srcinc valid incr */ - switch (field) { - case DATETIME_SECOND: - if (src->second < incr->second) { - borrow = 1 + (incr->second - src->second - 1) / 60; - src->second += borrow * 60; - } - src->second -= incr->second; - if (borrow) { - srcinc.minute = borrow; - _datetime_subtract_field(src, &srcinc, DATETIME_MINUTE); - } - break; - - case DATETIME_MINUTE: - if (src->minute < incr->minute) { - borrow = 1 + (incr->minute - src->minute - 1) / 60; - src->minute += borrow * 60; - } - src->minute -= incr->minute; - if (borrow) { - srcinc.hour = borrow; - _datetime_subtract_field(src, &srcinc, DATETIME_HOUR); - } - break; - - case DATETIME_HOUR: - if (src->hour < incr->hour) { - borrow = 1 + (incr->hour - src->hour - 1) / 24; - src->hour += borrow * 24; - } - src->hour -= incr->hour; - if (borrow) { - srcinc.day = borrow; - _datetime_subtract_field(src, &srcinc, DATETIME_DAY); - } - break; - - case DATETIME_DAY: - - if (src->day <= incr->day) { - datetime_copy(&cpsrc, src); - datetime_change_from_to(&cpsrc, DATETIME_YEAR, DATETIME_MONTH, - -1); - datetime_set_increment_type(&cpsrc, &tinc); - tinc.month = 1; - newdays = src->day; - while (newdays <= incr->day) { - _datetime_subtract_field(&cpsrc, &tinc, DATETIME_MONTH); - newdays += datetime_days_in_month(cpsrc.year, cpsrc.month, - cpsrc.positive); - borrow++; - } - src->day = newdays; - } - src->day -= incr->day; - if (borrow) { - /* - src->year = cpsrc.year; - src->month = cpsrc.month; - src->positive = cpsrc.positive; - */ - /* check here & below - srcinc may be a day-second interval - - * mess anything up? */ - srcinc.month = borrow; - _datetime_subtract_field(src, &srcinc, DATETIME_MONTH); - } - break; - - case DATETIME_MONTH: - if (src->month <= incr->month) { - borrow = 1 + (incr->month - src->month) / 12; - src->month += borrow * 12; - } - src->month -= incr->month; - if (borrow) { - srcinc.year = borrow; - _datetime_subtract_field(src, &srcinc, DATETIME_YEAR); - } - break; - - case DATETIME_YEAR: - if (src->year <= incr->year) { /* SIGN CHANGE */ - datetime_set_increment_type(src, &tinc); - tinc.positive = src->positive; - if (datetime_in_interval_year_month(tinc.to)) { - tinc.month = src->month - 1; /* convert to REL */ - src->year = incr->year - src->year + 1; - /* +1 to skip 0 */ - datetime_invert_sign(src); - tinc.year = 0; - src->month = 1; - datetime_increment(src, &tinc); /* no sign change */ - } - else { /* have to convert to days */ - tinc.day = src->day - 1; /* convert to REL */ - for (i = src->month - 1; i > 0; i--) { - tinc.day += - datetime_days_in_month(src->year, i, src->positive); - } - tinc.hour = src->hour; - tinc.minute = src->minute; - tinc.second = src->second; - src->year = incr->year - src->year + 1; - /* +1 to skip 0 */ - datetime_invert_sign(src); - src->month = 1; - src->day = 1; - src->hour = src->minute = 0; - src->second = 0; - datetime_increment(src, &tinc); /* no sign change */ - } - } - else - src->year -= incr->year; - break; - } - } + if (src->mode == DATETIME_ABSOLUTE) + return subtract_absolute_field(src, incr, field); return 0; } @@ -494,3 +303,327 @@ static int _datetime_add_field(DateTime *src, DateTime *incr, int field) return 0; } + +/* ---------------- NEW: RELATIVE dispatcher ---------------- */ +static int subtract_relative_field(DateTime *src, DateTime *incr, int field) +{ + switch (field) { + case DATETIME_SECOND: + return subtract_rel_second(src, incr); + case DATETIME_MINUTE: + return subtract_rel_minute(src, incr); + case DATETIME_HOUR: + return subtract_rel_hour(src, incr); + case DATETIME_DAY: + return subtract_rel_day(src, incr); + case DATETIME_MONTH: + return subtract_rel_month(src, incr); + case DATETIME_YEAR: + return subtract_rel_year(src, incr); + default: + return 0; + } +} + +static int subtract_rel_second(DateTime *src, DateTime *incr) +{ + DateTime srcinc; + int borrow = 0; + + datetime_copy(&srcinc, incr); + + if (src->second < incr->second) { + double diff = incr->second - src->second; + + /* keep original integer-diff special case */ + if ((int)diff == diff) + borrow = 1 + (diff - 1) / 60; + else + borrow = 1 + diff / 60; + + src->second += borrow * 60; + } + + src->second -= incr->second; + + if (borrow) { + srcinc.minute = borrow; + _datetime_subtract_field(src, &srcinc, DATETIME_MINUTE); + } + return 0; +} + +static int subtract_rel_minute(DateTime *src, DateTime *incr) +{ + DateTime srcinc; + int borrow = 0; + + datetime_copy(&srcinc, incr); + + if (src->minute < incr->minute) { + borrow = 1 + (incr->minute - src->minute - 1) / 60; + src->minute += borrow * 60; + } + src->minute -= incr->minute; + + if (borrow) { + srcinc.hour = borrow; + _datetime_subtract_field(src, &srcinc, DATETIME_HOUR); + } + return 0; +} + +static int subtract_rel_hour(DateTime *src, DateTime *incr) +{ + DateTime srcinc; + int borrow = 0; + + datetime_copy(&srcinc, incr); + + if (src->hour < incr->hour) { + borrow = 1 + (incr->hour - src->hour - 1) / 24; + src->hour += borrow * 24; + } + src->hour -= incr->hour; + + if (borrow) { + srcinc.day = borrow; + _datetime_subtract_field(src, &srcinc, DATETIME_DAY); + } + return 0; +} + +static int subtract_rel_day(DateTime *src, DateTime *incr) +{ + DateTime tinc; + + /* keep original sign-change behavior exactly */ + if (src->day < incr->day) { /* SIGN CHANGE */ + datetime_copy(&tinc, src); + src->day = incr->day - src->day; + datetime_invert_sign(src); + tinc.day = 0; + src->hour = 0; + src->minute = 0; + src->second = 0.0; + datetime_increment(src, &tinc); /* no sign change */ + return 0; + } + + src->day -= incr->day; + return 0; +} + +static int subtract_rel_month(DateTime *src, DateTime *incr) +{ + DateTime srcinc; + int borrow = 0; + + datetime_copy(&srcinc, incr); + + if (src->month < incr->month) { + borrow = 1 + (incr->month - src->month - 1) / 12; + src->month += borrow * 12; + } + src->month -= incr->month; + + if (borrow) { + srcinc.year = borrow; + _datetime_subtract_field(src, &srcinc, DATETIME_YEAR); + } + return 0; +} + +static int subtract_rel_year(DateTime *src, DateTime *incr) +{ + DateTime tinc; + + /* keep original sign-change behavior exactly */ + if (src->year < incr->year) { /* SIGN CHANGE */ + datetime_copy(&tinc, src); + src->year = incr->year - src->year; + datetime_invert_sign(src); + tinc.year = 0; + src->month = 0; + datetime_increment(src, &tinc); /* no sign change */ + return 0; + } + + src->year -= incr->year; + return 0; +} + +/* ---------------- NEW: ABSOLUTE dispatcher ---------------- */ +static int subtract_absolute_field(DateTime *src, DateTime *incr, int field) +{ + switch (field) { + case DATETIME_SECOND: + return subtract_abs_second(src, incr); + case DATETIME_MINUTE: + return subtract_abs_minute(src, incr); + case DATETIME_HOUR: + return subtract_abs_hour(src, incr); + case DATETIME_DAY: + return subtract_abs_day(src, incr); + case DATETIME_MONTH: + return subtract_abs_month(src, incr); + case DATETIME_YEAR: + return subtract_abs_year(src, incr); + default: + return 0; + } +} + +static int subtract_abs_second(DateTime *src, DateTime *incr) +{ + DateTime srcinc; + int borrow = 0; + + datetime_copy(&srcinc, incr); /* makes srcinc valid incr */ + + if (src->second < incr->second) { + borrow = 1 + (incr->second - src->second - 1) / 60; + src->second += borrow * 60; + } + src->second -= incr->second; + + if (borrow) { + srcinc.minute = borrow; + _datetime_subtract_field(src, &srcinc, DATETIME_MINUTE); + } + return 0; +} + +static int subtract_abs_minute(DateTime *src, DateTime *incr) +{ + DateTime srcinc; + int borrow = 0; + + datetime_copy(&srcinc, incr); + + if (src->minute < incr->minute) { + borrow = 1 + (incr->minute - src->minute - 1) / 60; + src->minute += borrow * 60; + } + src->minute -= incr->minute; + + if (borrow) { + srcinc.hour = borrow; + _datetime_subtract_field(src, &srcinc, DATETIME_HOUR); + } + return 0; +} + +static int subtract_abs_hour(DateTime *src, DateTime *incr) +{ + DateTime srcinc; + int borrow = 0; + + datetime_copy(&srcinc, incr); + + if (src->hour < incr->hour) { + borrow = 1 + (incr->hour - src->hour - 1) / 24; + src->hour += borrow * 24; + } + src->hour -= incr->hour; + + if (borrow) { + srcinc.day = borrow; + _datetime_subtract_field(src, &srcinc, DATETIME_DAY); + } + return 0; +} + +static int subtract_abs_day(DateTime *src, DateTime *incr) +{ + DateTime srcinc, tinc, cpsrc; + int newdays, borrow = 0; + + datetime_copy(&srcinc, incr); + + if (src->day <= incr->day) { + datetime_copy(&cpsrc, src); + datetime_change_from_to(&cpsrc, DATETIME_YEAR, DATETIME_MONTH, -1); + datetime_set_increment_type(&cpsrc, &tinc); + tinc.month = 1; + + newdays = src->day; + while (newdays <= incr->day) { + _datetime_subtract_field(&cpsrc, &tinc, DATETIME_MONTH); + newdays += datetime_days_in_month(cpsrc.year, cpsrc.month, + cpsrc.positive); + borrow++; + } + src->day = newdays; + } + + src->day -= incr->day; + + if (borrow) { + srcinc.month = borrow; + _datetime_subtract_field(src, &srcinc, DATETIME_MONTH); + } + return 0; +} + +static int subtract_abs_month(DateTime *src, DateTime *incr) +{ + DateTime srcinc; + int borrow = 0; + + datetime_copy(&srcinc, incr); + + if (src->month <= incr->month) { + borrow = 1 + (incr->month - src->month) / 12; + src->month += borrow * 12; + } + src->month -= incr->month; + + if (borrow) { + srcinc.year = borrow; + _datetime_subtract_field(src, &srcinc, DATETIME_YEAR); + } + return 0; +} + +static int subtract_abs_year(DateTime *src, DateTime *incr) +{ + DateTime tinc; + int i; + + if (src->year <= incr->year) { /* SIGN CHANGE */ + datetime_set_increment_type(src, &tinc); + tinc.positive = src->positive; + + if (datetime_in_interval_year_month(tinc.to)) { + tinc.month = src->month - 1; /* convert to REL */ + src->year = incr->year - src->year + 1; /* +1 to skip 0 */ + datetime_invert_sign(src); + tinc.year = 0; + src->month = 1; + datetime_increment(src, &tinc); /* no sign change */ + } + else { /* have to convert to days */ + tinc.day = src->day - 1; /* convert to REL */ + for (i = src->month - 1; i > 0; i--) { + tinc.day += datetime_days_in_month(src->year, i, src->positive); + } + tinc.hour = src->hour; + tinc.minute = src->minute; + tinc.second = src->second; + + src->year = incr->year - src->year + 1; /* +1 to skip 0 */ + datetime_invert_sign(src); + src->month = 1; + src->day = 1; + src->hour = src->minute = 0; + src->second = 0; + datetime_increment(src, &tinc); /* no sign change */ + } + return 0; + } + + src->year -= incr->year; + return 0; +} + From 43c906f07d7e01027a6b96796536ac30f3069f91 Mon Sep 17 00:00:00 2001 From: Neel Date: Sun, 8 Feb 2026 15:34:16 -0500 Subject: [PATCH 07/11] Maintainbility: Refactor this function to reduce its Cognitive Complexity from 47 to the 25 allowed --- lib/datetime/incr1.c | 112 ++++++++++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 45 deletions(-) diff --git a/lib/datetime/incr1.c b/lib/datetime/incr1.c index fa57599ec68..dba5d3c3615 100644 --- a/lib/datetime/incr1.c +++ b/lib/datetime/incr1.c @@ -182,11 +182,33 @@ static int _datetime_subtract_field(DateTime *src, DateTime *incr, int field) /* When absolute is zero, all fields carry toward the future */ /* When absolute is one, sign of datetime is ignored */ +/* NEW helpers for _datetime_carry() */ +static void carry_day_second(DateTime *dt); +static void maybe_temp_sign_year(DateTime *dt, int absolute); +static void normalize_year_month(DateTime *dt); +static void normalize_year_day(DateTime *dt); +static void undo_temp_sign_year(DateTime *dt, int absolute); + static int _datetime_carry(DateTime *dt, int absolute) +{ + carry_day_second(dt); + + maybe_temp_sign_year(dt, absolute); + + if (dt->from == DATETIME_YEAR && dt->to >= DATETIME_MONTH) + normalize_year_month(dt); + + if (dt->mode == DATETIME_ABSOLUTE && dt->to > DATETIME_MONTH) + normalize_year_day(dt); + + undo_temp_sign_year(dt, absolute); + + return 0; +} +static void carry_day_second(DateTime *dt) { int i, carry; - /* normalize day-sec (same for ABSOLUTE & RELATIVE) */ for (i = dt->to; i > dt->from && i > DATETIME_DAY; i--) { switch (i) { case DATETIME_SECOND: @@ -212,68 +234,68 @@ static int _datetime_carry(DateTime *dt, int absolute) break; } } +} - /* give year a SIGN, temporarily */ - if (!absolute && !dt->positive && dt->mode == DATETIME_ABSOLUTE) { +static void maybe_temp_sign_year(DateTime *dt, int absolute) +{ + if (!absolute && !dt->positive && dt->mode == DATETIME_ABSOLUTE) dt->year = -dt->year; - } +} - if (dt->from == DATETIME_YEAR && dt->to >= DATETIME_MONTH) { +static void normalize_year_month(DateTime *dt) +{ + int carry; + + if (dt->mode == DATETIME_ABSOLUTE) { + if (dt->month > 12) { + carry = (dt->month - 1) / 12; + dt->year += carry; + if (dt->year == 0) + dt->year = 1; + dt->month -= carry * 12; + } + } + else { + if (dt->month >= 12) { + carry = dt->month / 12; + dt->year += carry; + dt->month -= carry * 12; + } + } +} - /* normalize yr-mo */ - if (dt->mode == DATETIME_ABSOLUTE) { - if (dt->month > 12) { /* month will never be zero */ - carry = (dt->month - 1) / 12; /* no carry until 13 */ - dt->year += carry; - if (dt->year == 0) - dt->year = 1; - dt->month -= carry * 12; - /* - if(dt->month == 0) dt->month = 1; - shouldn't happen */ - } +static void normalize_year_day(DateTime *dt) +{ + while (dt->day > + datetime_days_in_month(dt->year, dt->month, dt->positive)) { + dt->day -= datetime_days_in_month(dt->year, dt->month, dt->positive); + + if (dt->month == 12) { + dt->year++; + if (dt->year == 0) + dt->year = 1; + dt->month = 1; } else { - if (dt->month >= 12) { - carry = dt->month / 12; - dt->year += carry; - dt->month -= carry * 12; - } + dt->month++; } } +} - /* normalize yr-day */ - if (dt->mode == DATETIME_ABSOLUTE && dt->to > DATETIME_MONTH) { - - while (dt->day > - datetime_days_in_month(dt->year, dt->month, dt->positive)) { - dt->day -= - datetime_days_in_month(dt->year, dt->month, dt->positive); - if (dt->month == 12) { /* carry to year */ - dt->year++; - if (dt->year == 0) - dt->year = 1; - dt->month = 1; - } - else /* no carry to year */ - dt->month++; - - } /* end while */ - } /* end if */ - - /* undo giving year a SIGN, temporarily */ +static void undo_temp_sign_year(DateTime *dt, int absolute) +{ if (!absolute && dt->mode == DATETIME_ABSOLUTE) { if (dt->year < 0) { dt->year = -dt->year; dt->positive = 0; } - else + else { dt->positive = 1; + } } - - return 0; } + static int _datetime_add_field(DateTime *src, DateTime *incr, int field) { switch (field) { From e49ad673ab20d9b40ebe9b7692ef6ba7cfb0c2de Mon Sep 17 00:00:00 2001 From: Neel Date: Sun, 8 Feb 2026 15:37:45 -0500 Subject: [PATCH 08/11] Maintainibility: Refactor this code to not nest more than 3 if|for|do|while|switch statements --- lib/datetime/incr1.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/datetime/incr1.c b/lib/datetime/incr1.c index dba5d3c3615..185662006bc 100644 --- a/lib/datetime/incr1.c +++ b/lib/datetime/incr1.c @@ -247,13 +247,16 @@ static void normalize_year_month(DateTime *dt) int carry; if (dt->mode == DATETIME_ABSOLUTE) { - if (dt->month > 12) { - carry = (dt->month - 1) / 12; - dt->year += carry; - if (dt->year == 0) - dt->year = 1; - dt->month -= carry * 12; - } + if (dt->month > 12) { /* month will never be zero */ + carry = (dt->month - 1) / 12; /* no carry until 13 */ + dt->year += carry; + + /* avoid an extra nested if (S134) */ + dt->year = (dt->year == 0) ? 1 : dt->year; + + dt->month -= carry * 12; +} + } else { if (dt->month >= 12) { From 63b37c8b42760260f4e65e7800882502291fe68e Mon Sep 17 00:00:00 2001 From: Neel Date: Sun, 8 Feb 2026 15:41:55 -0500 Subject: [PATCH 09/11] Maintainibility: Refactor this code to not nest more than 3 if|for|do|while|switch statements --- lib/datetime/incr1.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/datetime/incr1.c b/lib/datetime/incr1.c index 185662006bc..978c1a5ff91 100644 --- a/lib/datetime/incr1.c +++ b/lib/datetime/incr1.c @@ -273,15 +273,16 @@ static void normalize_year_day(DateTime *dt) datetime_days_in_month(dt->year, dt->month, dt->positive)) { dt->day -= datetime_days_in_month(dt->year, dt->month, dt->positive); - if (dt->month == 12) { + if (dt->month == 12) { /* carry to year */ dt->year++; - if (dt->year == 0) - dt->year = 1; + + /* avoid extra nested if (S134) */ + dt->year = (dt->year == 0) ? 1 : dt->year; + dt->month = 1; } - else { + else /* no carry to year */ dt->month++; - } } } From 431cf237be895d9e8ece9fb5516a0db26c324c1e Mon Sep 17 00:00:00 2001 From: Neel Date: Mon, 9 Feb 2026 14:38:32 -0500 Subject: [PATCH 10/11] Maintainibility: Refactor this function to reduce its Cognitive Complexity from 56 to the 25 allowed --- lib/datetime/scan.c | 127 +++++++++++--------------------------------- 1 file changed, 32 insertions(+), 95 deletions(-) diff --git a/lib/datetime/scan.c b/lib/datetime/scan.c index 0be1c198138..d25ac347f7e 100644 --- a/lib/datetime/scan.c +++ b/lib/datetime/scan.c @@ -25,6 +25,9 @@ static void skip_space(const char **); static int get_int(const char **, int *, int *); static int get_double(const char **, double *, int *, int *); +static int parse_abs_date(const char **p, AbsParsed *a); +static int parse_abs_time_and_tz(const char **p, AbsParsed *a); +static int apply_abs_fields(DateTime *dt, const AbsParsed *a); /*! * \brief * @@ -52,115 +55,49 @@ int datetime_scan(DateTime *dt, const char *buf) static const char *month_names[] = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"}; + +typedef struct { + int to; + int fracsec; + int tz; + int have_tz; + int bc; + int year, month, day; + int hour, minute; + double second; +} AbsParsed; + static int scan_absolute(DateTime *dt, const char *buf) { - char word[1024]; - int n; - int ndigits; - int tz = 0; - int have_tz = 0; - int bc = 0; - int to, fracsec = 0; - int year, month, day = 0, hour, minute; - double second; - const char *p; + const char *p = buf; + AbsParsed a; + + memset(&a, 0, sizeof(a)); + a.to = DATETIME_YEAR; - p = buf; if (!more(&p)) return 0; - if (!get_int(&p, &n, &ndigits)) { /* no day, so must be month, like Jan */ - if (!get_word(&p, word)) - return 0; - if (!which_month(word, &month)) - return 0; - if (!get_int(&p, &year, &ndigits)) /* year following the month */ - return 0; - to = DATETIME_MONTH; - if (is_bc(&p)) - bc = 1; - goto set; - } - - bc = is_bc(&p); - if (bc || !get_word(&p, word)) { /* just a year */ - year = n; - to = DATETIME_YEAR; - goto set; - } - to = DATETIME_DAY; /* must be at least: day Mon year [bc] */ - day = n; - if (!which_month(word, &month)) - return 0; - if (!get_int(&p, &year, &ndigits)) - return 0; - if (is_bc(&p)) - bc = 1; - - /* now for the time */ - if (!get_int(&p, &hour, &ndigits)) - goto set; - to = DATETIME_HOUR; - if (*p != ':') - goto set; - p++; - if (!get_int(&p, &minute, &ndigits)) + if (!parse_abs_date(&p, &a)) return 0; - if (ndigits != 2) - return 0; - to = DATETIME_MINUTE; - if (*p != ':') - goto timezone; - p++; - if (!get_double(&p, &second, &ndigits, &fracsec)) - return 0; - if (ndigits != 2) + + if (!parse_abs_time_and_tz(&p, &a)) return 0; - to = DATETIME_SECOND; -timezone: - if (!get_word(&p, word)) - goto set; - if (!scan_tz(word, &tz)) + if (more(&p)) return 0; - have_tz = 1; -set: - if (more(&p)) /* make sure there isn't anything else */ + if (datetime_set_type(dt, DATETIME_ABSOLUTE, + DATETIME_YEAR, a.to, a.fracsec)) return 0; - if (datetime_set_type(dt, DATETIME_ABSOLUTE, DATETIME_YEAR, to, fracsec)) + + if (!apply_abs_fields(dt, &a)) return 0; - for (n = DATETIME_YEAR; n <= to; n++) { - switch (n) { - case DATETIME_YEAR: - if (datetime_set_year(dt, year)) - return 0; - break; - case DATETIME_MONTH: - if (datetime_set_month(dt, month)) - return 0; - break; - case DATETIME_DAY: - if (datetime_set_day(dt, day)) - return 0; - break; - case DATETIME_HOUR: - if (datetime_set_hour(dt, hour)) - return 0; - break; - case DATETIME_MINUTE: - if (datetime_set_minute(dt, minute)) - return 0; - break; - case DATETIME_SECOND: - if (datetime_set_second(dt, second)) - return 0; - break; - } - } - if (bc) + + if (a.bc) datetime_set_negative(dt); - if (have_tz && datetime_set_timezone(dt, tz)) + + if (a.have_tz && datetime_set_timezone(dt, a.tz)) return 0; return 1; From 6cd5d8b099e69bd041942f1a669b006e1e530faf Mon Sep 17 00:00:00 2001 From: Neel Date: Mon, 9 Feb 2026 14:47:54 -0500 Subject: [PATCH 11/11] Maintainibility: Refactor this function to reduce its Cognitive Complexity from 35 to the 25 allowed --- lib/datetime/scan.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/lib/datetime/scan.c b/lib/datetime/scan.c index d25ac347f7e..596d6e3a02f 100644 --- a/lib/datetime/scan.c +++ b/lib/datetime/scan.c @@ -24,6 +24,19 @@ static int is_digit(char); static void skip_space(const char **); static int get_int(const char **, int *, int *); static int get_double(const char **, double *, int *, int *); +static int apply_relative_fields(DateTime *dt, int from, int to, + int year, int month, int day, + int hour, int minute, double second); +typedef struct { + int to; + int fracsec; + int tz; + int have_tz; + int bc; + int year, month, day; + int hour, minute; + double second; +} AbsParsed; static int parse_abs_date(const char **p, AbsParsed *a); static int parse_abs_time_and_tz(const char **p, AbsParsed *a); @@ -55,18 +68,6 @@ int datetime_scan(DateTime *dt, const char *buf) static const char *month_names[] = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"}; - -typedef struct { - int to; - int fracsec; - int tz; - int have_tz; - int bc; - int year, month, day; - int hour, minute; - double second; -} AbsParsed; - static int scan_absolute(DateTime *dt, const char *buf) { const char *p = buf; @@ -156,6 +157,19 @@ static int scan_relative(DateTime *dt, const char *buf) return 0; if (datetime_set_type(dt, DATETIME_RELATIVE, from, to, fracsec)) return 0; + if (!apply_relative_fields(dt, from, to, year, month, day, hour, minute, second)) + return 0; + if (neg) + datetime_set_negative(dt); + + return 1; +} +static int apply_relative_fields(DateTime *dt, int from, int to, + int year, int month, int day, + int hour, int minute, double second) +{ + int pos; + for (pos = from; pos <= to; pos++) { switch (pos) { case DATETIME_YEAR: @@ -184,12 +198,11 @@ static int scan_relative(DateTime *dt, const char *buf) break; } } - if (neg) - datetime_set_negative(dt); - return 1; } + + static int is_space(char c) { return (c == ' ' || c == '\t' || c == '\n');