/*	posixtim.c
 *	V1.2			02-Dec-1997	IfN/Mey
 *	V1.1			14-Jul-1996	IfN/Mey
 *
 *	POSIX time routines.
 *
 *	(c) Eckart Meyer, 1995-1997		meyer@ifn.ing.tu-bs.de
 *+
 * Here are some routines replacing C RTL routines to implement time zones.
 * Since VMS has local time, all related RTL routines return local time,
 * (gmtime() even returns the NULL pointer).
 *
 * The following routines replaces the RTL routines and implement the
 * POSIX time scheme.
 *
 * NOTE: To obtain timezone information, the logicals in the order
 *
 *	POSIX_TZ
 *	TZ
 *	SYS$TIME_ZONERULE	(obsolete, don't use)
 *	SYS$TIMEZONE_RULE	(added V1.2)
 *	POSIX$DEFAULT_TZ
 *
 * are read until the first of them is found. The translation is then 
 * used the same way VMS POSIX uses it. For me (Germany) this is:
 *
 * $ DEFINE/SYS/EXE POSIX$DEFAULT_TZ "CET-1:00CET DST,M3.5.0/2:00,M9.5.0/3:00"
 *
 * This means: The time zone designator is normally CET, -1:00 hours must
 * be added to get UTC time. Daylight saving time has the designator
 * "CET DST" and begins at the last (5) sunday (0) in march (3) at 2:00 and
 * ends at the last sunday in september at 3:00 (24 hour times).
 *
 * For more information see SYS$MANAGER:POSIX$LOCALIZATION.COM and
 * the International Standard ISO/IEC 9945-1:1990 (also IEEE Std 1003.1-1990).
 *
 * Note: This implementation relies on the time_t type to be an integer.
 *	 If this will ever change, some of the code must be rewritten.
 */

#ifndef __DECC
#define NO_DIFFTIME
#endif

#if 1
#define tzname		posix_tzname
#define daylight	posix_daylight
#define timezone	posix_timezone
#endif

#if 0
#ifndef _POSIX_SOURCE
#define _POSIX_SOURCE
#endif
#endif

#define __NO_MACROS 1	/* POSIX difftime macro confuses compiler ... (???) */

#ifdef _stat
#define stat _stat
#endif
#ifdef _fstat
#define fstat _fstat
#endif

#include <stdio.h>
#include <time.h>
#include <sys/timeb.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

struct timezone {
	int tz_minuteswest; /* of Greenwich */
	int tz_dsttime;     /* type of dst correction to apply */
};

struct timeval {
	long tv_sec;
	long tv_usec;
};

struct utimbuf {
	time_t	actime;
	time_t	modtime;
};

/*
 * Foward declarations
 */
struct tm * posix_localtime(const time_t *);
struct tm * posix_gmtime(const time_t *);
time_t posix_mktime(struct tm *);
time_t posix_time(time_t *);
char * posix_ctime(const time_t *);
void posix_tzset(void);
void posix_ftime(struct timeb *);
int posix_gettimeofday(struct timeval *, struct timezone *);
int posix_utime(const char *, const struct utimbuf *);
int posix_stat(char *, struct stat *);
int posix_lstat(char *, struct stat *);
int posix_fstat(int, struct stat *);

#ifdef VMS
int vms_utime(const char *, const struct utimbuf *);
#endif

/*
 * Public
 */
int daylight = 1;
long timezone = 8*3600;
char *tzname[2] = {"PST","PDT"};

/*
 * static storage
 */
static char s_tzname1[15];
static char s_tzname2[15];
static char *s_pdston, *s_pdstoff;

static time_t s_dston;			/* stored DST begin/end time... */
static time_t s_dstoff;			/* ...in seconds (UTC) */
static time_t s_year_begin = 0;		/* time_t value of next new year */
static time_t s_year_end = 0;

static time_t this_dston;		/* stored DST begin/end time... */
static time_t this_dstoff; 		/* ...in seconds (UTC) */
static time_t this_year_begin = 0;	/* time_t value of next new year */
static time_t this_year_end = 0;

/*
 * For historical reasons the default is US Pacific (I believe):
 */
char *dston_default = "M4.1.0/2:00";
char *dstoff_default = "M10.5.0/2:00";

