📄 time_lib.c
字号:
/* -----------------------------------------------------------------------------This source is copyrighted by Norbert Pueschel <pueschel@imsdd.meb.uni-bonn.de>From 'clockdaemon.readme':(available from Aminet, main site is ftp.wustl.edu:/pub/aminet/ under util/time/clockdaemon.lha)"The original SAS/C functions gmtime, localtime, mktime and time do notwork correctly. The supplied link library time.lib contains replacementfunctions for them."The time.lib library consists of three parts (time.c, timezone.c and version.c),all included here. [time.lib 1.2 (1997-04-02)]Permission is granted to the Info-ZIP group to redistribute the time.lib source.The use of time.lib functions in own, noncommerical programs is permitted.It is only required to add the timezone.doc to such a distribution.Using the time.lib library in commerical software (including Shareware) is onlypermitted after prior consultation of the author.------------------------------------------------------------------------------*//* History *//* 30 Mar 1997, Haidinger Walter, added AVAIL_GETVAR macro to support OS <V36 *//* 24 May 1997, Haidinger Walter, added NO_MKTIME macro to allow use of Zip's *//* mktime.c. NO_MKTIME must be defined in the makefile, though. *//* 25 May 1997, Haidinger Walter, moved set_TZ() here from filedate.c *//* 20 Jul 1997, Paul Kienitz, adapted for Aztec C, added mkgmtime(), *//* debugged, and made New York settings default, as is common. *//* 30 Sep 1997, Paul Kienitz, restored real_timezone_is_set flag *//* 19 Oct 1997, Paul Kienitz, corrected 16 bit multiply overflow bug *//* 21 Oct 1997, Chr. Spieler, shortened long lines, removed more 16 bit stuff *//* (n.b. __stdoffset and __dstoffset now have to be long ints) *//* 25 Oct 1997, Paul Kienitz, cleanup, make tzset() not redo work needlessly *//* 29 Oct 1997, Chr. Spieler, initialized globals _TZ, real_timezone_is_set */#ifdef __SASC# include <proto/dos.h># include <proto/locale.h># include <proto/exec.h>#else# include <clib/dos_protos.h># include <clib/locale_protos.h># include <clib/exec_protos.h># ifdef AZTEC_C# include <pragmas/exec_lib.h># include <pragmas/dos_lib.h># include <pragmas/locale_lib.h> int setenv(const char *var, const char *value, int overwrite);# endif#endif#include <exec/execbase.h>#include <clib/alib_stdio_protos.h>#include <string.h>#include <stdlib.h>/* Info-ZIP accesses these by their standard names: */#define __timezone timezone#define __daylight daylight#define __tzset tzsetextern struct ExecBase *SysBase;/* externals from C library */extern char *getenv(const char *var);/* extern int timer(unsigned int *); */typedef unsigned long time_t;struct tm { int tm_sec; /* seconds after the minute */ int tm_min; /* minutes after the hour */ int tm_hour; /* hours since midnight */ int tm_mday; /* day of the month */ int tm_mon; /* months since January */ int tm_year; /* years since 1900 */ int tm_wday; /* days since Sunday */ int tm_yday; /* days since January 1 */ int tm_isdst; /* Daylight Savings Time flag */};struct dstdate { enum { JULIAN0, JULIAN, MWD } dd_type; int dd_day; int dd_week; int dd_month; int dd_secs;};static struct dstdate __dststart;static struct dstdate __dstend;#define isleapyear(y) (((y)%4==0&&(!((y)%100==0)||((y)%400==0)))?1:0)#define yearlen(y) (isleapyear(y)?366:365)#define weekday(d) (((d)+4)%7)#define jan1ofyear(y) (((y)-70)*365+((y)-69)/4-((y)-1)/100+((y)+299)/400)#define wdayofyear(y) weekday(jan1ofyear(y))#define sgn(y) ((y)<0?-1:((y)>0?1:0))#define MAXTIMEZONELEN 16#define AMIGA2UNIX 252460800 /* seconds between 1.1.1970 and 1.1.1978 */#define CHECK 300 /* min. time between checks of IXGMTOFFSET */#define GETVAR_REQVERS 36L /* required OS version for GetVar() */#define AVAIL_GETVAR ((SysBase->LibNode.lib_Version >= GETVAR_REQVERS) ? 1:0)char *envvarstr; /* ptr to environment string (used if !AVAIL_GETVAR) */int __daylight;long __timezone;char *__tzname[2];char __tzstn[MAXTIMEZONELEN];char __tzdtn[MAXTIMEZONELEN];char *_TZ = NULL;int __nextdstchange;long __stdoffset;long __dstoffset;int real_timezone_is_set = FALSE;#define TZLEN 64static char TZ[TZLEN];static struct tm TM;static const unsigned short days[2][13] = { { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }};#ifndef NO_MKTIME /* only used by mktime() */static const unsigned short monlen[2][12] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }};#endif/* internal prototypes */static time_t dst2time(int year,struct dstdate *dst);static void time2tm(time_t time);static int checkdst(time_t time);#ifndef NO_MKTIMEstatic void normalize(int *i,int *j,int norm);#endifstatic long gettime(char **s);static void getdstdate(char **s,struct dstdate *dst);void set_TZ(long time_zone, int day_light);/* prototypes for sc.lib replacement functions */struct tm *gmtime(const time_t *t);struct tm *localtime(const time_t *t);#ifndef NO_MKTIMEtime_t mkgmtime(struct tm *tm);time_t mktime(struct tm *tm);#endiftime_t time(time_t *tm);void __tzset(void);static time_t dst2time(int year,struct dstdate *dst){ int isleapyear,week,mon,mday; mon = 0; mday = dst->dd_day; isleapyear = isleapyear(year); switch(dst->dd_type) { case JULIAN: if(!isleapyear || dst->dd_day <= 59) break; default: mday++; break; case MWD: mon = dst->dd_month-1; week = dst->dd_week; if(week == 5) { mon++; week = 0; } mday = dst->dd_day - weekday(jan1ofyear(year)+days[isleapyear][mon]); if(mday < 0) mday += 7; mday += (week - 1) * 7 + 1; break; } return((time_t)(jan1ofyear(year)+days[isleapyear][mon]+mday-1)*(time_t)86400L+ (time_t)dst->dd_secs);}static void time2tm(time_t time){ int isleapyear; TM.tm_sec = time % 60; time /= 60; TM.tm_min = time % 60; time /= 60; TM.tm_hour = time % 24; time /= 24; TM.tm_year = time/365 + 70; /* guess year */ while((TM.tm_yday = time - jan1ofyear(TM.tm_year)) < 0) TM.tm_year--; isleapyear = isleapyear(TM.tm_year); for(TM.tm_mon = 0; TM.tm_yday >= days[isleapyear][TM.tm_mon+1]; TM.tm_mon++); TM.tm_mday = TM.tm_yday - days[isleapyear][TM.tm_mon] + 1; TM.tm_wday = (time+4)%7;}static int checkdst(time_t time){ int year,day; time_t t,u; day = time / 86400L; year = day / 365 + 70; /* guess year */ while(day - jan1ofyear(year) < 0) year--; t = dst2time(year,&__dststart) + __stdoffset; u = dst2time(year,&__dstend) + __dstoffset; if(u > t) { return((time >= t && time < u)?1:0); } else { return((time < u || time >= t)?1:0); }}struct tm *gmtime(const time_t *t){ TM.tm_isdst = 0; time2tm(*t); return(&TM);}struct tm *localtime(const time_t *t){ if(!_TZ) __tzset(); TM.tm_isdst = checkdst(*t); time2tm(*t - (TM.tm_isdst ? __dstoffset : __stdoffset)); return(&TM);}#ifndef NO_MKTIME /* normalize() only used by mktime() */static void normalize(int *i,int *j,int norm){ while(*i < 0) { *i += norm; (*j)--; } while(*i >= norm) { *i -= norm; (*j)++; }}time_t mkgmtime(struct tm *tm){ time_t t; normalize(&tm->tm_sec,&tm->tm_min,60); normalize(&tm->tm_min,&tm->tm_hour,60); normalize(&tm->tm_hour,&tm->tm_mday,24); normalize(&tm->tm_mon,&tm->tm_year,12); while(tm->tm_mday > monlen[isleapyear(tm->tm_year)][tm->tm_mon]) { tm->tm_mday -= monlen[isleapyear(tm->tm_year)][tm->tm_mon]; tm->tm_mon++; if(tm->tm_mon == 12) { tm->tm_mon = 0; tm->tm_year++; } } while(tm->tm_mday < 0) { tm->tm_mon--; if(tm->tm_mon == -1) { tm->tm_mon = 11; tm->tm_year--; } tm->tm_mday += monlen[isleapyear(tm->tm_year)][tm->tm_mon]; } tm->tm_yday = tm->tm_mday + days[isleapyear(tm->tm_year)][tm->tm_mon] - 1; t = jan1ofyear(tm->tm_year) + tm->tm_yday; tm->tm_wday = weekday(t); if(tm->tm_year < 70) return((time_t)0); t = t * 86400L + tm->tm_hour * 3600L + tm->tm_min * 60L + (time_t)tm->tm_sec; return(t);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -