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.
This commit is contained in:
parent
a26c50352b
commit
10d0021609
|
@ -1,3 +1,30 @@
|
|||
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.
|
||||
|
||||
2002-04-17 Thomas Fitzsimmons <fitzsim@redhat.com>
|
||||
|
||||
* configure.in (CRT0_DIR): Set to libc/.
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#define _TIME_H_
|
||||
|
||||
#include "_ansi.h"
|
||||
#include <sys/reent.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -55,22 +56,29 @@ struct tm *_EXFUN(gmtime, (const time_t *_timer));
|
|||
struct tm *_EXFUN(localtime,(const time_t *_timer));
|
||||
#endif
|
||||
size_t _EXFUN(strftime, (char *_s, size_t _maxsize, const char *_fmt, const struct tm *_t));
|
||||
char *_EXFUN(strptime, (const char *, const char *, struct tm *));
|
||||
|
||||
char *_EXFUN(asctime_r, (const struct tm *, char *));
|
||||
char *_EXFUN(ctime_r, (const time_t *, char *));
|
||||
struct tm *_EXFUN(gmtime_r, (const time_t *, struct tm *));
|
||||
struct tm *_EXFUN(localtime_r, (const time_t *, struct tm *));
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#ifndef __STRICT_ANSI__
|
||||
char *_EXFUN(strptime, (const char *, const char *, struct tm *));
|
||||
_VOID _EXFUN(tzset, (_VOID));
|
||||
_VOID _EXFUN(_tzset_r, (struct _reent *));
|
||||
|
||||
/* defines for the opengroup specifications Derived from Issue 1 of the SVID. */
|
||||
extern __IMPORT time_t _timezone;
|
||||
extern __IMPORT int _daylight;
|
||||
extern __IMPORT char *_tzname[2];
|
||||
/* defines for the opengroup specifications Derived from Issue 1 of the SVID. */
|
||||
|
||||
/* POSIX defines the external tzname being defined in time.h */
|
||||
#ifndef tzname
|
||||
#define tzname _tzname
|
||||
#endif
|
||||
|
||||
/* CYGWIN also exposes daylight and timezone in the name space */
|
||||
#ifdef __CYGWIN__
|
||||
#ifndef daylight
|
||||
#define daylight _daylight
|
||||
#endif
|
||||
|
@ -81,13 +89,11 @@ extern __IMPORT char *_tzname[2];
|
|||
#else
|
||||
char *_EXFUN(timezone, (void));
|
||||
#endif
|
||||
void _EXFUN(tzset, (void));
|
||||
#endif
|
||||
#endif /* __CYGWIN__ */
|
||||
#endif /* !__STRICT_ANSI__ */
|
||||
|
||||
#include <sys/features.h>
|
||||
|
||||
|
||||
#if defined(_POSIX_TIMERS)
|
||||
|
||||
#include <signal.h>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* This file may have been modified by DJ Delorie (Jan 1991). If so,
|
||||
** these modifications are Copyright (C) 1991 DJ Delorie
|
||||
** these modifications are Copyright (C) 1991 DJ Delorie.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -26,6 +26,7 @@
|
|||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "envlock.h"
|
||||
|
||||
extern char **environ;
|
||||
|
@ -69,8 +70,11 @@ _DEFUN (_setenv_r, (reent_ptr, name, value, rewrite),
|
|||
}
|
||||
if (strlen (C) >= l_value)
|
||||
{ /* old larger; copy over */
|
||||
while ((*C++ = *value++) != 0);
|
||||
while ((*C++ = *value++) != 0);
|
||||
ENV_UNLOCK;
|
||||
/* if we are changing the TZ environment variable, update timezone info */
|
||||
if (strcmp (name, "TZ") == 0)
|
||||
tzset ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -117,6 +121,10 @@ _DEFUN (_setenv_r, (reent_ptr, name, value, rewrite),
|
|||
|
||||
ENV_UNLOCK;
|
||||
|
||||
/* if we are setting the TZ environment variable, update timezone info */
|
||||
if (strcmp (name, "TZ") == 0)
|
||||
tzset ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
extern char **environ;
|
||||
|
@ -28,5 +29,6 @@ void _start(int args)
|
|||
char **argv = (char **) (params+1);
|
||||
|
||||
environ = argv+argc+1;
|
||||
tzset(); /* initialize timezone info */
|
||||
exit(main(argc,argv,environ));
|
||||
}
|
||||
|
|
|
@ -16,9 +16,13 @@ LIB_SOURCES = \
|
|||
lcltime.c \
|
||||
lcltime_r.c \
|
||||
mktime.c \
|
||||
mktm_r.c \
|
||||
strftime.c \
|
||||
strptime.c \
|
||||
time.c
|
||||
strptime.c \
|
||||
time.c \
|
||||
tzlock.c \
|
||||
tzset.c \
|
||||
tzset_r.c
|
||||
|
||||
libtime_la_LDFLAGS = -Xcompiler -nostdlib
|
||||
|
||||
|
@ -43,7 +47,9 @@ CHEWOUT_FILES = \
|
|||
lcltime.def \
|
||||
mktime.def \
|
||||
strftime.def \
|
||||
time.def
|
||||
time.def \
|
||||
tzlock.def \
|
||||
tzset.def
|
||||
|
||||
SUFFIXES = .def
|
||||
|
||||
|
|
|
@ -107,9 +107,13 @@ LIB_SOURCES = \
|
|||
lcltime.c \
|
||||
lcltime_r.c \
|
||||
mktime.c \
|
||||
mktm_r.c \
|
||||
strftime.c \
|
||||
strptime.c \
|
||||
time.c
|
||||
strptime.c \
|
||||
time.c \
|
||||
tzlock.c \
|
||||
tzset.c \
|
||||
tzset_r.c
|
||||
|
||||
|
||||
libtime_la_LDFLAGS = -Xcompiler -nostdlib
|
||||
|
@ -130,7 +134,9 @@ CHEWOUT_FILES = \
|
|||
lcltime.def \
|
||||
mktime.def \
|
||||
strftime.def \
|
||||
time.def
|
||||
time.def \
|
||||
tzlock.def \
|
||||
tzset.def
|
||||
|
||||
|
||||
SUFFIXES = .def
|
||||
|
@ -151,15 +157,16 @@ LIBS = @LIBS@
|
|||
lib_a_LIBADD =
|
||||
@USE_LIBTOOL_FALSE@lib_a_OBJECTS = asctime.o asctime_r.o clock.o \
|
||||
@USE_LIBTOOL_FALSE@ctime.o ctime_r.o difftime.o gmtime.o gmtime_r.o \
|
||||
@USE_LIBTOOL_FALSE@lcltime.o lcltime_r.o mktime.o strftime.o strptime.o \
|
||||
@USE_LIBTOOL_FALSE@time.o
|
||||
@USE_LIBTOOL_FALSE@lcltime.o lcltime_r.o mktime.o mktm_r.o strftime.o \
|
||||
@USE_LIBTOOL_FALSE@strptime.o time.o tzlock.o tzset.o tzset_r.o
|
||||
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
||||
|
||||
libtime_la_LIBADD =
|
||||
@USE_LIBTOOL_TRUE@libtime_la_OBJECTS = asctime.lo asctime_r.lo clock.lo \
|
||||
@USE_LIBTOOL_TRUE@ctime.lo ctime_r.lo difftime.lo gmtime.lo gmtime_r.lo \
|
||||
@USE_LIBTOOL_TRUE@lcltime.lo lcltime_r.lo mktime.lo strftime.lo \
|
||||
@USE_LIBTOOL_TRUE@strptime.lo time.lo
|
||||
@USE_LIBTOOL_TRUE@lcltime.lo lcltime_r.lo mktime.lo mktm_r.lo \
|
||||
@USE_LIBTOOL_TRUE@strftime.lo strptime.lo time.lo tzlock.lo tzset.lo \
|
||||
@USE_LIBTOOL_TRUE@tzset_r.lo
|
||||
CFLAGS = @CFLAGS@
|
||||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
|
|
|
@ -59,9 +59,8 @@ struct tm *
|
|||
_DEFUN (gmtime, (tim_p),
|
||||
_CONST time_t * tim_p)
|
||||
{
|
||||
time_t tim = *tim_p + _GMT_OFFSET;
|
||||
|
||||
return (localtime (&tim));
|
||||
_REENT_CHECK_TM(_REENT);
|
||||
return gmtime_r (tim_p, (struct tm *)_REENT_TM(_REENT));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,15 +3,12 @@
|
|||
*/
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define _GMT_OFFSET 0
|
||||
#include "local.h"
|
||||
|
||||
struct tm *
|
||||
_DEFUN (gmtime_r, (tim_p, res),
|
||||
_CONST time_t * tim_p _AND
|
||||
struct tm *res)
|
||||
{
|
||||
time_t tim = *tim_p + _GMT_OFFSET;
|
||||
|
||||
return (localtime_r (&tim, res));
|
||||
return (_mktm_r (tim_p, res, 1));
|
||||
}
|
||||
|
|
|
@ -1,104 +1,18 @@
|
|||
/*
|
||||
* localtime_r.c
|
||||
* Original Author: Adapted from tzcode maintained by Arthur David Olson.
|
||||
*
|
||||
* 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>
|
||||
|
||||
#define SECSPERMIN 60L
|
||||
#define MINSPERHOUR 60L
|
||||
#define HOURSPERDAY 24L
|
||||
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
|
||||
#define SECSPERDAY (SECSPERHOUR * HOURSPERDAY)
|
||||
#define DAYSPERWEEK 7
|
||||
#define MONSPERYEAR 12
|
||||
|
||||
#define YEAR_BASE 1900
|
||||
#define EPOCH_YEAR 1970
|
||||
#define EPOCH_WDAY 4
|
||||
|
||||
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
|
||||
|
||||
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
|
||||
} ;
|
||||
#include "local.h"
|
||||
|
||||
struct tm *
|
||||
_DEFUN (localtime_r, (tim_p, res),
|
||||
_CONST time_t * tim_p _AND
|
||||
struct tm *res)
|
||||
{
|
||||
long days, rem;
|
||||
int y;
|
||||
int yleap;
|
||||
_CONST int *ip;
|
||||
|
||||
days = ((long) *tim_p) / SECSPERDAY;
|
||||
rem = ((long) *tim_p) % 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;
|
||||
|
||||
/* set daylight saving time flag */
|
||||
res->tm_isdst = -1;
|
||||
|
||||
return (res);
|
||||
return _mktm_r (tim_p, res, 0);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/* local header used by libc/time routines */
|
||||
#include <_ansi.h>
|
||||
#include <time.h>
|
||||
|
||||
#define SECSPERMIN 60L
|
||||
#define MINSPERHOUR 60L
|
||||
#define HOURSPERDAY 24L
|
||||
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
|
||||
#define SECSPERDAY (SECSPERHOUR * HOURSPERDAY)
|
||||
#define DAYSPERWEEK 7
|
||||
#define MONSPERYEAR 12
|
||||
|
||||
#define YEAR_BASE 1900
|
||||
#define EPOCH_YEAR 1970
|
||||
#define EPOCH_WDAY 4
|
||||
#define EPOCH_YEARS_SINCE_LEAP 2
|
||||
#define EPOCH_YEARS_SINCE_CENTURY 70
|
||||
#define EPOCH_YEARS_SINCE_LEAP_CENTURY 370
|
||||
|
||||
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
|
||||
|
||||
extern time_t __tzstart_std;
|
||||
extern time_t __tzstart_dst;
|
||||
extern int __tznorth;
|
||||
extern int __tzyear;
|
||||
|
||||
typedef struct __tzrule_struct
|
||||
{
|
||||
char ch;
|
||||
int m;
|
||||
int n;
|
||||
int d;
|
||||
int s;
|
||||
time_t change;
|
||||
int offset;
|
||||
} __tzrule_type;
|
||||
|
||||
extern __tzrule_type __tzrule[2];
|
||||
|
||||
struct tm * _EXFUN (_mktm_r, (_CONST time_t *, struct tm *, int __is_gmtime));
|
||||
int _EXFUN (__tzcalc_limits, (int __year));
|
||||
|
||||
/* locks for multi-threading */
|
||||
#ifdef __SINGLE_THREAD__
|
||||
#define TZ_LOCK
|
||||
#define TZ_UNLOCK
|
||||
#else
|
||||
#define TZ_LOCK __tz_lock()
|
||||
#define TZ_UNLOCK __tz_unlock()
|
||||
#endif
|
||||
|
||||
void _EXFUN(__tz_lock,(_VOID));
|
||||
void _EXFUN(__tz_unlock,(_VOID));
|
||||
|
|
@ -47,6 +47,7 @@ ANSI C requires <<mktime>>.
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "local.h"
|
||||
|
||||
#define _SEC_IN_MINUTE 60L
|
||||
#define _SEC_IN_HOUR 3600L
|
||||
|
@ -156,7 +157,7 @@ mktime (tim_p)
|
|||
{
|
||||
time_t tim = 0;
|
||||
long days = 0;
|
||||
int year;
|
||||
int year, isdst;
|
||||
|
||||
/* validate structure */
|
||||
validate_structure (tim_p);
|
||||
|
@ -200,5 +201,50 @@ mktime (tim_p)
|
|||
/* compute total seconds */
|
||||
tim += (days * _SEC_IN_DAY);
|
||||
|
||||
isdst = tim_p->tm_isdst;
|
||||
|
||||
if (_daylight)
|
||||
{
|
||||
int y = tim_p->tm_year + YEAR_BASE;
|
||||
if (y == __tzyear || __tzcalc_limits (y))
|
||||
{
|
||||
/* 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 = __tzrule[0].change - __tzrule[1].offset;
|
||||
time_t startstd_dst = __tzrule[1].change - __tzrule[1].offset;
|
||||
time_t startstd_std = __tzrule[1].change - __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 */
|
||||
else
|
||||
{
|
||||
isdst = (__tznorth
|
||||
? (tim >= startdst_dst && tim < startstd_std)
|
||||
: (tim >= startdst_dst || tim < startstd_std));
|
||||
/* if user committed and was wrong, perform correction */
|
||||
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 = __tzrule[0].offset - __tzrule[1].offset;
|
||||
if (!isdst)
|
||||
diff = -diff;
|
||||
tim_p->tm_sec += diff;
|
||||
validate_structure (tim_p);
|
||||
tim += diff; /* we also need to correct our current time calculation */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add appropriate offset to put time in gmt format */
|
||||
if (isdst == 1)
|
||||
tim += __tzrule[1].offset;
|
||||
else /* otherwise assume std time */
|
||||
tim += __tzrule[0].offset;
|
||||
|
||||
/* reset isdst flag to what we have calculated */
|
||||
tim_p->tm_isdst = isdst;
|
||||
|
||||
return tim;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -115,9 +115,9 @@ o %Y
|
|||
The full year, formatted with four digits to include the century.
|
||||
|
||||
o %Z
|
||||
Defined by ANSI C as eliciting the time zone if available; it is not
|
||||
available in this implementation (which accepts `<<%Z>>' but generates
|
||||
no output for it).
|
||||
The time zone name. If tm_isdst is -1, no output is generated.
|
||||
Otherwise, the time zone name based on the TZ environment variable
|
||||
is used.
|
||||
|
||||
o %%
|
||||
A single character, `<<%>>'.
|
||||
|
@ -142,6 +142,7 @@ ANSI C requires <<strftime>>, but does not specify the contents of
|
|||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "local.h"
|
||||
|
||||
static _CONST int dname_len[7] =
|
||||
{6, 6, 7, 9, 8, 6, 8};
|
||||
|
@ -426,6 +427,23 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
|
|||
return 0;
|
||||
break;
|
||||
case 'Z':
|
||||
if (tim_p->tm_isdst >= 0)
|
||||
{
|
||||
int size;
|
||||
TZ_LOCK;
|
||||
size = strlen(_tzname[tim_p->tm_isdst]);
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (count < maxsize - 1)
|
||||
s[count++] = _tzname[tim_p->tm_isdst][i];
|
||||
else
|
||||
{
|
||||
TZ_UNLOCK;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
TZ_UNLOCK;
|
||||
}
|
||||
break;
|
||||
case '%':
|
||||
if (count < maxsize - 1)
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
FUNCTION
|
||||
<<__tz_lock>>, <<__tz_unlock>>--lock time zone global variables
|
||||
|
||||
INDEX
|
||||
__tz_lock
|
||||
INDEX
|
||||
__tz_unlock
|
||||
|
||||
ANSI_SYNOPSIS
|
||||
#include "local.h"
|
||||
void __tz_lock (void);
|
||||
void __tz_unlock (void);
|
||||
|
||||
TRAD_SYNOPSIS
|
||||
void __tz_lock();
|
||||
void __tz_unlock();
|
||||
|
||||
DESCRIPTION
|
||||
The <<tzset>> facility functions call these functions when they need
|
||||
to ensure the values of global variables. The version of these routines supplied
|
||||
in the library do not do anything. If multiple threads of execution
|
||||
can call the time functions and give up scheduling in the middle, then you
|
||||
you need to define your own versions of these functions in order to
|
||||
safely lock the time zone variables during a call. If you do not, the results
|
||||
of <<localtime>>, <<mktime>>, <<ctime>>, and <<strftime>> are undefined.
|
||||
|
||||
The lock <<__tz_lock>> may not be called recursively; that is,
|
||||
a call <<__tz_lock>> will always lock all subsequent <<__tz_lock>> calls
|
||||
until the corresponding <<__tz_unlock>> call on the same thread is made.
|
||||
*/
|
||||
|
||||
#include <_ansi.h>
|
||||
#include "local.h"
|
||||
|
||||
_VOID
|
||||
_DEFUN_VOID (__tz_lock)
|
||||
{
|
||||
}
|
||||
|
||||
_VOID
|
||||
_DEFUN_VOID (__tz_unlock)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
FUNCTION
|
||||
<<tzset>>---set timezone characteristics from TZ environment variable
|
||||
|
||||
INDEX
|
||||
tzset
|
||||
|
||||
ANSI_SYNOPSIS
|
||||
#include <time.h>
|
||||
void tzset(void);
|
||||
void _tzset_r (struct _reent *);
|
||||
|
||||
TRAD_SYNOPSIS
|
||||
#include <time.h>
|
||||
void tzset();
|
||||
void _tzset_r (reent_ptr)
|
||||
struct _reent *reent_ptr;
|
||||
|
||||
DESCRIPTION
|
||||
<<tzset>> examines the TZ environment variable and sets up the three
|
||||
external variables: <<_timezone>>, <<_daylight>>, and <<tzname>>. The
|
||||
value of <<_timezone>> shall be the offset from the current time zone
|
||||
to GMT. The value of <<_daylight>> shall be 0 if there is no daylight
|
||||
savings time for the current time zone, otherwise it will be non-zero.
|
||||
The <<tzname>> array has two entries: the first is the name of the
|
||||
standard time zone, the second is the name of the daylight-savings time
|
||||
zone.
|
||||
|
||||
The TZ environment variable is expected to be in the following POSIX
|
||||
format:
|
||||
|
||||
stdoffset1[dst[offset2][,start[/time1],end[/time2]]]
|
||||
|
||||
where: std is the name of the standard time-zone (minimum 3 chars)
|
||||
offset1 is the value to add to local time to arrive at Universal time
|
||||
it has the form: hh[:mm[:ss]]
|
||||
dst is the name of the alternate (daylight-savings) time-zone (min 3 chars)
|
||||
offset2 is the value to add to local time to arrive at Universal time
|
||||
it has the same format as the std offset
|
||||
start is the day that the alternate time-zone starts
|
||||
time1 is the optional time that the alternate time-zone starts
|
||||
(this is in local time and defaults to 02:00:00 if not specified)
|
||||
end is the day that the alternate time-zone ends
|
||||
time2 is the time that the alternate time-zone ends
|
||||
(it is in local time and defaults to 02:00:00 if not specified)
|
||||
|
||||
Note that there is no white-space padding between fields. Also note that
|
||||
if TZ is null, the default is Universal GMT which has no daylight-savings
|
||||
time. If TZ is empty, the default EST5EDT is used.
|
||||
|
||||
The function <<_tzset_r>> is identical to <<tzset>> only it is reentrant
|
||||
and is used for applications that use multiple threads.
|
||||
|
||||
RETURNS
|
||||
There is no return value.
|
||||
|
||||
PORTABILITY
|
||||
<<tzset>> is part of the POSIX standard.
|
||||
|
||||
Supporting OS subroutine required: None
|
||||
*/
|
||||
|
||||
#include <_ansi.h>
|
||||
#include <reent.h>
|
||||
#include <time.h>
|
||||
#include "local.h"
|
||||
|
||||
_VOID
|
||||
_DEFUN_VOID (tzset)
|
||||
{
|
||||
_tzset_r (_REENT);
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
#include <_ansi.h>
|
||||
#include <reent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include "local.h"
|
||||
|
||||
static char __tzname_std[11];
|
||||
static char __tzname_dst[11];
|
||||
static char *prev_tzenv = NULL;
|
||||
|
||||
/* default to GMT */
|
||||
char *_tzname[2] = {"GMT" "GMT"};
|
||||
int _daylight = 0;
|
||||
time_t _timezone = (time_t)0;
|
||||
|
||||
int __tzyear = 0;
|
||||
|
||||
int __tznorth = 1;
|
||||
|
||||
__tzrule_type __tzrule[2] = { {'J', 0, 0, 0, 0, (time_t)0, 0 },
|
||||
{'J', 0, 0, 0, 0, (time_t)0, 0 } };
|
||||
|
||||
_VOID
|
||||
_DEFUN (_tzset_r, (reent_ptr),
|
||||
struct _reent *reent_ptr)
|
||||
{
|
||||
char *tzenv;
|
||||
int hh, mm, ss, sign, m, w, d, n;
|
||||
int i, ch;
|
||||
|
||||
if ((tzenv = _getenv_r (reent_ptr, "TZ")) == NULL)
|
||||
{
|
||||
TZ_LOCK;
|
||||
_timezone = (time_t)0;
|
||||
_daylight = 0;
|
||||
_tzname[0] = "GMT";
|
||||
_tzname[1] = "GMT";
|
||||
TZ_UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
TZ_LOCK;
|
||||
|
||||
if (prev_tzenv != NULL && strcmp(tzenv, prev_tzenv) == 0)
|
||||
{
|
||||
TZ_UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
free(prev_tzenv);
|
||||
prev_tzenv = _strdup_r (reent_ptr, tzenv);
|
||||
|
||||
/* ignore implementation-specific format specifier */
|
||||
if (*tzenv == ':')
|
||||
++tzenv;
|
||||
|
||||
if (sscanf (tzenv, "%10[^0-9,+-]%n", __tzname_std, &n) <= 0)
|
||||
{
|
||||
TZ_UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
tzenv += n;
|
||||
|
||||
sign = 1;
|
||||
if (*tzenv == '-')
|
||||
{
|
||||
sign = -1;
|
||||
++tzenv;
|
||||
}
|
||||
else if (*tzenv == '+')
|
||||
++tzenv;
|
||||
|
||||
mm = 0;
|
||||
ss = 0;
|
||||
|
||||
if (sscanf (tzenv, "%hu%n:%hu%n:%hu%n", &hh, &n, &mm, &n, &ss, &n) < 1)
|
||||
{
|
||||
TZ_UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
__tzrule[0].offset = sign * (ss + SECSPERMIN * mm + SECSPERHOUR * hh);
|
||||
_tzname[0] = __tzname_std;
|
||||
tzenv += n;
|
||||
|
||||
if (sscanf (tzenv, "%10[^0-9,+-]%n", __tzname_dst, &n) <= 0)
|
||||
{
|
||||
_tzname[1] = _tzname[0];
|
||||
TZ_UNLOCK;
|
||||
return;
|
||||
}
|
||||
else
|
||||
_tzname[1] = __tzname_dst;
|
||||
|
||||
tzenv += n;
|
||||
|
||||
/* otherwise we have a dst name, look for the offset */
|
||||
sign = 1;
|
||||
if (*tzenv == '-')
|
||||
{
|
||||
sign = -1;
|
||||
++tzenv;
|
||||
}
|
||||
else if (*tzenv == '+')
|
||||
++tzenv;
|
||||
|
||||
hh = 0;
|
||||
mm = 0;
|
||||
ss = 0;
|
||||
|
||||
if (sscanf (tzenv, "%hu%n:%hu%n:%hu%n", &hh, &n, &mm, &n, &ss, &n) <= 0)
|
||||
__tzrule[1].offset = __tzrule[0].offset - 3600;
|
||||
else
|
||||
__tzrule[1].offset = sign * (ss + SECSPERMIN * mm + SECSPERHOUR * hh);
|
||||
|
||||
tzenv += n;
|
||||
|
||||
if (*tzenv == ',')
|
||||
++tzenv;
|
||||
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
if (*tzenv == 'M')
|
||||
{
|
||||
if (sscanf (tzenv, "M%hu%n.%hu%n.%hu%n", &m, &n, &w, &n, &d, &n) != 3 ||
|
||||
m < 1 || m > 12 || w < 1 || w > 5 || d > 6)
|
||||
{
|
||||
TZ_UNLOCK;
|
||||
return;
|
||||
}
|
||||
|
||||
__tzrule[i].ch = 'M';
|
||||
__tzrule[i].m = m;
|
||||
__tzrule[i].n = w;
|
||||
__tzrule[i].d = d;
|
||||
|
||||
tzenv += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *end;
|
||||
if (*tzenv == 'J')
|
||||
{
|
||||
ch = 'J';
|
||||
++tzenv;
|
||||
}
|
||||
else
|
||||
ch = 'D';
|
||||
|
||||
d = strtoul (tzenv, &end, 10);
|
||||
|
||||
/* if unspecified, default to US settings */
|
||||
if (end == tzenv)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
__tzrule[0].ch = 'M';
|
||||
__tzrule[0].m = 4;
|
||||
__tzrule[0].n = 1;
|
||||
__tzrule[0].d = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
__tzrule[1].ch = 'M';
|
||||
__tzrule[1].m = 10;
|
||||
__tzrule[1].n = 5;
|
||||
__tzrule[1].d = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__tzrule[i].ch = ch;
|
||||
__tzrule[i].d = d;
|
||||
}
|
||||
|
||||
tzenv = end;
|
||||
}
|
||||
|
||||
/* default time is 02:00:00 am */
|
||||
hh = 2;
|
||||
mm = 0;
|
||||
ss = 0;
|
||||
|
||||
if (*tzenv == '/')
|
||||
sscanf (tzenv, "%hu%n:%hu%n:%hu%n", &hh, &n, &mm, &n, &ss, &n);
|
||||
|
||||
__tzrule[i].s = ss + SECSPERMIN * mm + SECSPERHOUR * hh;
|
||||
}
|
||||
|
||||
__tzcalc_limits (__tzyear);
|
||||
_timezone = (time_t)(__tzrule[0].offset);
|
||||
_daylight = __tzrule[0].offset != __tzrule[1].offset;
|
||||
|
||||
TZ_UNLOCK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue