gmtime的实现

struct tm __time_tm;	/* Global shared by gmtime() and localtime(). */
#define time_t uint32_t 
struct tm *_time_t2tm(const time_t * timer,
					  int offset, struct tm * result)
{
	int *p;
	time_t t1, t, v;
	int wday = wday; /* ok to be uninitialized, shutting up warning */

	{
		const uint16_t *vp;
		t = *timer;
		p = (int *) result;
		p[7] = 0;
		vp = _vals;
		do {
			if ((v = *vp) == 7) {
				/* Overflow checking, assuming time_t is long int... */

				/* We have days since the epoch, so caluclate the weekday. */

				wday = ((int)((t % (*vp)) + 11)) % ((int)(*vp)); /* help bcc */
				/* Set divisor to days in 400 years.  Be kind to bcc... */
				v = ((time_t)(vp[1])) << 2;
				++v;
				/* Change to days since 1/1/1601 so that for 32 bit time_t
				 * values, we'll have t >= 0.  This should be changed for
				 * archs with larger time_t types.
				 * Also, correct for offset since a multiple of 7. */

				/* TODO: Does this still work on archs with time_t > 32 bits? */
				t += (135140L - 366) + offset; /* 146097 - (365*30 + 7) -366 */
			}

			if ((t -= ((t1 = t / v) * v)) < 0) {
				t += v;
				--t1;
			}

			if ((*vp == 7) && (t == v-1)) {
				--t;			/* Correct for 400th year leap case */
				++p[4];			/* Stash the extra day... */
			}


			if (v <= 60) {
				*p++ = t;
				t = t1;
			} else {
				*p++ = t1;
			}
		} while (*++vp);
	}

	if (p[-1] == 4) {
		--p[-1];
		t = 365;
	}

	*p += ((int) t);			/* result[7] .. tm_yday */

	p -= 2;						/* at result[5] */


	*p = ((((p[-2]<<2) + p[-1])*25 + p[0])<< 2) + p[1] - 299; /* tm_year */

	p[1] = wday;				/* result[6] .. tm_wday */

	{
		const unsigned char *d = days;

		wday = 1900 + *p;
		if (isleap(wday)) {
			d += 11;
		}

		wday = p[2] + 1;		/* result[7] .. tm_yday */
		*--p = 0;				/* at result[4] .. tm_mon */
		while (wday > *d) {
			wday -= *d;
			if (*d == 29) {
				d -= 11;		/* Backup to non-leap Feb. */
			}
			++d;
			++*p;				/* Increment tm_mon. */
		}
		p[-1] = wday;			/* result[3] .. tm_mday */
	}
	/* TODO -- should this be 0? */
	p[4] = 0;					/* result[8] .. tm_isdst */
	
	return result;
}

#endif

struct tm *gmtime(int32_t *timer)
{
	struct tm *ptm = &__time_tm;

	_time_t2tm(timer, 0, ptm); /* Can return NULL... */

	return ptm;
}

开源库代码,程序在32位mcu上跑通。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
static __time64_t __cdecl _make__time64_t ( struct tm *tb, int ultflag ) { __time64_t tmptm1, tmptm2, tmptm3; struct tm tbtemp; long dstbias = 0; long timezone = 0; _VALIDATE_RETURN( ( tb != NULL ), EINVAL, ( ( __time64_t )( -1 ) ) ) /* * First, make sure tm_year is reasonably close to being in range. */ if ( ((tmptm1 = tb->tm_year) < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR64 + 1) ) goto err_mktime; /* * Adjust month value so it is in the range 0 - 11. This is because * we don't know how many days are in months 12, 13, 14, etc. */ if ( (tb->tm_mon < 0) || (tb->tm_mon > 11) ) { tmptm1 += (tb->tm_mon / 12); if ( (tb->tm_mon %= 12) < 0 ) { tb->tm_mon += 12; tmptm1--; } /* * Make sure year count is still in range. */ if ( (tmptm1 < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR64 + 1) ) goto err_mktime; } /***** HERE: tmptm1 holds number of elapsed years *****/ /* * Calculate days elapsed minus one, in the given year, to the given * month. Check for leap year and adjust if necessary. */ tmptm2 = _days[tb->tm_mon]; if ( _IS_LEAP_YEAR(tmptm1) && (tb->tm_mon > 1) ) tmptm2++; /* * Calculate elapsed days since base date (midnight, 1/1/70, UTC) * * * 365 days for each elapsed year since 1970, plus one more day for * each elapsed leap year. no danger of overflow because of the range * check (above) on tmptm1. */ tmptm3 = (tmptm1 - _BASE_YEAR) * 365 + _ELAPSED_LEAP_YEARS(tmptm1); /* * elapsed days to current month (still no possible overflow) */ tmptm3 += tmptm2; /* * elapsed days to current date. */ tmptm1 = tmptm3 + (tmptm2 = (__time64_t)(tb->tm_mday)); /***** HERE: tmptm1 holds number of elapsed days *****/ /* * Calculate elapsed hours since base date */ tmptm2 = tmptm1 * 24; tmptm1 = tmptm2 + (tmptm3 = (__time64_t)tb->tm_hour); /***** HERE: tmptm1 holds number of elapsed hours *****/ /* * Calculate elapsed minutes since base date */ tmptm2 = tmptm1 * 60; tmptm1 = tmptm2 + (tmptm3 = (__time64_t)tb->tm_min); /***** HERE: tmptm1 holds number of elapsed minutes *****/ /* * Calculate elapsed seconds since base date */ tmptm2 = tmptm1 * 60; tmptm1 = tmptm2 + (tmptm3 = (__time64_t)tb->tm_sec); /***** HERE: tmptm1 holds number of elapsed seconds *****/ if ( ultflag ) { /* * Adjust for timezone. No need to check for overflow since * localtime() will check its arg value */ __tzset(); _ERRCHECK(_get_dstbias(&dstbias;)); _ERRCHECK(_get_timezone(&timezone;)); tmptm1 += timezone; /* * Convert this second count back into a time block structure. * If localtime returns NULL, return an error. */ if ( _localtime64_s(&tbtemp;, &tmptm1;) != 0 ) goto err_mktime; /* * Now must compensate for DST. The ANSI rules are to use the * passed-in tm_isdst flag if it is non-negative. Otherwise, * compute if DST applies. Recall that tbtemp has the time without * DST compensation, but has set tm_isdst correctly. */ if ( (tb->tm_isdst > 0) || ((tb->tm_isdst < 0) && (tbtemp.tm_isdst > 0)) ) { tmptm1 += dstbias; if ( _localtime64_s(&tbtemp;, &tmptm1;) != 0 ) goto err_mktime; } } else { if ( _gmtime64_s(&tbtemp;, &tmptm1;) != 0) goto err_mktime; } /***** HERE: tmptm1 holds number of elapsed seconds, adjusted *****/ /***** for local time if requested *****/ *tb = tbtemp; return tmptm1; err_mktime: /* * All errors come to here */ errno = EINVAL; return (__time64_t)(-1); }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值