⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 localtime.c

📁 asterisk 是一个很有知名度开源软件
💻 C
📖 第 1 页 / 共 4 页
字号:
				}			}			theirdstoffset = 0;			for (i = 0; i < sp->timecnt; ++i) {				j = sp->types[i];				if (sp->ttis[j].tt_isdst) {					theirdstoffset =						-sp->ttis[j].tt_gmtoff;					break;				}			}			/*			** Initially we're assumed to be in standard time.			*/			isdst = FALSE;			theiroffset = theirstdoffset;			/*			** Now juggle transition times and types			** tracking offsets as you do.			*/			for (i = 0; i < sp->timecnt; ++i) {				j = sp->types[i];				sp->types[i] = sp->ttis[j].tt_isdst;				if (sp->ttis[j].tt_ttisgmt) {					/* No adjustment to transition time */				} else {					/*					** If summer time is in effect, and the					** transition time was not specified as					** standard time, add the summer time					** offset to the transition time;					** otherwise, add the standard time					** offset to the transition time.					*/					/*					** Transitions from DST to DDST					** will effectively disappear since					** POSIX provides for only one DST					** offset.					*/					if (isdst && !sp->ttis[j].tt_ttisstd) {						sp->ats[i] += dstoffset -							theirdstoffset;					} else {						sp->ats[i] += stdoffset -							theirstdoffset;					}				}				theiroffset = -sp->ttis[j].tt_gmtoff;				if (sp->ttis[j].tt_isdst)					theirdstoffset = theiroffset;				else	theirstdoffset = theiroffset;			}			/*			** Finally, fill in ttis.			** ttisstd and ttisgmt need not be handled.			*/			sp->ttis[0].tt_gmtoff = -stdoffset;			sp->ttis[0].tt_isdst = FALSE;			sp->ttis[0].tt_abbrind = 0;			sp->ttis[1].tt_gmtoff = -dstoffset;			sp->ttis[1].tt_isdst = TRUE;			sp->ttis[1].tt_abbrind = stdlen + 1;			sp->typecnt = 2;		}	} else {		dstlen = 0;		sp->typecnt = 1;		/* only standard time */		sp->timecnt = 0;		sp->ttis[0].tt_gmtoff = -stdoffset;		sp->ttis[0].tt_isdst = 0;		sp->ttis[0].tt_abbrind = 0;	}	sp->charcnt = stdlen + 1;	if (dstlen != 0)		sp->charcnt += dstlen + 1;	if ((size_t) sp->charcnt > sizeof sp->chars)		return -1;	cp = sp->chars;	(void) strncpy(cp, stdname, stdlen);	cp += stdlen;	*cp++ = '\0';	if (dstlen != 0) {		(void) strncpy(cp, dstname, dstlen);		*(cp + dstlen) = '\0';	}	return 0;}static int gmtload(struct state *sp){	if (tzload(gmt, sp, TRUE) != 0)		return tzparse(gmt, sp, TRUE);	else		return -1;}static const struct state *ast_tzset(const char *zone){	struct state *sp;	if (ast_strlen_zero(zone))		zone = "/etc/localtime";	AST_LIST_LOCK(&zonelist);	AST_LIST_TRAVERSE(&zonelist, sp, list) {		if (!strcmp(sp->name, zone)) {			AST_LIST_UNLOCK(&zonelist);			return sp;		}	}	AST_LIST_UNLOCK(&zonelist);	if (!(sp = ast_calloc(1, sizeof *sp)))		return NULL;	if (tzload(zone, sp, TRUE) != 0) {		if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0)			(void) gmtload(sp);	}	ast_copy_string(sp->name, zone, sizeof(sp->name));	AST_LIST_LOCK(&zonelist);	AST_LIST_INSERT_TAIL(&zonelist, sp, list);	AST_LIST_UNLOCK(&zonelist);	return sp;}/*! \note** The easy way to behave "as if no library function calls" localtime** is to not call it--so we drop its guts into "localsub", which can be** freely called. (And no, the PANS doesn't require the above behavior--** but it *is* desirable.)**** The unused offset argument is for the benefit of mktime variants.*/static struct ast_tm *localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp){	const struct ttinfo *	ttisp;	int			i;	struct ast_tm *		result;	struct timeval	t;	memcpy(&t, timep, sizeof(t));	if (sp == NULL)		return gmtsub(timep, offset, tmp);	if ((sp->goback && t.tv_sec < sp->ats[0]) ||		(sp->goahead && t.tv_sec > sp->ats[sp->timecnt - 1])) {			struct timeval	newt = t;			time_t		seconds;			time_t		tcycles;			int_fast64_t	icycles;			if (t.tv_sec < sp->ats[0])				seconds = sp->ats[0] - t.tv_sec;			else	seconds = t.tv_sec - sp->ats[sp->timecnt - 1];			--seconds;			tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;			++tcycles;			icycles = tcycles;			if (tcycles - icycles >= 1 || icycles - tcycles >= 1)				return NULL;			seconds = icycles;			seconds *= YEARSPERREPEAT;			seconds *= AVGSECSPERYEAR;			if (t.tv_sec < sp->ats[0])				newt.tv_sec += seconds;			else	newt.tv_sec -= seconds;			if (newt.tv_sec < sp->ats[0] ||				newt.tv_sec > sp->ats[sp->timecnt - 1])					return NULL;	/* "cannot happen" */			result = localsub(&newt, offset, tmp, sp);			if (result == tmp) {				time_t	newy;				newy = tmp->tm_year;				if (t.tv_sec < sp->ats[0])					newy -= icycles * YEARSPERREPEAT;				else					newy += icycles * YEARSPERREPEAT;				tmp->tm_year = newy;				if (tmp->tm_year != newy)					return NULL;			}			return result;	}	if (sp->timecnt == 0 || t.tv_sec < sp->ats[0]) {		i = 0;		while (sp->ttis[i].tt_isdst) {			if (++i >= sp->typecnt) {				i = 0;				break;			}		}	} else {		int	lo = 1;		int	hi = sp->timecnt;		while (lo < hi) {			int	mid = (lo + hi) >> 1;			if (t.tv_sec < sp->ats[mid])				hi = mid;			else				lo = mid + 1;		}		i = (int) sp->types[lo - 1];	}	ttisp = &sp->ttis[i];	/*	** To get (wrong) behavior that's compatible with System V Release 2.0	** you'd replace the statement below with	**	t += ttisp->tt_gmtoff;	**	timesub(&t, 0L, sp, tmp);	*/	result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);	tmp->tm_isdst = ttisp->tt_isdst;#ifndef SOLARIS /* Solaris doesn't have this element */	tmp->tm_gmtoff = ttisp->tt_gmtoff;#endif#ifdef TM_ZONE	tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];#endif /* defined TM_ZONE */	tmp->tm_usec = timep->tv_usec;	return result;}struct ast_tm *ast_localtime(const struct timeval *timep, struct ast_tm *tmp, const char *zone){	const struct state *sp = ast_tzset(zone);	memset(tmp, 0, sizeof(*tmp));	return sp ? localsub(timep, 0L, tmp, sp) : NULL;}/*** This function provides informaton about daylight savings time ** for the given timezone.  This includes whether it can determine ** if daylight savings is used for this timezone, the UTC times for ** when daylight savings transitions, and the offset in seconds from ** UTC. */void ast_get_dst_info(const time_t * const timep, int *dst_enabled, time_t *dst_start, time_t *dst_end, int *gmt_off, const char * const zone){	int i;		int transition1 = -1;	int transition2 = -1;	time_t		seconds;	int  bounds_exceeded = 0;	time_t  t = *timep;	const struct state *sp;		if (NULL == dst_enabled)		return;	*dst_enabled = 0;	if (NULL == dst_start || NULL == dst_end || NULL == gmt_off)		return;	*gmt_off = 0; 		sp = ast_tzset(zone);	if (NULL == sp) 		return;		/* If the desired time exceeds the bounds of the defined time transitions  	* then give give up on determining DST info and simply look for gmt offset 	* This requires that I adjust the given time using increments of Gregorian 	* repeats to place the time within the defined time transitions in the 	* timezone structure.  	*/	if ((sp->goback && t < sp->ats[0]) ||			(sp->goahead && t > sp->ats[sp->timecnt - 1])) {		time_t		tcycles;		int_fast64_t	icycles;		if (t < sp->ats[0])			seconds = sp->ats[0] - t;		else	seconds = t - sp->ats[sp->timecnt - 1];		--seconds;		tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;		++tcycles;		icycles = tcycles;		if (tcycles - icycles >= 1 || icycles - tcycles >= 1)			return;		seconds = icycles;		seconds *= YEARSPERREPEAT;		seconds *= AVGSECSPERYEAR;		if (t < sp->ats[0])			t += seconds;		else			t -= seconds;				if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1])			return;	/* "cannot happen" */		bounds_exceeded = 1;	}	if (sp->timecnt == 0 || t < sp->ats[0]) {		/* I have no transition times or I'm before time */		*dst_enabled = 0;		/* Find where I can get gmtoff */		i = 0;		while (sp->ttis[i].tt_isdst)			if (++i >= sp->typecnt) {			i = 0;			break;			}			*gmt_off = sp->ttis[i].tt_gmtoff;			return;	} 	for (i = 1; i < sp->timecnt; ++i) {		if (t < sp->ats[i]) {			transition1 = sp->types[i - 1];			transition2 = sp->types[i];			break;		} 	}	/* if I found transition times that do not bounded the given time and these correspond to 		or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */	if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 ||			(sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) {		*dst_enabled = 0;		*gmt_off 	 = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff;	} else {		/* I have valid daylight savings information. */		if(sp->ttis[transition2].tt_isdst) 			*gmt_off = sp->ttis[transition1].tt_gmtoff;		else 			*gmt_off = sp->ttis[transition2].tt_gmtoff;		/* If I adjusted the time earlier, indicate that the dst is invalid */		if (!bounds_exceeded) {			*dst_enabled = 1;			/* Determine which of the bounds is the start of daylight savings and which is the end */			if(sp->ttis[transition2].tt_isdst) {				*dst_start = sp->ats[i];				*dst_end = sp->ats[i -1];			} else {				*dst_start = sp->ats[i -1];				*dst_end = sp->ats[i];			}		}	}		return;}/*** gmtsub is to gmtime as localsub is to localtime.*/static struct ast_tm *gmtsub(const struct timeval *timep, const long offset, struct ast_tm *tmp){	struct ast_tm *	result;	struct state *sp;	AST_LIST_LOCK(&zonelist);	AST_LIST_TRAVERSE(&zonelist, sp, list) {		if (!strcmp(sp->name, "UTC"))			break;	}	if (!sp) {		if (!(sp = (struct state *) ast_calloc(1, sizeof *sp)))			return NULL;		gmtload(sp);		AST_LIST_INSERT_TAIL(&zonelist, sp, list);	}	AST_LIST_UNLOCK(&zonelist);	result = timesub(timep, offset, sp, tmp);#ifdef TM_ZONE	/*	** Could get fancy here and deliver something such as	** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,	** but this is no time for a treasure hunt.	*/	if (offset != 0)		tmp->TM_ZONE = "    ";	else		tmp->TM_ZONE = sp->chars;#endif /* defined TM_ZONE */	return result;}/*! \brief** Return the number of leap years through the end of the given year** where, to make the math easy, the answer for year zero is defined as zero.*/static int leaps_thru_end_of(const int y){	return (y >= 0) ? (y / 4 - y / 100 + y / 400) :		-(leaps_thru_end_of(-(y + 1)) + 1);}static struct ast_tm *timesub(const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp){	const struct lsinfo *	lp;	time_t			tdays;	int			idays;	/* unsigned would be so 2003 */	long			rem;	int				y;	const int *		ip;	long			corr;	int			hit;	int			i;	long	seconds;	corr = 0;	hit = 0;	i = (sp == NULL) ? 0 : sp->leapcnt;	while (--i >= 0) {		lp = &sp->lsis[i];		if (timep->tv_sec >= lp->ls_trans) {			if (timep->tv_sec == lp->ls_trans) {				hit = ((i == 0 && lp->ls_corr > 0) ||					lp->ls_corr > sp->lsis[i - 1].ls_corr);				if (hit)					while (i > 0 &&						sp->lsis[i].ls_trans ==						sp->lsis[i - 1].ls_trans + 1 &&						sp->lsis[i].ls_corr ==						sp->lsis[i - 1].ls_corr + 1) {							++hit;							--i;					}			}			corr = lp->ls_corr;			break;		}	}	y = EPOCH_YEAR;	tdays = timep->tv_sec / SECSPERDAY;	rem = timep->tv_sec - tdays * SECSPERDAY;	while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {		int		newy;		time_t	tdelta;		int	idelta;		int	leapdays;		tdelta = tdays / DAYSPERLYEAR;		idelta = tdelta;		if (tdelta - idelta >= 1 || idelta - tdelta >= 1)			return NULL;		if (idelta == 0)			idelta = (tdays < 0) ? -1 : 1;		newy = y;		if (increment_overflow(&newy, idelta))			return NULL;		leapdays = leaps_thru_end_of(newy - 1) -			leaps_thru_end_of(y - 1);		tdays -= ((time_t) newy - y) * DAYSPERNYEAR;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -