diff --git a/library/GNUmakefile.68k b/library/GNUmakefile.68k index a380f66..981a4d1 100644 --- a/library/GNUmakefile.68k +++ b/library/GNUmakefile.68k @@ -1,5 +1,5 @@ # -# $Id: GNUmakefile.68k,v 1.21 2005-01-24 10:25:46 obarthel Exp $ +# $Id: GNUmakefile.68k,v 1.22 2005-01-26 18:41:38 obarthel Exp $ # # :ts=8 # @@ -376,6 +376,7 @@ C_LIB = \ time_numbertostring.o \ time_strftime.o \ time_time.o \ + time_weekday.o \ unistd_access.o \ unistd_chdir.o \ unistd_chdir_exit.o \ diff --git a/library/GNUmakefile.os4 b/library/GNUmakefile.os4 index 1e6ac9c..fc6514d 100644 --- a/library/GNUmakefile.os4 +++ b/library/GNUmakefile.os4 @@ -1,5 +1,5 @@ # -# $Id: GNUmakefile.os4,v 1.21 2005-01-24 10:25:46 obarthel Exp $ +# $Id: GNUmakefile.os4,v 1.22 2005-01-26 18:41:39 obarthel Exp $ # # :ts=8 # @@ -378,6 +378,7 @@ C_LIB = \ time_numbertostring.o \ time_strftime.o \ time_time.o \ + time_weekday.o \ unistd_access.o \ unistd_chdir.o \ unistd_chdir_exit.o \ diff --git a/library/changes b/library/changes index a5707e6..72cc6fa 100644 --- a/library/changes +++ b/library/changes @@ -14,6 +14,10 @@ UTC. This didn't really work up until now since the time value returned was given as local time. +- Plugged in a different algorithm for calculating the day of the week in + strftime() and asctime_r(). This one isn't sensitive to the effects of + adding/subtracting the local time zone. + c.lib 1.186 (14.1.2005) diff --git a/library/smakefile b/library/smakefile index ef60738..193c7b6 100644 --- a/library/smakefile +++ b/library/smakefile @@ -1,5 +1,5 @@ # -# $Id: smakefile,v 1.16 2005-01-24 10:25:46 obarthel Exp $ +# $Id: smakefile,v 1.17 2005-01-26 18:41:39 obarthel Exp $ # # :ts=8 # @@ -484,7 +484,8 @@ TIME_OBJ = \ time_mktime.o \ time_numbertostring.o \ time_strftime.o \ - time_time.o + time_time.o \ + time_weekday.o UNISTD_OBJ = \ unistd_access.o \ diff --git a/library/time_asctime_r.c b/library/time_asctime_r.c index dd5d88e..a3a90a0 100644 --- a/library/time_asctime_r.c +++ b/library/time_asctime_r.c @@ -1,5 +1,5 @@ /* - * $Id: time_asctime_r.c,v 1.3 2005-01-02 09:07:19 obarthel Exp $ + * $Id: time_asctime_r.c,v 1.4 2005-01-26 18:41:39 obarthel Exp $ * * :ts=4 * @@ -101,21 +101,13 @@ __asctime_r(const struct tm *tm,char * buffer,size_t buffer_size) /* Fill in the week day if it's not in proper range. */ if(tm->tm_wday < 0 || tm->tm_wday > 6) { - struct tm other_tm; - time_t seconds; + /* We use a peculiar algorithm rather than falling back onto + mktime() here in order to avoid trouble with skewed results + owing to time zone influence. */ + copy_tm = (*tm); + copy_tm.tm_wday = __calculate_weekday(tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday); - other_tm = (*tm); - - seconds = mktime(&other_tm); - if(seconds != (time_t)-1) - { - __convert_time(seconds,0,&other_tm); - - copy_tm = (*tm); - copy_tm.tm_wday = other_tm.tm_wday; - - tm = ©_tm; - } + tm = ©_tm; } if(0 <= tm->tm_wday && tm->tm_wday <= 6) diff --git a/library/time_headers.h b/library/time_headers.h index 739d35f..9d2a8eb 100644 --- a/library/time_headers.h +++ b/library/time_headers.h @@ -1,5 +1,5 @@ /* - * $Id: time_headers.h,v 1.6 2005-01-24 10:25:46 obarthel Exp $ + * $Id: time_headers.h,v 1.7 2005-01-26 18:41:39 obarthel Exp $ * * :ts=4 * @@ -95,6 +95,7 @@ extern char * __asctime_r(const struct tm *tm,char * buffer,size_t buffer_size); extern char * __number_to_string(unsigned int number,char * string,size_t max_len,size_t min_len); extern struct tm * __convert_time(ULONG seconds, LONG gmt_offset, struct tm * tm); extern time_t __convert_datestamp_to_time(const struct DateStamp * ds); +extern int __calculate_weekday(int year,int month,int day); /****************************************************************************/ diff --git a/library/time_strftime.c b/library/time_strftime.c index 7618a2d..a78dfe8 100644 --- a/library/time_strftime.c +++ b/library/time_strftime.c @@ -1,5 +1,5 @@ /* - * $Id: time_strftime.c,v 1.3 2005-01-24 10:25:46 obarthel Exp $ + * $Id: time_strftime.c,v 1.4 2005-01-26 18:41:39 obarthel Exp $ * * :ts=4 * @@ -118,20 +118,13 @@ format_date(const char *format,const struct tm *tm,time_t time_value,struct Hook /* Fill in the week day if it's not in proper range. */ if(tm->tm_wday < 0 || tm->tm_wday > 6) { - time_t seconds; + /* We use a peculiar algorithm rather than falling back onto + mktime() here in order to avoid trouble with skewed results + owing to time zone influence. */ + copy_tm = (*tm); + copy_tm.tm_wday = __calculate_weekday(tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday); - other_tm = (*tm); - - seconds = mktime(&other_tm); - if(seconds != (time_t)-1) - { - __convert_time(seconds,0,&other_tm); - - copy_tm = (*tm); - copy_tm.tm_wday = other_tm.tm_wday; - - tm = ©_tm; - } + tm = ©_tm; } while((c = (*format++)) != '\0') diff --git a/library/time_weekday.c b/library/time_weekday.c new file mode 100644 index 0000000..fb5def7 --- /dev/null +++ b/library/time_weekday.c @@ -0,0 +1,86 @@ +/* + * $Id: time_weekday.c,v 1.1 2005-01-26 18:41:39 obarthel Exp $ + * + * :ts=4 + * + * Portable ISO 'C' (1994) runtime library for the Amiga computer + * Copyright (c) 2002-2005 by Olaf Barthel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Neither the name of Olaf Barthel nor the names of contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/****************************************************************************/ + +#ifndef _TIME_HEADERS_H +#include "time_headers.h" +#endif /* _TIME_HEADERS_H */ + +/****************************************************************************/ + +int +__calculate_weekday(int year,int month,int day) +{ + /* This algorithm comes from . */ + static const char month_skew[12] = + { + 0,3,3,6, + 1,4,6,2, + 5,0,3,5 + }; + + int sum; + + /* Subtract 1900 from the year. */ + sum = year - 1900; + + /* To that number, add one fourth of itself, discarding + any remainder. This sum is the year's skew value. */ + sum += sum / 4; + + /* If the month in question is January or February in a leap + year, subtract 1 from the sum. */ + if(month == 1 || month == 2) + { + int leap_year_adjust; + + /* Figure out if the year is a leap year. */ + if((year % 4) != 0) + leap_year_adjust = 0; + else if ((year % 400) == 0) + leap_year_adjust = 1; + else if ((year % 100) == 0) + leap_year_adjust = 0; + else + leap_year_adjust = 1; + + sum -= leap_year_adjust; + } + + /* Add the month's skew value from the table. */ + sum += day + month_skew[month-1]; + + /* The sum is the number of days after Sunday on which the date falls. */ + return(sum % 7); +}