#ifdef NO_DIFFTIME
#define difftime mydifftime
double difftime (time_t t1, time_t t0)
{
	return( (double)t1 - (double)t0 );
}
#endif

/*
 * bintime
 *
 * convert a time string "[+|-]dd hh:mm:ss" into a time_t value, i.e. in seconds
 *
 *	00:01	-> +00 00:01:00
 *	::1	-> +00 00:00:01
 *	1 1	-> +01 01:00:00
 *	-1	-> -00 01:00:00
 */
static time_t bintime(char *s)
{
	int mul = 1;
	char *p, *q;
	int t = 0;
	int i;
	int sign = 1;

	if (s == NULL) return(0);
	if (*s == '\0') return(0);

	while (*s != '\0'  &&  *s == ' ') s++;	/* trim leading blanks */

	if (*s == '+') {
		s++;
	}
	if (*s == '-') {
		s++;
		sign = -1;
	}

	while (*s != '\0'  &&  *s == ' ') s++;	/* remove blanks */

	p = s + strlen(s);

	while (p != s  &&  *(p-1) == ' ') --p;	/* trim trainling blanks */
	if (p == s) return(0);			/* empty string */

	while(TRUE) {		/* time digits loop */
		q = p - 1;	/* q: preview character in front of this one */
		if (p == s  ||  !isdigit(*q)) {
			if (p == s  ||  *q == ':'  ||  *q == ' ') {
				i = atoi(p);
				t += i * mul;
				if (i < 0 || i > 59) return(0);
				if (mul == 1) mul = 60;
				else if (mul == 60) mul = 3600;
				else if (mul == 3600) mul = 0;
				else return(0);
			}
			else {
				return(0);
			}
		}
		if (p == s) break;
		if (*q == ' ') break;
		--p;
	}
	if (i > 23) return(0);		/* last scanned number is hours */
	if (mul == 60) t = t * 3600;	/* "hh" */
	if (mul == 3600) t = t * 60;	/* "hh:mm" */
	if (p == s) return(sign * t);
/*
 * Now for the days...
 */
	while (p != s  &&  *(p-1) == ' ') --p;	/* trim */
	for (; p != s  &&  isdigit(*(p-1)); --p);
	i = atoi(p);
	if (p != s) return(0);		/* must now be at start of string */
	t += i * 3600 * 24;	/* days */
	return(sign * t);
}

/*
 * Decode the DST begin and end dates.
 *
 *	Format:	<start>/<time>		(<time> is optional)
 *
 *	<start>		Is the date when summer time starts. The <start> field 
 *			can be in the following format:
 *
 *			Jn	The Julian day n (1<=n<=365)
 *			n	The zero-based Julian day n (0<=n<=365)
 *			Mm.n.d	The day d of the week n of the month m,
 *				where:
 *				0<=d<=6; d=0 is Sunday
 *				1<=n<=5; n=5 means the last d day in the month m
 *					 n=1 means the first week in which the
 *					     d'th day occurs
 *				1<=m<=12; m=1 is January
 *
 *	<time>		Describes when, in current local time, the change
 *			to the other time is made. The <time> field has the 
 *			same format as the <offset> field except that the 
 *			sign is not allowed.
 */
