xref: /onnv-gate/usr/src/lib/libast/common/tm/tmxtime.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin /*
244887Schin  * Glenn Fowler
254887Schin  * AT&T Research
264887Schin  *
274887Schin  * Time_t conversion support
284887Schin  */
294887Schin 
304887Schin #include <tmx.h>
314887Schin 
324887Schin #include "FEATURE/tmlib"
334887Schin 
344887Schin /*
354887Schin  * convert Tm_t to Time_t
364887Schin  *
374887Schin  * if west==TM_LOCALZONE then the local timezone is used
384887Schin  * otherwise west is the number of minutes west
394887Schin  * of GMT with DST taken into account
404887Schin  *
414887Schin  * this routine works with a copy of Tm_t to avoid clashes
424887Schin  * with other tm*() that may return static Tm_t*
434887Schin  */
444887Schin 
454887Schin Time_t
tmxtime(register Tm_t * tm,int west)464887Schin tmxtime(register Tm_t* tm, int west)
474887Schin {
484887Schin 	register Time_t		t;
494887Schin 	register Tm_leap_t*	lp;
504887Schin 	register int32_t	y;
514887Schin 	int			n;
524887Schin 	int			sec;
534887Schin 	time_t			now;
544887Schin 	struct tm*		tl;
554887Schin 	Tm_t*			to;
564887Schin 	Tm_t			ts;
574887Schin 
584887Schin 	ts = *tm;
594887Schin 	to = tm;
604887Schin 	tm = &ts;
614887Schin 	tmset(tm_info.zone);
624887Schin 	tmfix(tm);
634887Schin 	y = tm->tm_year;
644887Schin 	if (y < 69 || y > (TMX_MAXYEAR - 1900))
654887Schin 		return TMX_NOTIME;
664887Schin 	y--;
674887Schin 	t = y * 365 + y / 4 - y / 100 + (y + (1900 - 1600)) / 400 - (1970 - 1901) * 365 - (1970 - 1901) / 4;
684887Schin 	if ((n = tm->tm_mon) > 11)
694887Schin 		n = 11;
704887Schin 	y += 1901;
714887Schin 	if (n > 1 && tmisleapyear(y))
724887Schin 		t++;
734887Schin 	t += tm_data.sum[n] + tm->tm_mday - 1;
744887Schin 	t *= 24;
754887Schin 	t += tm->tm_hour;
764887Schin 	t *= 60;
774887Schin 	t += tm->tm_min;
784887Schin 	t *= 60;
794887Schin 	t += sec = tm->tm_sec;
804887Schin 	if (west != TM_UTCZONE && !(tm_info.flags & TM_UTC))
814887Schin 	{
824887Schin 		/*
834887Schin 		 * time zone adjustments
844887Schin 		 */
854887Schin 
864887Schin 		if (west == TM_LOCALZONE)
874887Schin 		{
884887Schin 			t += tm_info.zone->west * 60;
894887Schin 			if (!tm_info.zone->daylight)
904887Schin 				tm->tm_isdst = 0;
914887Schin 			else
924887Schin 			{
934887Schin 				y = tm->tm_year;
944887Schin 				tm->tm_year = tmequiv(tm) - 1900;
954887Schin 				now = tmxsec(tmxtime(tm, tm_info.zone->west));
964887Schin 				tm->tm_year = y;
974887Schin 				if (!(tl = tmlocaltime(&now)))
984887Schin 					return TMX_NOTIME;
994887Schin 				if (tm->tm_isdst = tl->tm_isdst)
1004887Schin 					t += tm_info.zone->dst * 60;
1014887Schin 			}
1024887Schin 		}
1034887Schin 		else
1044887Schin 		{
1054887Schin 			t += west * 60;
1064887Schin 			if (!tm_info.zone->daylight)
1074887Schin 				tm->tm_isdst = 0;
1084887Schin 			else if (tm->tm_isdst < 0)
1094887Schin 			{
1104887Schin 				y = tm->tm_year;
1114887Schin 				tm->tm_year = tmequiv(tm) - 1900;
1124887Schin 				tm->tm_isdst = 0;
1134887Schin 				now = tmxsec(tmxtime(tm, tm_info.zone->west));
1144887Schin 				tm->tm_year = y;
1154887Schin 				if (!(tl = tmlocaltime(&now)))
1164887Schin 					return TMX_NOTIME;
1174887Schin 				tm->tm_isdst = tl->tm_isdst;
1184887Schin 			}
1194887Schin 		}
1204887Schin 	}
1214887Schin 	else if (tm->tm_isdst)
1224887Schin 		tm->tm_isdst = 0;
1234887Schin 	*to = *tm;
1244887Schin 	if (tm_info.flags & TM_LEAP)
1254887Schin 	{
1264887Schin 		/*
1274887Schin 		 * leap second adjustments
1284887Schin 		 */
1294887Schin 
1304887Schin 		for (lp = &tm_data.leap[0]; t < lp->time - (lp+1)->total; lp++);
1314887Schin 		t += lp->total;
1324887Schin 		n = lp->total - (lp+1)->total;
1334887Schin 		if (t <= (lp->time + n) && (n > 0 && sec > 59 || n < 0 && sec > (59 + n) && sec <= 59))
1344887Schin 			t -= n;
1354887Schin 	}
1364887Schin 	return tmxsns(t, tm->tm_nsec);
1374887Schin }
138