122695Sdist /*
234920Sbostic  * Copyright (c) 1983 Eric P. Allman
333728Sbostic  * Copyright (c) 1988 Regents of the University of California.
433728Sbostic  * All rights reserved.
533728Sbostic  *
633728Sbostic  * Redistribution and use in source and binary forms are permitted
734920Sbostic  * provided that the above copyright notice and this paragraph are
834920Sbostic  * duplicated in all such forms and that any documentation,
934920Sbostic  * advertising materials, and other materials related to such
1034920Sbostic  * distribution and use acknowledge that the software was developed
1134920Sbostic  * by the University of California, Berkeley.  The name of the
1234920Sbostic  * University may not be used to endorse or promote products derived
1334920Sbostic  * from this software without specific prior written permission.
1434920Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1534920Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1634920Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1733728Sbostic  */
1822695Sdist 
1922695Sdist #ifndef lint
20*36529Sbostic static char sccsid[] = "@(#)arpadate.c	5.10 (Berkeley) 01/08/89";
2133728Sbostic #endif /* not lint */
2222695Sdist 
239152Seric # include "conf.h"
2416895Seric # include <time.h>
252897Seric # include <sys/types.h>
264437Seric # include "useful.h"
27293Seric 
28293Seric /*
29293Seric **  ARPADATE -- Create date in ARPANET format
30293Seric **
31293Seric **	Parameters:
322897Seric **		ud -- unix style date string.  if NULL, one is created.
33293Seric **
34293Seric **	Returns:
35293Seric **		pointer to an ARPANET date field
36293Seric **
37293Seric **	Side Effects:
38293Seric **		none
39293Seric **
40293Seric **	WARNING:
41293Seric **		date is stored in a local buffer -- subsequent
42293Seric **		calls will overwrite.
433185Seric **
443185Seric **	Bugs:
453185Seric **		Timezone is computed from local time, rather than
463185Seric **		from whereever (and whenever) the message was sent.
473185Seric **		To do better is very hard.
484315Seric **
494315Seric **		Some sites are now inserting the timezone into the
504315Seric **		local date.  This routine should figure out what
514315Seric **		the format is and work appropriately.
52293Seric */
53293Seric 
541586Seric char *
552897Seric arpadate(ud)
562897Seric 	register char *ud;
57293Seric {
58293Seric 	register char *p;
592897Seric 	register char *q;
60*36529Sbostic 	register int off;
61*36529Sbostic 	register int i;
62*36529Sbostic 	register struct tm *lt;
63*36529Sbostic 	time_t t;
64*36529Sbostic 	struct tm gmt;
65293Seric 	static char b[40];
66*36529Sbostic 	extern struct tm *localtime(), *gmtime();
671586Seric 	extern char *ctime();
68*36529Sbostic 	extern time_t time();
69293Seric 
704315Seric 	/*
714315Seric 	**  Get current time.
724315Seric 	**	This will be used if a null argument is passed and
734315Seric 	**	to resolve the timezone.
744315Seric 	*/
754315Seric 
764315Seric 	(void) time(&t);
772897Seric 	if (ud == NULL)
782897Seric 		ud = ctime(&t);
79293Seric 
804315Seric 	/*
814315Seric 	**  Crack the UNIX date line in a singularly unoriginal way.
824315Seric 	*/
834315Seric 
842897Seric 	q = b;
852897Seric 
8613932Seric 	p = &ud[0];		/* Mon */
8713932Seric 	*q++ = *p++;
8813932Seric 	*q++ = *p++;
8913932Seric 	*q++ = *p++;
9013932Seric 	*q++ = ',';
9113932Seric 	*q++ = ' ';
9213932Seric 
93293Seric 	p = &ud[8];		/* 16 */
94293Seric 	if (*p == ' ')
95293Seric 		p++;
962897Seric 	else
972897Seric 		*q++ = *p++;
982897Seric 	*q++ = *p++;
9910251Seric 	*q++ = ' ';
1002897Seric 
1015184Seric 	p = &ud[4];		/* Sep */
1025184Seric 	*q++ = *p++;
1035184Seric 	*q++ = *p++;
1045184Seric 	*q++ = *p++;
10510251Seric 	*q++ = ' ';
1062897Seric 
10713932Seric 	p = &ud[22];		/* 79 */
1085184Seric 	*q++ = *p++;
1095184Seric 	*q++ = *p++;
1102897Seric 	*q++ = ' ';
1112897Seric 
1122897Seric 	p = &ud[11];		/* 01:03:52 */
1135184Seric 	for (i = 8; i > 0; i--)
1142897Seric 		*q++ = *p++;
1152897Seric 
116*36529Sbostic 	/*
117*36529Sbostic 	 * should really get the timezone from the time in "ud" (which
118*36529Sbostic 	 * is only different if a non-null arg was passed which is different
119*36529Sbostic 	 * from the current time), but for all practical purposes, returning
120*36529Sbostic 	 * the current local zone will do (its all that is ever needed).
121*36529Sbostic 	 */
122*36529Sbostic 	gmt = *gmtime(&t);
123*36529Sbostic 	lt = localtime(&t);
1242897Seric 
125*36529Sbostic 	off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min;
12615109Skarels 
127*36529Sbostic 	/* assume that offset isn't more than a day ... */
128*36529Sbostic 	if (lt->tm_year < gmt.tm_year)
129*36529Sbostic 		off -= 24 * 60;
130*36529Sbostic 	else if (lt->tm_year > gmt.tm_year)
131*36529Sbostic 		off += 24 * 60;
132*36529Sbostic 	else if (lt->tm_yday < gmt.tm_yday)
133*36529Sbostic 		off -= 24 * 60;
134*36529Sbostic 	else if (lt->tm_yday > gmt.tm_yday)
135*36529Sbostic 		off += 24 * 60;
13615109Skarels 
137*36529Sbostic 	*q++ = ' ';
138*36529Sbostic 	if (off == 0) {
139*36529Sbostic 		*q++ = 'G';
140*36529Sbostic 		*q++ = 'M';
141*36529Sbostic 		*q++ = 'T';
142*36529Sbostic 	} else {
143*36529Sbostic 		if (off < 0) {
144*36529Sbostic 			off = -off;
145*36529Sbostic 			*q++ = '-';
146*36529Sbostic 		} else
147*36529Sbostic 			*q++ = '+';
14815109Skarels 
149*36529Sbostic 		if (off >= 24*60)		/* should be impossible */
150*36529Sbostic 			off = 23*60+59;		/* if not, insert silly value */
15115137Seric 
152*36529Sbostic 		*q++ = (off / 600) + '0';
153*36529Sbostic 		*q++ = (off / 60) % 10 + '0';
154*36529Sbostic 		off %= 60;
155*36529Sbostic 		*q++ = (off / 10) + '0';
156*36529Sbostic 		*q++ = (off % 10) + '0';
15715137Seric 	}
158*36529Sbostic 	*q = '\0';
159*36529Sbostic 
160*36529Sbostic 	return (b);
16115109Skarels }
162