static int decode_dst(time_t *dstclock, char *s, time_t *clock)
{
	char *p, *q;
	struct tm tmp;
	int i;
	time_t t;
	int jday;
	int dstmon, dstweek, dstwday, dsttime = 0;

	if (s == NULL) return(-1);

	p = strchr(s,'/');
	if (p != NULL) {
		dsttime = bintime(p+1);
	}
	
	t = (clock == NULL) ? time(&t) : *clock;
	tmp = *localtime(&t);	/* only to obtain the year */
	if (*s == 'J'  ||  isdigit(*s)) {
		if (*s == 'J') {
			s++;
			jday = atoi(s);
		}
		else {
			jday = atoi(s) + 1;
		}
		tmp.tm_sec = 0;
		tmp.tm_min = 0;
		tmp.tm_hour = 0;
		tmp.tm_mon = 0;
		tmp.tm_mday = jday;	/* set the day here */
		tmp.tm_isdst = 0;
		*dstclock = mktime(&tmp) + timezone;
	}
	else if (*s == 'M') {
/*
 * parse the string "Mm.n.d"
 */
		s++;
		i = sscanf(s,"%d.%d.%d",&dstmon,&dstweek,&dstwday);
		if (i != 3) return(-1);
		if (dstmon < 1 || dstmon > 12) return(-1);
		if (dstweek < 1 || dstweek > 5) return(-1);
		if (dstwday < 0 || dstwday > 6) return(-1);
		tmp.tm_sec = dsttime;
		tmp.tm_min = 0;
		tmp.tm_hour = 0;
		tmp.tm_mday = 1;
		tmp.tm_mon = dstmon - 1;	/* months start with 0 */
		tmp.tm_isdst = 0;
		if (dstweek == 5) {
			tmp.tm_mday = 0;
			tmp.tm_mon++;
			t = mktime(&tmp);
			i = dstwday - tmp.tm_wday;
			if (i > 0) i -= 7;
			tmp.tm_mday += i;
		}
		else {
			t = mktime(&tmp);
			i = dstwday - tmp.tm_wday;
			if (i < 0) i += 7;
			tmp.tm_mday += ((dstweek-1) * 7) + i;
		}
		*dstclock = mktime(&tmp) + timezone;
	}
	else {
		return(-1);
	}
	return(0);
}


/*
 * dst_setup calculates dst times and start/end of year of the year
 * represented by the given clock value. If known values for this
 * year are present, use them (current year and last used year).
 *
 * Also, tzset() is called if not already done.
 */
static void dst_setup(const time_t *clock)
{
	time_t t;
	struct tm tm;
	int i;

	t = (clock == NULL) ? time(&t) : *clock;
/*
 * If we have already setup for the year represented by clock value t
 * we just return (we also return if s_year_end == 1 to prevent
 * infinite loops).
 */
	if (s_year_end == 1  ||  (t >= s_year_begin && t <= s_year_end)) return;
/*
 * Check if tzset() was called at all in this process.
 * tzset() also setup the values for the current year.
 */
	if (this_year_end == 0) {
		this_year_end = 1;	/* prevent infinite loop */
		posix_tzset();		/* calls dst_setup for current year */
	}
/*
 * Check for current year. If so, just use the stored values.
 * This should speed up the time() function.
 */
	if (t >= this_year_begin && t <= this_year_end) {
		s_year_begin = this_year_begin;
		s_year_end = this_year_end;
		s_dston = this_dston;
		s_dstoff = this_dstoff;
		return;
	}
/*
 * Nothing available, we have to do the work.
 */
	s_year_end = 1;			/* prevent infinite loop */
/*
 * Setup the clock values for dst begin and dst end for the year
 * represented by the clock value t.
 */
	i = decode_dst(&s_dston, s_pdston, &t);
	if (i < 0) decode_dst(&s_dston, dston_default, &t);
	i = decode_dst(&s_dstoff, s_pdstoff, &t);
	if (i < 0) decode_dst(&s_dstoff, dstoff_default, &t);
/*
 * Setup the clock values for begin and end of the year represented
 * by the clock value t. This way we can later check if a still using
 * a date in the same year and avoid recalculation of the dst values.
 *
 * - January, 1st.
 */
	tm = *posix_localtime(&t);
	tm.tm_sec = 0;
	tm.tm_min = 0;
	tm.tm_hour = 0;
	tm.tm_mday = 1;
	tm.tm_mon = 0;
	tm.tm_isdst = -1;
	s_year_begin = posix_mktime(&tm);
/*
 * - December, 31th.
 */
	tm.tm_sec = 59;
	tm.tm_min = 59;
	tm.tm_hour = 23;
	tm.tm_mday = 31;
	tm.tm_mon = 11;
	tm.tm_isdst = -1;
	s_year_end = posix_mktime(&tm);
#if 0
	tm = *posix_localtime(&s_year_begin);
printf("year_begin = %08X, %s",s_year_begin,asctime(&tm)); /**/
	tm = *posix_localtime(&s_year_end);
printf("year_end   = %08X, %s",s_year_end,asctime(&tm)); /**/
	tm = *posix_localtime(&s_dston);
printf("dston      = %08X, %s",s_dston,asctime(&tm)); /**/
	tm = *posix_localtime(&s_dstoff);
printf("dstoff     = %08X, %s",s_dstoff,asctime(&tm)); /**/
#endif
}


