xref: /openbsd-src/usr.bin/rcs/rcstime.c (revision 099bc3622b4e1de69ecf60616221f4e660477a82)
1*099bc362Sguenther /*	$OpenBSD: rcstime.c,v 1.6 2016/08/26 09:02:54 guenther Exp $	*/
22dc36bedSjoris /*
32dc36bedSjoris  * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
42dc36bedSjoris  * All rights reserved.
52dc36bedSjoris  *
62dc36bedSjoris  * Redistribution and use in source and binary forms, with or without
72dc36bedSjoris  * modification, are permitted provided that the following conditions
82dc36bedSjoris  * are met:
92dc36bedSjoris  *
102dc36bedSjoris  * 1. Redistributions of source code must retain the above copyright
112dc36bedSjoris  *    notice, this list of conditions and the following disclaimer.
122dc36bedSjoris  * 2. The name of the author may not be used to endorse or promote products
132dc36bedSjoris  *    derived from this software without specific prior written permission.
142dc36bedSjoris  *
152dc36bedSjoris  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
162dc36bedSjoris  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
172dc36bedSjoris  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
182dc36bedSjoris  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
192dc36bedSjoris  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
202dc36bedSjoris  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
212dc36bedSjoris  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
222dc36bedSjoris  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
232dc36bedSjoris  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
242dc36bedSjoris  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
252dc36bedSjoris  */
262dc36bedSjoris 
274781e2faSxsa #include <err.h>
284781e2faSxsa #include <stdlib.h>
294781e2faSxsa #include <string.h>
30*099bc362Sguenther #include <time.h>
312dc36bedSjoris 
322dc36bedSjoris #include "rcs.h"
332dc36bedSjoris 
342dc36bedSjoris void
rcs_set_tz(char * tz,struct rcs_delta * rdp,struct tm * tb)352dc36bedSjoris rcs_set_tz(char *tz, struct rcs_delta *rdp, struct tm *tb)
362dc36bedSjoris {
372dc36bedSjoris 	int tzone;
382dc36bedSjoris 	int pos;
392dc36bedSjoris 	char *h, *m;
405a713317Sotto 	const char *errstr;
412dc36bedSjoris 	struct tm *ltb;
422dc36bedSjoris 	time_t now;
432dc36bedSjoris 
442dc36bedSjoris 	if (!strcmp(tz, "LT")) {
452dc36bedSjoris 		now = mktime(&rdp->rd_date);
462dc36bedSjoris 		ltb = localtime(&now);
472dc36bedSjoris 		ltb->tm_hour += ((int)ltb->tm_gmtoff/3600);
48cbab9f86Sniallo 		memcpy(tb, ltb, sizeof(*tb));
492dc36bedSjoris 	} else {
502dc36bedSjoris 		pos = 0;
512dc36bedSjoris 		switch (*tz) {
522dc36bedSjoris 		case '-':
532dc36bedSjoris 			break;
542dc36bedSjoris 		case '+':
552dc36bedSjoris 			pos = 1;
562dc36bedSjoris 			break;
572dc36bedSjoris 		default:
582dc36bedSjoris 			errx(1, "%s: not a known time zone", tz);
592dc36bedSjoris 		}
602dc36bedSjoris 
612dc36bedSjoris 		h = (tz + 1);
622dc36bedSjoris 		if ((m = strrchr(tz, ':')) != NULL)
632dc36bedSjoris 			*(m++) = '\0';
642dc36bedSjoris 
65cbab9f86Sniallo 		memcpy(tb, &rdp->rd_date, sizeof(*tb));
662dc36bedSjoris 
675a713317Sotto 		tzone = strtonum(h, -23, 23, &errstr);
685a713317Sotto 		if (errstr)
692dc36bedSjoris 			errx(1, "%s: not a known time zone", tz);
702dc36bedSjoris 
712dc36bedSjoris 		if (pos) {
722dc36bedSjoris 			tb->tm_hour += tzone;
732dc36bedSjoris 			tb->tm_gmtoff += (tzone * 3600);
742dc36bedSjoris 		} else {
752dc36bedSjoris 			tb->tm_hour -= tzone;
762dc36bedSjoris 			tb->tm_gmtoff -= (tzone * 3600);
772dc36bedSjoris 		}
782dc36bedSjoris 
792dc36bedSjoris 		if ((tb->tm_hour >= 24) || (tb->tm_hour <= -24))
802dc36bedSjoris 			tb->tm_hour = 0;
812dc36bedSjoris 
822dc36bedSjoris 		if (m != NULL) {
835a713317Sotto 			tzone = strtonum(m, 0, 59, &errstr);
845a713317Sotto 			if (errstr)
855a713317Sotto 				errx(1, "%s: not a known minute", m);
862dc36bedSjoris 
872dc36bedSjoris 			if ((tb->tm_min + tzone) >= 60) {
882dc36bedSjoris 				tb->tm_hour++;
892dc36bedSjoris 				tb->tm_min -= (60 - tzone);
902dc36bedSjoris 			} else
912dc36bedSjoris 				tb->tm_min += tzone;
922dc36bedSjoris 
932dc36bedSjoris 			tb->tm_gmtoff += (tzone*60);
942dc36bedSjoris 		}
952dc36bedSjoris 	}
962dc36bedSjoris }
97