This is the mail archive of the
newlib@sources.redhat.com
mailing list for the newlib project.
strftime followup
- From: Eric Blake <ebb9 at byu dot net>
- To: newlib at sources dot redhat dot com
- Date: Fri, 25 Feb 2005 07:20:20 -0700
- Subject: strftime followup
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Oops, I had an incorrect statement in the docs (not all years have 53
weeks), and missed a case of negative years (the expansion of %x) the
first time around. Meanwhile, since __tzrule.offset[0] is supposed to
match _timezone, I made sure the time functions don't overflow
architectures with a 16-bit int when a 32-bit long is required.
2005-02-24 Eric Blake <ebb9@byu.net>
* libc/include/time.h (__tzrule_struct): Make offset long, since
a 16-bit int overflows on a 12-hour offset.
* libc/sys/linux/include/time.h: Ditto.
* libc/time/mktime.c (mktime): Use new type of __tzrule.offset.
* libc/time/mktm_r.c: Ditto.
* libc/time/gettzinfo.c: Ditto.
* libc/time/strftime.c (strftime): Fix '%x' to deal with negative
years. Fix '%z' to use long, not int.
- --
Life is short - so eat dessert first!
Eric Blake ebb9@byu.net
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org
iD8DBQFCHzQk84KuGfSFAYARAk6LAJsFqrw7io5mJFDoBOIMaFhAqwWK2ACfYTXY
in7uj3hkEsVlV0F0Z9uulIY=
=v7+A
-----END PGP SIGNATURE-----
Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/newlib/ChangeLog,v
retrieving revision 1.759
diff -u -p -r1.759 ChangeLog
Index: libc/include/time.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/include/time.h,v
retrieving revision 1.15
diff -u -p -r1.15 time.h
--- libc/include/time.h 23 Feb 2005 22:20:55 -0000 1.15
+++ libc/include/time.h 25 Feb 2005 04:55:13 -0000
@@ -79,7 +79,7 @@ typedef struct __tzrule_struct
int d;
int s;
time_t change;
- int offset;
+ long offset; /* Match type of _timezone. */
} __tzrule_type;
typedef struct __tzinfo_struct
Index: libc/sys/linux/include/time.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/sys/linux/include/time.h,v
retrieving revision 1.4
diff -u -p -r1.4 time.h
--- libc/sys/linux/include/time.h 23 Feb 2005 19:08:57 -0000 1.4
+++ libc/sys/linux/include/time.h 25 Feb 2005 04:55:14 -0000
@@ -92,7 +92,7 @@ typedef struct __tzrule_struct
int d;
int s;
time_t change;
- int offset;
+ long offset; /* Match type of _timezone. */
} __tzrule_type;
typedef struct __tzinfo_struct
Index: libc/time/gettzinfo.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/time/gettzinfo.c,v
retrieving revision 1.1
diff -u -p -r1.1 gettzinfo.c
--- libc/time/gettzinfo.c 23 Feb 2005 19:08:58 -0000 1.1
+++ libc/time/gettzinfo.c 25 Feb 2005 04:55:14 -0000
@@ -3,8 +3,8 @@
/* Shared timezone information for libc/time functions. */
static __tzinfo_type tzinfo = {1, 0,
- { {'J', 0, 0, 0, 0, (time_t)0, 0 },
- {'J', 0, 0, 0, 0, (time_t)0, 0 }
+ { {'J', 0, 0, 0, 0, (time_t)0, 0L },
+ {'J', 0, 0, 0, 0, (time_t)0, 0L }
}
};
Index: libc/time/mktime.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/time/mktime.c,v
retrieving revision 1.4
diff -u -p -r1.4 mktime.c
--- libc/time/mktime.c 23 Feb 2005 19:08:58 -0000 1.4
+++ libc/time/mktime.c 25 Feb 2005 04:55:14 -0000
@@ -211,9 +211,12 @@ mktime (tim_p)
{
/* calculate start of dst in dst local time and
start of std in both std local time and dst local time */
- time_t startdst_dst = tz->__tzrule[0].change - tz->__tzrule[1].offset;
- time_t startstd_dst = tz->__tzrule[1].change - tz->__tzrule[1].offset;
- time_t startstd_std = tz->__tzrule[1].change - tz->__tzrule[0].offset;
+ time_t startdst_dst = tz->__tzrule[0].change
+ - (time_t) tz->__tzrule[1].offset;
+ time_t startstd_dst = tz->__tzrule[1].change
+ - (time_t) tz->__tzrule[1].offset;
+ time_t startstd_std = tz->__tzrule[1].change
+ - (time_t) tz->__tzrule[0].offset;
/* if the time is in the overlap between dst and std local times */
if (tim >= startstd_std && tim < startstd_dst)
; /* we let user decide or leave as -1 */
@@ -226,8 +229,12 @@ mktime (tim_p)
if ((isdst ^ tim_p->tm_isdst) == 1)
{
/* we either subtract or add the difference between
- time zone offsets, depending on which way the user got it wrong */
- int diff = tz->__tzrule[0].offset - tz->__tzrule[1].offset;
+ time zone offsets, depending on which way the user got it
+ wrong. The diff is typically one hour, or 3600 seconds,
+ and should fit in a 16-bit int, even though offset
+ is a long to accomodate 12 hours. */
+ int diff = (int) (tz->__tzrule[0].offset
+ - tz->__tzrule[1].offset);
if (!isdst)
diff = -diff;
tim_p->tm_sec += diff;
@@ -240,9 +247,9 @@ mktime (tim_p)
/* add appropriate offset to put time in gmt format */
if (isdst == 1)
- tim += tz->__tzrule[1].offset;
+ tim += (time_t) tz->__tzrule[1].offset;
else /* otherwise assume std time */
- tim += tz->__tzrule[0].offset;
+ tim += (time_t) tz->__tzrule[0].offset;
/* reset isdst flag to what we have calculated */
tim_p->tm_isdst = isdst;
Index: libc/time/mktm_r.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/time/mktm_r.c,v
retrieving revision 1.3
diff -u -p -r1.3 mktm_r.c
--- libc/time/mktm_r.c 23 Feb 2005 19:08:58 -0000 1.3
+++ libc/time/mktm_r.c 25 Feb 2005 04:55:14 -0000
@@ -95,7 +95,7 @@ _DEFUN (_mktm_r, (tim_p, res, is_gmtime)
if (!is_gmtime)
{
- int offset;
+ long offset;
int hours, mins, secs;
TZ_LOCK;
@@ -117,11 +117,11 @@ _DEFUN (_mktm_r, (tim_p, res, is_gmtime)
? tz->__tzrule[1].offset
: tz->__tzrule[0].offset);
- hours = offset / SECSPERHOUR;
+ hours = (int) (offset / SECSPERHOUR);
offset = offset % SECSPERHOUR;
- mins = offset / SECSPERMIN;
- secs = offset % SECSPERMIN;
+ mins = (int) (offset / SECSPERMIN);
+ secs = (int) (offset % SECSPERMIN);
res->tm_sec -= secs;
res->tm_min -= mins;
Index: libc/time/strftime.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/time/strftime.c,v
retrieving revision 1.9
diff -u -p -r1.9 strftime.c
--- libc/time/strftime.c 24 Feb 2005 06:14:44 -0000 1.9
+++ libc/time/strftime.c 25 Feb 2005 04:55:16 -0000
@@ -1,6 +1,7 @@
/*
* strftime.c
* Original Author: G. Haley
+ * Additions from: Eric Blake
*
* Places characters into the array pointed to by s as controlled by the string
* pointed to by format. If the total number of resulting characters including
@@ -102,9 +103,9 @@ The last two digits of the week-based ye
o %G
The week-based year. In the ISO 8601:2000 calendar, week 1 of the year
includes January 4th, and begin on Mondays. Therefore, if January 1st,
-2nd, or 3rd falls on a Sunday, that day and earlier belong to week 53
-of the previous year; and if December 29th, 30th, or 31st falls on
-Monday, that day and later belong to week 1 of the next year. For
+2nd, or 3rd falls on a Sunday, that day and earlier belong to the last
+week of the previous year; and if December 29th, 30th, or 31st falls
+on Monday, that day and later belong to week 1 of the next year. For
consistency with %Y, it always has at least four characters.
Example: "%G" for Saturday 2nd January 1999 gives "1998", and for
Tuesday 30th December 1997 gives "1998". [tm_year, tm_wday, tm_yday]
@@ -447,7 +448,8 @@ _DEFUN (strftime, (s, maxsize, format, t
{
sprintf (&s[count], "%.2d/%.2d/%.2d",
tim_p->tm_mon + 1, tim_p->tm_mday,
- (tim_p->tm_year % 100 + 100) % 100);
+ tim_p->tm_year >= 0 ? tim_p->tm_year % 100
+ : abs (tim_p->tm_year + YEAR_BASE) % 100);
count += 8;
}
else
@@ -756,7 +758,7 @@ _DEFUN (strftime, (s, maxsize, format, t
{
if (count < maxsize - 5)
{
- int offset;
+ long offset;
__tzinfo_type *tz = __gettzinfo ();
TZ_LOCK;
/* The sign of this is exactly opposite the envvar TZ. We
@@ -764,8 +766,8 @@ _DEFUN (strftime, (s, maxsize, format, t
but have to use __tzrule for daylight savings. */
offset = -tz->__tzrule[tim_p->tm_isdst > 0].offset;
TZ_UNLOCK;
- sprintf (&s[count], "%+03ld%.2d", offset / SECSPERHOUR,
- abs (offset / SECSPERMIN) % 60);
+ sprintf (&s[count], "%+03ld%.2ld", offset / SECSPERHOUR,
+ labs (offset / SECSPERMIN) % 60L);
count += 5;
}
else