summaryrefslogtreecommitdiff
path: root/libexslt/date.c
diff options
context:
space:
mode:
Diffstat (limited to 'libexslt/date.c')
-rw-r--r--libexslt/date.c109
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;