/*
 * Decide if a clock value (seconds since 1-JAN-1970 UTC) is in the
 * the daylight saving time range.
 *
 * Note that at the end of DST we will have one hour "twice", e.g.
 * 2:10 DST and one our later 2:10 again normal time. The clock values
 * will be 3600 different of course. SunOS decides that without
 * specifying tm_isdst, 2:10:59 is DST and 2:11:00 is normal, i.e. one
 * hour later (if the the DST end time is ".../3:00").
 */
static long dst_offset(time_t *clock, time_t *dston, time_t *dstoff)
{
	if (!daylight) return(0);
/*
	if (difftime(*clock, *dston) < 0  ||
	    difftime(*clock, *dstoff-3600+(11*60)) >= 0) return(0);
	return(-3600);
*/

	return( (difftime(*clock, *dston)) >= 0 && 
		   (difftime(*clock, (*dstoff)-3600+(11*60))) < 0) ? -3600 : 0;

}


/*
 * convert clock value from local time to UTC.
 */
static void to_utc(time_t *clock)
{
	dst_setup(clock);  /* setup timezone and dst info */
	*clock += timezone;
	*clock += dst_offset(clock, &s_dston, &s_dstoff);
}


/*
 * tzset
 *
 * Set global variables daylight, timezone and tzname[2] from the logical
 * TZ or POSIX$DEFAULT_TZ.
 */
void posix_tzset()
{
	time_t t;
	char *p, *q;
	char c;
	char *ptz;
	char tbuf[20];
	int i;

	tzname[0] = s_tzname1;
	tzname[1] = s_tzname2;
	*s_tzname1 = '\0';
	*s_tzname2 = '\0';

	p = getenv("POSIX_TZ");
	if (p == NULL) p = getenv("TZ");
	if (p == NULL) p = getenv("SYS$TIME_ZONERULE");
	if (p == NULL) p = getenv("SYS$TIMEZONE_RULE");
	if (p == NULL) p = getenv("POSIX$DEFAULT_TZ");
/* printf("Time zone = {%s}\n",p); */

/*
 * parse into the three possible tokens "time zone", "DST begin", "DST end",
 * separated by comma.
 */
	ptz = NULL; s_pdston = NULL; s_pdstoff = NULL;
	if (p == NULL) return;
	q = p;
	do {
		if ( (c = *p) == ',' || *p == '\0') {
			*p = '\0';	/* terminate string */
			if (ptz == NULL) ptz = q;
			else if (s_pdston == NULL) s_pdston = q;
			else if (s_pdstoff == NULL) s_pdstoff = q;
			q = p+1;
		}
	} while (p++, c != '\0');

	if (s_pdston == NULL) s_pdston = dston_default;
	if (s_pdstoff == NULL) s_pdstoff = dstoff_default;
#if 0
printf("tz = {%s}\n",ptz);
printf("dst on  = {%s}\n",s_pdston);
printf("dst off = {%s}\n",s_pdstoff);
#endif

/*
 * Parse time zone
 *
 * - timezone designator
 */
	p = ptz;
	q = p;
	for (; isalpha(*p); p++);
	strncpy(s_tzname1,q,p-q);
	s_tzname1[p-q] = '\0';
/*
 * - timezone value
 */
	q = p;
	for (; isdigit(*p) || *p == '-' || *p == '+' || *p == ':'; p++);
	strncpy(tbuf,q,p-q);
	tbuf[p-q] = '\0';
	timezone = bintime(tbuf);
/*
 * - daylight saving time designator and flag
 */
	strcpy(s_tzname2,p);
	daylight = (s_tzname2[0] != '\0') ? TRUE : FALSE;
	if (!daylight) return;
/*
 * Decode the DST begin and end dates for this year.
 */
	this_year_end = 1;	/* prevent recursive call of tzset() */
	dst_setup(NULL);	/* setup for this year */
	this_dston = s_dston;
	this_dstoff = s_dstoff;
	this_year_begin = s_year_begin;
	this_year_end = s_year_end;
	return;
}


/*
 * localtime
 *
 * Adjust the clockvalue from UTC to posix localtime.
 * We have to set the DST flag correctly here.
 */
struct tm * posix_localtime(const time_t *clock)
{
	struct tm *local;
	time_t t, t1;
	int dstoff;

