11573Srgrimes/*
21573Srgrimes * Copyright (c) 1987, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * Redistribution and use in source and binary forms, with or without
61573Srgrimes * modification, are permitted provided that the following conditions
71573Srgrimes * are met:
81573Srgrimes * 1. Redistributions of source code must retain the above copyright
91573Srgrimes *    notice, this list of conditions and the following disclaimer.
101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111573Srgrimes *    notice, this list of conditions and the following disclaimer in the
121573Srgrimes *    documentation and/or other materials provided with the distribution.
131573Srgrimes * 4. Neither the name of the University nor the names of its contributors
141573Srgrimes *    may be used to endorse or promote products derived from this software
151573Srgrimes *    without specific prior written permission.
161573Srgrimes *
171573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271573Srgrimes * SUCH DAMAGE.
281573Srgrimes */
291573Srgrimes
301573Srgrimes#if defined(LIBC_SCCS) && !defined(lint)
311573Srgrimesstatic char sccsid[] = "@(#)timezone.c	8.1 (Berkeley) 6/4/93";
321573Srgrimes#endif /* LIBC_SCCS and not lint */
3390041Sobrien#include <sys/cdefs.h>
3490041Sobrien__FBSDID("$FreeBSD$");
351573Srgrimes
361573Srgrimes#include <sys/types.h>
371573Srgrimes#include <sys/time.h>
381573Srgrimes#include <stdio.h>
391573Srgrimes#include <stdlib.h>
401573Srgrimes#include <string.h>
419935Swollman#define TZ_MAX_CHARS 255
421573Srgrimes
43200150Sedchar *_tztab(int, int);
441573Srgrimes
451573Srgrimes/*
461573Srgrimes * timezone --
471573Srgrimes *	The arguments are the number of minutes of time you are westward
481573Srgrimes *	from Greenwich and whether DST is in effect.  It returns a string
491573Srgrimes *	giving the name of the local timezone.  Should be replaced, in the
501573Srgrimes *	application code, by a call to localtime.
511573Srgrimes */
521573Srgrimes
531573Srgrimesstatic char	czone[TZ_MAX_CHARS];		/* space for zone name */
541573Srgrimes
551573Srgrimeschar *
56200150Sedtimezone(int zone, int dst)
571573Srgrimes{
5890041Sobrien	char	*beg,
591573Srgrimes			*end;
601573Srgrimes
6117141Sjkh	if ( (beg = getenv("TZNAME")) ) {	/* set in environment */
6217141Sjkh		if ( (end = index(beg, ',')) ) {/* "PST,PDT" */
631573Srgrimes			if (dst)
641573Srgrimes				return(++end);
651573Srgrimes			*end = '\0';
661573Srgrimes			(void)strncpy(czone,beg,sizeof(czone) - 1);
671573Srgrimes			czone[sizeof(czone) - 1] = '\0';
681573Srgrimes			*end = ',';
691573Srgrimes			return(czone);
701573Srgrimes		}
711573Srgrimes		return(beg);
721573Srgrimes	}
731573Srgrimes	return(_tztab(zone,dst));	/* default: table or created zone */
741573Srgrimes}
751573Srgrimes
761573Srgrimesstatic struct zone {
771573Srgrimes	int	offset;
781573Srgrimes	char	*stdzone;
791573Srgrimes	char	*dlzone;
801573Srgrimes} zonetab[] = {
8117141Sjkh	{-1*60,	"MET",	"MET DST"},	/* Middle European */
8217141Sjkh	{-2*60,	"EET",	"EET DST"},	/* Eastern European */
8317141Sjkh	{4*60,	"AST",	"ADT"},		/* Atlantic */
8417141Sjkh	{5*60,	"EST",	"EDT"},		/* Eastern */
8517141Sjkh	{6*60,	"CST",	"CDT"},		/* Central */
8617141Sjkh	{7*60,	"MST",	"MDT"},		/* Mountain */
8717141Sjkh	{8*60,	"PST",	"PDT"},		/* Pacific */
881573Srgrimes#ifdef notdef
891573Srgrimes	/* there's no way to distinguish this from WET */
9017141Sjkh	{0,	"GMT",	0},		/* Greenwich */
911573Srgrimes#endif
9217141Sjkh	{0*60,	"WET",	"WET DST"},	/* Western European */
9317141Sjkh	{-10*60,"EST",	"EST"},		/* Aust: Eastern */
9417141Sjkh     {-10*60+30,"CST",	"CST"},		/* Aust: Central */
9517141Sjkh	{-8*60,	"WST",	0},		/* Aust: Western */
9617141Sjkh	{-1}
971573Srgrimes};
981573Srgrimes
991573Srgrimes/*
1001573Srgrimes * _tztab --
1011573Srgrimes *	check static tables or create a new zone name; broken out so that
1021573Srgrimes *	we can make a guess as to what the zone is if the standard tables
1031573Srgrimes *	aren't in place in /etc.  DO NOT USE THIS ROUTINE OUTSIDE OF THE
1041573Srgrimes *	STANDARD LIBRARY.
1051573Srgrimes */
1061573Srgrimeschar *
107200150Sed_tztab(int zone, int dst)
1081573Srgrimes{
10990041Sobrien	struct zone	*zp;
11090041Sobrien	char	sign;
1111573Srgrimes
1121573Srgrimes	for (zp = zonetab; zp->offset != -1;++zp)	/* static tables */
1131573Srgrimes		if (zp->offset == zone) {
1141573Srgrimes			if (dst && zp->dlzone)
1151573Srgrimes				return(zp->dlzone);
1161573Srgrimes			if (!dst && zp->stdzone)
1171573Srgrimes				return(zp->stdzone);
1181573Srgrimes		}
1191573Srgrimes
1201573Srgrimes	if (zone < 0) {					/* create one */
1211573Srgrimes		zone = -zone;
1221573Srgrimes		sign = '+';
1231573Srgrimes	}
1241573Srgrimes	else
1251573Srgrimes		sign = '-';
12632687Simp	(void)snprintf(czone, sizeof(czone),
12732687Simp	    "GMT%c%d:%02d",sign,zone / 60,zone % 60);
1281573Srgrimes	return(czone);
1291573Srgrimes}
130