Mercurial > hg > Applications > mh
diff zotnet/tws/phoon/dtime.c @ 0:bce86c4163a3
Initial revision
author | kono |
---|---|
date | Mon, 18 Apr 2005 23:46:02 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/zotnet/tws/phoon/dtime.c Mon Apr 18 23:46:02 2005 +0900 @@ -0,0 +1,448 @@ +/* dtime.c - routines to do ``ARPA-style'' time structures + +ver date who remarks +--- ------- --- ------------------------------------------------------------- +01B 15nov86 JP Thouroughly hacked by Jef Poskanzer. +01A ??????? MTR Original version from the MH 6.5 distribution, courtesy + of Marshall Rose. + +*/ + + +#include "tws.h" +#include <stdio.h> +#include <sys/types.h> +#include <sys/time.h> +#ifdef SYS5 +#include <string.h> +#else SYS5 +#include <strings.h> +#include <sys/timeb.h> +#endif SYS5 + +#ifdef SYS5 +extern int daylight; +extern long timezone; +extern char *tzname[]; +#endif SYS5 + +/* */ + +#define abs(a) ( a >= 0 ? a : -a ) + +char *tw_moty[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL }; + +char *tw_dotw[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL }; + +char *tw_ldotw[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday", NULL }; + +/* */ + +static struct zone + { + char *std; + char *dst; + int shift; + } + zones[] = { + "GMT", "BST", 0, + "EST", "EDT", -5, + "CST", "CDT", -6, + "MST", NULL, -7, + "PST", "PDT", -8, + "A", NULL, -1, + "B", NULL, -2, + "C", NULL, -3, + "D", NULL, -4, + "E", NULL, -5, + "F", NULL, -6, + "G", NULL, -7, + "H", NULL, -8, + "I", NULL, -9, + "K", NULL, -10, + "L", NULL, -11, + "M", NULL, -12, + "N", NULL, 1, +#ifndef HUJI + "O", NULL, 2, +#else HUJI + "JST", "JDT", 2, +#endif HUJI + "P", NULL, 3, + "Q", NULL, 4, + "R", NULL, 5, + "S", NULL, 6, + "T", NULL, 7, + "U", NULL, 8, + "V", NULL, 9, + "W", NULL, 10, + "X", NULL, 11, + "Y", NULL, 12, + NULL }; + +#define CENTURY 19 + +long time( ); +struct tm *localtime( ); + +/* */ + +char *dtimenow( ) + { + long clock; + + (void) time( &clock ); + return ( dtime( &clock ) ); + } + + +char * +dctime( tw ) +struct tws *tw; + { + static char buffer[25]; + + if ( tw == NULL ) + return ( NULL ); + + (void) sprintf( buffer, "%.3s %.3s %02d %02d:%02d:%02d %.4d\n", + tw_dotw[tw -> tw_wday], tw_moty[tw -> tw_mon], tw -> tw_mday, + tw -> tw_hour, tw -> tw_min, tw -> tw_sec, + tw -> tw_year >= 100 ? tw -> tw_year : 1900 + tw -> tw_year ); + + return ( buffer ); + } + +/* */ + +struct tws * +dtwstime( ) + { + long clock; + + (void) time( &clock ); + return ( dlocaltime( &clock ) ); + } + + +struct tws * +dlocaltime( clock ) +long *clock; + { + register struct tm *tm; +#ifndef SYS5 + struct timeb tb; +#endif not SYS5 + static struct tws tw; + + if ( clock == NULL ) + return ( NULL ); + tw.tw_flags = TW_NULL; + + tm = localtime( clock ); + tw.tw_sec = tm -> tm_sec; + tw.tw_min = tm -> tm_min; + tw.tw_hour = tm -> tm_hour; + tw.tw_mday = tm -> tm_mday; + tw.tw_mon = tm -> tm_mon; + tw.tw_year = tm -> tm_year; + tw.tw_wday = tm -> tm_wday; + tw.tw_yday = tm -> tm_yday; + if ( tm -> tm_isdst ) + tw.tw_flags |= TW_DST; +#ifndef SYS5 + ftime( &tb ); + tw.tw_zone = -tb.timezone; +#else SYS5 + tzset( ); + tw.tw_zone = -(timezone / 60); +#endif SYS5 + tw.tw_flags &= ~TW_SDAY; + tw.tw_flags |= TW_SEXP; + tw.tw_clock = *clock; + + return ( &tw ); + } + + +struct tws * +dgmtime( clock ) +long *clock; + { + register struct tm *tm; + static struct tws tw; + + if ( clock == NULL ) + return ( NULL ); + tw.tw_flags = TW_NULL; + + tm = gmtime( clock ); + tw.tw_sec = tm -> tm_sec; + tw.tw_min = tm -> tm_min; + tw.tw_hour = tm -> tm_hour; + tw.tw_mday = tm -> tm_mday; + tw.tw_mon = tm -> tm_mon; + tw.tw_year = tm -> tm_year; + tw.tw_wday = tm -> tm_wday; + tw.tw_yday = tm -> tm_yday; + if ( tm -> tm_isdst ) + tw.tw_flags |= TW_DST; + tw.tw_zone = 0; + tw.tw_flags &= ~TW_SDAY; + tw.tw_flags |= TW_SEXP; + tw.tw_clock = *clock; + + return( &tw ); + } + +/* */ + +char * +dasctime( tw, flags ) +struct tws *tw; +int flags; + { + static char buffer[80], result[80]; + + if ( tw == NULL ) + return ( NULL ); + + (void) sprintf( buffer, "%02d %s %02d %02d:%02d:%02d %s", + tw -> tw_mday, tw_moty[tw -> tw_mon], tw -> tw_year, + tw -> tw_hour, tw -> tw_min, tw -> tw_sec, + dtimezone( tw -> tw_zone, tw -> tw_flags | flags ) ); + + if ( (tw -> tw_flags & TW_SDAY) == TW_SEXP ) + (void) sprintf( result, "%s, %s", tw_dotw[tw -> tw_wday], buffer ); + else + if ( (tw -> tw_flags & TW_SDAY) == TW_SNIL ) + (void) strcpy( result, buffer ); + else + (void) sprintf( result, "%s (%s)", buffer, tw_dotw[tw -> tw_wday] ); + + return ( result ); + } + +/* */ + +char * +dtimezone( offset, flags ) +int offset, flags; + { + register int hours, mins; + register struct zone *z; + static char buffer[10]; + + if ( offset < 0 ) + { + mins = -((-offset) % 60); + hours = -((-offset) / 60); + } + else + { + mins = offset % 60; + hours = offset / 60; + } + + if ( !(flags & TW_ZONE) && mins == 0 ) + for ( z = zones; z -> std; z++ ) + if ( z -> shift == hours ) + return ( z -> dst && (flags & TW_DST) ? z -> dst : z -> std ); + +#ifdef DSTXXX + if ( flags & TW_DST ) + hours += 1; +#endif DSTXXX + (void) sprintf( buffer, "%s%02d%02d", + offset < 0 ? "-" : "+", abs( hours ), abs( mins ) ); + return ( buffer ); + } + +/* */ + +void +twscopy( tb, tw ) +struct tws *tb, *tw; + { +#ifdef notdef + tb -> tw_sec = tw -> tw_sec; + tb -> tw_min = tw -> tw_min; + tb -> tw_hour = tw -> tw_hour; + tb -> tw_mday = tw -> tw_mday; + tb -> tw_mon = tw -> tw_mon; + tb -> tw_year = tw -> tw_year; + tb -> tw_wday = tw -> tw_wday; + tb -> tw_yday = tw -> tw_yday; + tb -> tw_zone = tw -> tw_zone; + tb -> tw_clock = tw -> tw_clock; + tb -> tw_flags = tw -> tw_flags; +#else not notdef + *tb = *tw; +#endif not notdef + } + + +int +twsort( tw1, tw2 ) +struct tws *tw1, *tw2; + { + register long c1, c2; + + (void) twclock( tw1 ); + (void) twclock( tw2 ); + + return ( (c1 = tw1 -> tw_clock) > (c2 = tw2 -> tw_clock) ? 1 + : c1 == c2 ? 0 : -1 ); + } + +/* */ + + +/* Julian day number of the Unix clock's origin, 01 Jan 1970. */ +#define JD1970 2440587L + + +long +twjuliandate( tw ) +struct tws *tw; + { + register int mday, mon, year; + register long a, b; + double jd; + + if ( (mday = tw -> tw_mday) < 1 || mday > 31 || + (mon = tw -> tw_mon + 1) < 1 || mon > 12 || + (year = tw -> tw_year) < 1 || year > 10000 ) + return ( -1L ); + if ( year < 100 ) + year += CENTURY * 100; + + if ( mon == 1 || mon == 2 ) + { + --year; + mon += 12; + } + if ( year < 1583 ) + return ( -1L ); + a = year / 100; + b = 2 - a + a / 4; + b += (long) ( (double) year * 365.25 ); + b += (long) ( 30.6001 * ( (double) mon + 1.0 ) ); + jd = mday + b + 1720994.5; + return ( (long) jd ); + } + + +long +twsubdayclock( tw ) +struct tws *tw; + { + register int i, sec, min, hour; + register long result; + + if ( (sec = tw -> tw_sec) < 0 || sec > 59 || + (min = tw -> tw_min) < 0 || min > 59 || + (hour = tw -> tw_hour) < 0 || hour > 23 ) + return ( -1L ); + + result = ( hour * 60 + min ) * 60 + sec; + result -= 60 * tw -> tw_zone; + if ( tw -> tw_flags & TW_DST ) + result -= 60 * 60; + + return ( result ); + } + + +long +twclock( tw ) +struct tws *tw; + { + register long jd, sdc, result; + + if ( tw -> tw_clock != 0L ) + return ( tw -> tw_clock ); + + if ( ( jd = twjuliandate( tw ) ) == -1L ) + return ( tw -> tw_clock = -1L ); + if ( ( sdc = twsubdayclock( tw ) ) == -1L ) + return ( tw -> tw_clock = -1L ); + + result = ( jd - JD1970 ) * 24 * 60 * 60 + sdc; + + return ( tw -> tw_clock = result ); + } + +/* */ + +/*** twsubtract - subtract tw2 from tw1, returning result in seconds + +The point of this routine is that using twclock( tw1 ) - twclock( tw2 ) +would limit you to dates after the Unix Epoch ( 01 January 1970 ). This +routine avoids that limit. However, because the result is represented +by 32 bits, it is still limited to a span of two billion seconds, which is +about 66 years. + +*/ + +long +twsubtract( tw1, tw2 ) +struct tws *tw1, *tw2; + { + register long jd1, jd2, sdc1, sdc2, result; + + if ( ( jd1 = twjuliandate( tw1 ) ) == -1L ) + return ( 0L ); + if ( ( sdc1 = twsubdayclock( tw1 ) ) == -1L ) + return ( 0L ); + + if ( ( jd2 = twjuliandate( tw2 ) ) == -1L ) + return ( 0L ); + if ( ( sdc2 = twsubdayclock( tw2 ) ) == -1L ) + return ( 0L ); + + result = ( jd1 - jd2 ) * 24 * 60 * 60 + ( sdc1 - sdc2 ); + + return ( result ); + } + +/* */ + +/* + * Simple calculation of day of the week. Algorithm used is Zeller's + * congruence. Currently, we assume if tw -> tw_year < 100 + * then the century is CENTURY. + */ + +set_dotw( tw ) +struct tws *tw; + { + register int month, day, year, century; + + month = tw -> tw_mon - 1; + day = tw -> tw_mday; + year = tw -> tw_year % 100; + century = tw -> tw_year >= 100 ? tw -> tw_year / 100 : CENTURY; + + if ( month <= 0 ) + { + month += 12; + if ( --year < 0 ) + { + year += 100; + century--; + } + } + + tw -> tw_wday = + ((26 * month - 2) / 10 + day + year + year / 4 + - 3 * century / 4 + 1) % 7; + + tw -> tw_flags &= ~TW_SDAY; + tw -> tw_flags |= TW_SIMP; + }