diff options
author | Jeff Johnston <jjohnstn@redhat.com> | 2002-04-17 21:23:31 +0000 |
---|---|---|
committer | Jeff Johnston <jjohnstn@redhat.com> | 2002-04-17 21:23:31 +0000 |
commit | 10d002160949c985e6f99fb8d647d5e3c67ef554 (patch) | |
tree | 6ffe46b0b090120c2a251ffc2ce19574fb5f1dfb /newlib/libc/time/mktm_r.c | |
parent | a26c50352b4db457813ef86fb053bd838d310d30 (diff) | |
download | cygnal-10d002160949c985e6f99fb8d647d5e3c67ef554.tar.gz cygnal-10d002160949c985e6f99fb8d647d5e3c67ef554.tar.bz2 cygnal-10d002160949c985e6f99fb8d647d5e3c67ef554.zip |
2002-04-17 Jeff Johnston <jjohnstn@redhat.com>
* libc/include/time.h (tzset, _tzset_r): Added prototypes.
(strptime): Moved prototype to be within !__STRICT_ANSI__.
(_tzname, _daylight, _timezone): No long __CYGWIN__ only.
(tzname): Defined for all platforms.
(daylight, timezone): Defined only for CYGWIN.
* libc/sys/linux/machine/i386/crt0.c: Add call to tzset() after
environment set up.
* libc/stdlib/setenv_r.c (_setenv_r): Call tzset() if the TZ
environment variable is set.
* libc/time/Makefile.am: Add support for tzset.c, tzlock.c, and
tzset_r.c.
* libc/time/Makefile.in: Regenerated.
* libc/time/gmtime.c (gmtime): Changed to call gmtime_r.
* libc/time/gmtime_r.c (gmtime_r): Changed to call _mktm_r.
* libc/time/lcltime_r.c (lcltime_r): Ditto.
* libc/time/local.h: New local header file.
* libc/time/mktime.c (mktime): Add timezone support.
* libc/time/mktm_r.c: New file which is the common engine
for gmtime_r and lcltime_r. This code has timezone support.
* libc/time/strftime.c (strftime): Add %Z timezone support.
* libc/time/tzlock.c: New file containing timezone lock stubs.
* libc/time/tzset.c: New file containing tzset() routine.
* libc/time/tzset_r.c: New file containing _tzset_r and
internal routine for calculating timezone changes for specified year.
Diffstat (limited to 'newlib/libc/time/mktm_r.c')
-rw-r--r-- | newlib/libc/time/mktm_r.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/newlib/libc/time/mktm_r.c b/newlib/libc/time/mktm_r.c new file mode 100644 index 000000000..4fdfb9b7b --- /dev/null +++ b/newlib/libc/time/mktm_r.c @@ -0,0 +1,248 @@ +/* + * mktm_r.c + * Original Author: Adapted from tzcode maintained by Arthur David Olson. + * Modifications: Changed to mktm_r and added __tzcalc_limits - 04/10/02, Jeff Johnston + * + * Converts the calendar time pointed to by tim_p into a broken-down time + * expressed as local time. Returns a pointer to a structure containing the + * broken-down time. + */ + +#include <stdlib.h> +#include <time.h> +#include "local.h" + +static _CONST int mon_lengths[2][MONSPERYEAR] = { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} +} ; + +static _CONST int year_lengths[2] = { + 365, + 366 +} ; + +struct tm * +_DEFUN (_mktm_r, (tim_p, res, is_gmtime), + _CONST time_t * tim_p _AND + struct tm *res _AND + int is_gmtime) +{ + long days, rem; + time_t lcltime; + int i; + int y; + int yleap; + _CONST int *ip; + + /* base decision about std/dst time on current time */ + lcltime = *tim_p; + + days = ((long)lcltime) / SECSPERDAY; + rem = ((long)lcltime) % SECSPERDAY; + while (rem < 0) + { + rem += SECSPERDAY; + --days; + } + while (rem >= SECSPERDAY) + { + rem -= SECSPERDAY; + ++days; + } + + /* compute hour, min, and sec */ + res->tm_hour = (int) (rem / SECSPERHOUR); + rem %= SECSPERHOUR; + res->tm_min = (int) (rem / SECSPERMIN); + res->tm_sec = (int) (rem % SECSPERMIN); + + /* compute day of week */ + if ((res->tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0) + res->tm_wday += DAYSPERWEEK; + + /* compute year & day of year */ + y = EPOCH_YEAR; + if (days >= 0) + { + for (;;) + { + yleap = isleap(y); + if (days < year_lengths[yleap]) + break; + y++; + days -= year_lengths[yleap]; + } + } + else + { + do + { + --y; + yleap = isleap(y); + days += year_lengths[yleap]; + } while (days < 0); + } + + res->tm_year = y - YEAR_BASE; + res->tm_yday = days; + ip = mon_lengths[yleap]; + for (res->tm_mon = 0; days >= ip[res->tm_mon]; ++res->tm_mon) + days -= ip[res->tm_mon]; + res->tm_mday = days + 1; + + if (!is_gmtime) + { + int offset; + int hours, mins, secs; + + TZ_LOCK; + if (_daylight) + { + if (y == __tzyear || __tzcalc_limits (y)) + res->tm_isdst = (__tznorth + ? (*tim_p >= __tzrule[0].change && *tim_p < __tzrule[1].change) + : (*tim_p >= __tzrule[0].change || *tim_p < __tzrule[1].change)); + else + res->tm_isdst = -1; + } + else + res->tm_isdst = 0; + + offset = (res->tm_isdst == 1 ? __tzrule[1].offset : __tzrule[0].offset); + + hours = offset / SECSPERHOUR; + offset = offset % SECSPERHOUR; + + mins = offset / SECSPERMIN; + secs = offset % SECSPERMIN; + + res->tm_sec -= secs; + res->tm_min -= mins; + res->tm_hour -= hours; + + if (res->tm_sec >= SECSPERMIN) + { + res->tm_min += 1; + res->tm_sec -= SECSPERMIN; + } + else if (res->tm_sec < 0) + { + res->tm_min -= 1; + res->tm_sec += SECSPERMIN; + } + if (res->tm_min >= MINSPERHOUR) + { + res->tm_hour += 1; + res->tm_min -= MINSPERHOUR; + } + else if (res->tm_min < 0) + { + res->tm_hour -= 1; + res->tm_min += MINSPERHOUR; + } + if (res->tm_hour >= HOURSPERDAY) + { + ++res->tm_yday; + ++res->tm_wday; + if (res->tm_wday > 6) + res->tm_wday = 0; + ++res->tm_mday; + res->tm_hour -= HOURSPERDAY; + if (res->tm_mday >= ip[res->tm_mon]) + { + res->tm_mday -= ip[res->tm_mon] - 1; + res->tm_mon += 1; + if (res->tm_mon == 12) + { + res->tm_mon = 0; + res->tm_year += 1; + res->tm_yday = 0; + } + } + } + else if (res->tm_hour < 0) + { + res->tm_yday -= 1; + res->tm_wday -= 1; + if (res->tm_wday < 0) + res->tm_wday = 6; + res->tm_mday -= 1; + res->tm_hour += 24; + if (res->tm_mday == 0) + { + res->tm_mon -= 1; + if (res->tm_mon < 0) + { + res->tm_mon = 11; + res->tm_year -= 1; + res->tm_yday = 365 + isleap(res->tm_year); + } + res->tm_mday = ip[res->tm_mon]; + } + } + TZ_UNLOCK; + } + else + res->tm_isdst = 0; + + return (res); +} + +int +_DEFUN (__tzcalc_limits, (year), + int year) +{ + int days, year_days, years; + int i, j; + + if (year < EPOCH_YEAR) + return 0; + + __tzyear = year; + + years = (year - EPOCH_YEAR); + + year_days = years * 365 + + (years - 1 + EPOCH_YEARS_SINCE_LEAP) / 4 - (years - 1 + EPOCH_YEARS_SINCE_CENTURY) / 100 + + (years - 1 + EPOCH_YEARS_SINCE_LEAP_CENTURY) / 400; + + for (i = 0; i < 2; ++i) + { + if (__tzrule[i].ch == 'J') + days = year_days + __tzrule[i].d + (isleap(year) && __tzrule[i].d >= 60); + else if (__tzrule[i].ch == 'D') + days = year_days + __tzrule[i].d; + else + { + int yleap = isleap(year); + int m_day, m_wday, wday_diff; + _CONST int *ip = mon_lengths[yleap]; + + days = year_days; + + for (j = 1; j < __tzrule[i].m; ++j) + days += ip[j-1]; + + m_wday = (EPOCH_WDAY + days) % DAYSPERWEEK; + + wday_diff = __tzrule[i].d - m_wday; + if (wday_diff < 0) + wday_diff += DAYSPERWEEK; + m_day = (__tzrule[i].n - 1) * DAYSPERWEEK + wday_diff; + + while (m_day >= ip[j]) + m_day -= DAYSPERWEEK; + + days += m_day; + } + + /* store the change-over time in GMT form by adding offset */ + __tzrule[i].change = days * SECSPERDAY + __tzrule[i].s + __tzrule[i].offset; + } + + __tznorth = (__tzrule[0].change < __tzrule[1].change); + + return 1; +} + |