	dst_setup(clock);	/* setup timezone and dst info */
	t = *clock;
	dstoff = dst_offset(&t, &s_dston, &s_dstoff);
	if (difftime(t - dstoff, s_dstoff) >= 0) dstoff = 0;
	t -= dstoff;
	t -= timezone;
	local = localtime(&t);
	local->tm_isdst = (dstoff != 0);
	return(local);
}


/*
 * gmtime
 *
 * UTC is generated just by system's localtime().
 * UTC has no DST (??).
 */
struct tm * posix_gmtime(const time_t *clock)
{
	struct tm *local;

	local = localtime(clock);
	local->tm_isdst = 0;
	return(local);
}


/*
 * mktime
 *
 * is the inverse of localtime.
 * returns the clock value (seconds since 1-JAN-1970 UTC) and brings
 * the time struct into its normal form.
 *
 * In fact, the clock value is corrected according the dst flag and then
 * passed to localtime().
 */
time_t posix_mktime(struct tm *tm)
{
	time_t t;
	int isdst;
	int dstoff;

	isdst = tm->tm_isdst;	/* remember the flag */
	tm->tm_isdst = 0;	/* assume system's mktime does not handle DST */
	t = mktime(tm);
	if (this_year_end == 0) posix_tzset();	/* must know timezone info */
	t += timezone;
	dst_setup(&t);		/* now the dst values for the year */
	dstoff = dst_offset(&t, &s_dston, &s_dstoff);
	tm->tm_isdst = (isdst >= 0) ? isdst : (dstoff != 0);
	if (tm->tm_isdst) t += -3600;	/* make our own correction */
	*tm = *posix_localtime(&t);	/* re-make the time structure */
	return(t);
}


/*
 * ctime
 *
 * First call localtime(), then convert via asctime()
 */
char *posix_ctime(const time_t *clock)
{
	struct tm tm;

	tm = *posix_localtime(clock);
	return(asctime(&tm));
}


/*
 * time
 *
 * returns seconds since 1-JAN-1970 UTC
 *
 * time() calls tzset() since we must have the timezone and DST information
 * here. This is different to UNIX systems, where time() simply returns
 * the system time, which *is* UTC.
 */
time_t posix_time(time_t *clock)
{
	time_t t;

	if (this_year_end == 0) posix_tzset();
	time(&t);		/* system returns from 1-JAN-1970 local time */
	t += timezone;
	t += dst_offset(&t, &this_dston, &this_dstoff);
	if (clock != NULL) *clock = t;
	return(t);
}


void posix_ftime(struct timeb *tb)
{
	time_t t;

	if (this_year_end == 0) posix_tzset();
	ftime(tb);
	t = tb->time;
	tb->time += timezone;
	tb->time += dst_offset(&t, &this_dston, &this_dstoff);
	tb->timezone = timezone / 60;
	tb->dstflag = daylight;
}


/*
 * gettimeofday
 *
 * Note that the tz_dsttime element is not fully supported, we don't return
 * the DST values from sys/time.h here, only the dstflag from ftime().
 */
int posix_gettimeofday(struct timeval *tv, struct timezone *tz)
{
	struct timeb tb;

	posix_ftime(&tb);
	if (tv == NULL  &&  tz == NULL) return(-1);
	if (tv != NULL) {
		tv->tv_sec = tb.time;
		tv->tv_usec = tb.millitm * 1000;
	}
	if (tz != NULL) {
		tz->tz_minuteswest = tb.timezone;
		tz->tz_dsttime = tb.dstflag;
	}
	return(0);
}


/*
 * utime
 *
 * utime uses time_t clock values to set the file's dates.
 */
int posix_utime(const char *fname, const struct utimbuf *times)
{
	struct utimbuf timbuf;

	if (times == NULL) {
		time(&timbuf.actime);
		timbuf.modtime = timbuf.actime;
	}
	else {
		timbuf = *times;

		dst_setup(&timbuf.actime);  /* setup timezone and dst info */
		timbuf.actime -= timezone;
		timbuf.actime -= dst_offset(&timbuf.actime,
			&s_dston, &s_dstoff);

		dst_setup(&timbuf.modtime);  /* setup timezone and dst info */
		timbuf.modtime -= timezone;
		timbuf.modtime -= dst_offset(&timbuf.modtime,
			&s_dston, &s_dstoff);
	}
	return(vms_utime(fname, &timbuf));
}


