diff options
Diffstat (limited to 'libexslt/date.c')
-rw-r--r-- | libexslt/date.c | 109 |
1 files changed, 53 insertions, 56 deletions
diff --git a/libexslt/date.c b/libexslt/date.c index 9ca993c6..3af6f7fd 100644 --- a/libexslt/date.c +++ b/libexslt/date.c @@ -47,6 +47,9 @@ #include <string.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif #ifdef HAVE_MATH_H #include <math.h> #endif @@ -667,6 +670,11 @@ exsltDateCreateDate (exsltDateType type) } memset (ret, 0, sizeof(exsltDateVal)); + if (type != XS_DURATION) { + ret->value.date.mon = 1; + ret->value.date.day = 1; + } + if (type != EXSLT_UNKNOWN) ret->type = type; @@ -747,21 +755,55 @@ static exsltDateValPtr exsltDateCurrent (void) { struct tm localTm, gmTm; +#ifndef HAVE_GMTIME_R + struct tm *tb = NULL; +#endif time_t secs; int local_s, gm_s; exsltDateValPtr ret; +#ifdef HAVE_ERRNO_H + char *source_date_epoch; +#endif /* HAVE_ERRNO_H */ + int override = 0; ret = exsltDateCreateDate(XS_DATETIME); if (ret == NULL) return NULL; +#ifdef HAVE_ERRNO_H + /* + * Allow the date and time to be set externally by an exported + * environment variable to enable reproducible builds. + */ + source_date_epoch = getenv("SOURCE_DATE_EPOCH"); + if (source_date_epoch) { + errno = 0; + secs = (time_t) strtol (source_date_epoch, NULL, 10); + if (errno == 0) { +#if HAVE_GMTIME_R + if (gmtime_r(&secs, &localTm) != NULL) + override = 1; +#else + tb = gmtime(&secs); + if (tb != NULL) { + localTm = *tb; + override = 1; + } +#endif + } + } +#endif /* HAVE_ERRNO_H */ + + if (override == 0) { /* get current time */ - secs = time(NULL); + secs = time(NULL); + #if HAVE_LOCALTIME_R - localtime_r(&secs, &localTm); + localtime_r(&secs, &localTm); #else - localTm = *localtime(&secs); + localTm = *localtime(&secs); #endif + } /* get real year, not years since 1900 */ ret->value.date.year = localTm.tm_year + 1900; @@ -778,7 +820,9 @@ exsltDateCurrent (void) #if HAVE_GMTIME_R gmtime_r(&secs, &gmTm); #else - gmTm = *gmtime(&secs); + tb = gmtime(&secs); + if (tb != NULL) + gmTm = *tb; #endif ret->value.date.tz_flag = 0; #if 0 @@ -1278,7 +1322,7 @@ exsltDateFormat (const exsltDateValPtr dt) } if (dt->type & XS_GYEAR) { - xmlChar buf[20], *cur = buf; + xmlChar buf[100], *cur = buf; FORMAT_GYEAR(dt->value.date.year, cur); if (dt->type == XS_GYEARMONTH) { @@ -1395,10 +1439,10 @@ _exsltDateTruncateDate (exsltDateValPtr dt, exsltDateType type) } if ((type & XS_GDAY) != XS_GDAY) - dt->value.date.day = 0; + dt->value.date.day = 1; if ((type & XS_GMONTH) != XS_GMONTH) - dt->value.date.mon = 0; + dt->value.date.mon = 1; if ((type & XS_GYEAR) != XS_GYEAR) dt->value.date.year = 0; @@ -1473,18 +1517,6 @@ _exsltDateAdd (exsltDateValPtr dt, exsltDateValPtr dur) d = &(dt->value.date); u = &(dur->value.dur); - /* normalization */ - if (d->mon == 0) - d->mon = 1; - - /* normalize for time zone offset */ - u->sec -= (d->tzo * 60); /* changed from + to - (bug 153000) */ - d->tzo = 0; - - /* normalization */ - if (d->day == 0) - d->day = 1; - /* month */ carry = d->mon + u->mon; r->mon = (unsigned int)MODULO_RANGE(carry, 1, 13); @@ -1588,40 +1620,6 @@ _exsltDateAdd (exsltDateValPtr dt, exsltDateValPtr dur) } /** - * exsltDateNormalize: - * @dt: an #exsltDateValPtr - * - * Normalize @dt to GMT time. - * - */ -static void -exsltDateNormalize (exsltDateValPtr dt) -{ - exsltDateValPtr dur, tmp; - - if (dt == NULL) - return; - - if (((dt->type & XS_TIME) != XS_TIME) && (dt->value.date.tzo == 0)) - return; - - dur = exsltDateCreateDate(XS_DURATION); - if (dur == NULL) - return; - - tmp = _exsltDateAdd(dt, dur); - if (tmp == NULL) - return; - - memcpy(dt, tmp, sizeof(exsltDateVal)); - - exsltDateFreeDate(tmp); - exsltDateFreeDate(dur); - - dt->value.date.tzo = 0; -} - -/** * _exsltDateDifference: * @x: an #exsltDateValPtr * @y: an #exsltDateValPtr @@ -1645,9 +1643,6 @@ _exsltDateDifference (exsltDateValPtr x, exsltDateValPtr y, int flag) ((y->type < XS_GYEAR) || (y->type > XS_DATETIME))) return NULL; - exsltDateNormalize(x); - exsltDateNormalize(y); - /* * the operand with the most specific format must be converted to * the same type as the operand with the least specific format. @@ -1675,6 +1670,8 @@ _exsltDateDifference (exsltDateValPtr x, exsltDateValPtr y, int flag) _exsltDateCastYMToDays(x); ret->value.dur.day += y->value.date.day - x->value.date.day; ret->value.dur.sec = TIME_TO_NUMBER(y) - TIME_TO_NUMBER(x); + ret->value.dur.sec += (x->value.date.tzo - y->value.date.tzo) * + SECS_PER_MIN; if (ret->value.dur.day > 0.0 && ret->value.dur.sec < 0.0) { ret->value.dur.day -= 1; ret->value.dur.sec = ret->value.dur.sec + SECS_PER_DAY; |