int posix_stat(char *fname, struct stat *st_buf)
{
	int sts;

	sts = stat(fname, st_buf);
	if (sts < 0) return(sts);
	to_utc((time_t *)&st_buf->st_ctime);
	to_utc((time_t *)&st_buf->st_mtime);
	to_utc((time_t *)&st_buf->st_atime);
	return(sts);
}


int posix_lstat(char *fname, struct stat *st_buf)
{
	return(posix_stat(fname, st_buf));
}


int posix_fstat(int fd, struct stat *st_buf)
{
	int sts;

	sts = fstat(fd, st_buf);
	if (sts < 0) return(sts);
	to_utc((time_t *)&st_buf->st_ctime);
	to_utc((time_t *)&st_buf->st_mtime);
	to_utc((time_t *)&st_buf->st_atime);
	return(sts);
}


#if 0	/* DEBUG */
/* #define TST2	/**/

main(int argc, char *argv[])
{
	time_t t, t2;
	struct tm tm;

printf("=========== SYSTEM times ==============\n");

#ifdef TST2
	putenv("TZ=UTC");	/* set out physical time to UTC */
	if (argc >= 2) putenv(argv[1]);
	if (argc >= 3) putenv(argv[2]);
	tzset();
	printf(" _daylight = %d\n",_daylight);
	printf(" _timezone = %d\n",_timezone);
	printf(" _tzname[0] = {%s}\n",_tzname[0]);
	printf(" _tzname[1] = {%s}\n",_tzname[1]);
#endif

	time(&t);
printf("system time() = %08X\n\n",t);

	tm = *localtime(&t);
printf("localtime tm_hour = %d, tm_isdst = %d\n",tm.tm_hour,tm.tm_isdst);
printf("  mktime = %08X\n",mktime(&tm));
printf("  %s\n",asctime(&tm));

#ifndef VMS
	tm = *gmtime(&t);
printf("gmtime tm_hour = %d, tm_isdst = %d\n",tm.tm_hour,tm.tm_isdst);
printf("  mktime = %08X\n",mktime(&tm));
printf("  %s\n",asctime(&tm));
#endif
	
printf("\n=========== POSIX times ==============\n");

	printf(" daylight = %d\n",daylight);
	printf(" timezone = %d\n",timezone);
	printf(" tzname[0] = {%s}\n",tzname[0]);
	printf(" tzname[1] = {%s}\n",tzname[1]);

	posix_tzset(); /**/

	printf(" daylight = %d\n",daylight);
	printf(" timezone = %d\n",timezone);
	printf(" tzname[0] = {%s}\n",tzname[0]);
	printf(" tzname[1] = {%s}\n",tzname[1]);

	posix_time(&t);
printf("\nposix (UTC) time() = %08X\n\n",t);

	tm = *posix_localtime(&s_dston);
	printf(" dst begin = %08X, tm_hour = %d, tm_isdst = %d, %s",
		s_dston, tm.tm_hour,tm.tm_isdst,asctime(&tm));
	tm = *posix_localtime(&s_dstoff);
	printf(" dst end   = %08X, tm_hour = %d, tm_isdst = %d, %s\n",
		s_dstoff,tm.tm_hour,tm.tm_isdst,asctime(&tm));

	tm = *posix_gmtime(&t);
printf("gmtime tm_hour = %d, tm_isdst = %d\n",tm.tm_hour,tm.tm_isdst);
printf("  mktime = %08X\n",posix_mktime(&tm));
printf("  %s\n",asctime(&tm));
	
	tm = *posix_localtime(&t);
printf("localtime tm_hour = %d, tm_isdst = %d\n",tm.tm_hour,tm.tm_isdst);
printf("  mktime = %08X\n",posix_mktime(&tm));
printf("  %s\n",asctime(&tm));

printf("One year later...\n\n");
	tm.tm_year++;	/* display info for next year */
printf("localtime tm_hour = %d, tm_isdst = %d\n",tm.tm_hour,tm.tm_isdst);
printf("  mktime = %08X\n",posix_mktime(&tm));
printf("  %s\n",asctime(&tm));

}
#endif
