2012-08-26 wcdj
由UNIX时间戳转换为系统时间
- date -d'1970-01-01 UTC 2147483647 seconds' +"%Y-%m-%d %T %z"
- 2038-01-19 11:14:07 +0800
- date -d'1970-01-01 UTC 2147483648 seconds' +"%Y-%m-%d %T %z"
- date: invalid date "1970-01-01 UTC 2147483648 seconds"
- date -d'1970-01-01 UTC 0 seconds' +"%Y-%m-%d %T"
- 1970-01-01 08:00:00 +0800
显示当前的UNIX时间戳
Unix时间与系统时间之间的转换
http://shijianchuo.911cha.com/
- /*
- * 2012-08-26 wcdj
- * 使用Gauss算法解决UNIX时间问题
- * 将UNIX时间2038-01-19 03:14:08
- * 支持扩大到2106-02-07 06:28:16
- */
- #include <stdio.h>
- #include <string.h>
- #include <time.h> // struct tm, mktime
- #include <sys/time.h> // gettimeofday
-
- #define MAX_TIME_DIFF (24*60*60)
- #define SECS_PER_HOUR (60 * 60)
- #define SECS_PER_DAY (SECS_PER_HOUR * 24)
-
-
- // calc microseconds
- long long get_time_of_day()
- {
- struct timeval tv;
- if (gettimeofday(&tv, NULL) == 0)
- {
- return tv.tv_sec * 1000000ULL + tv.tv_usec;
- }
- else
- {
- return 0;
- }
- }
-
-
- static long _timezone = MAX_TIME_DIFF+1;
-
- /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
- * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
- * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
- *
- * [For the Julian calendar (which was used in Russia before 1917,
- * Britain & colonies before 1752, anywhere else before 1582,
- * and is still in use by some communities) leave out the
- * -year/100+year/400 terms, and add 10.]
- *
- * This algorithm was first published by Gauss (I think).
- *
- * WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines were long is 32-bit! (However, as time_t is signed, we
- * will already get problems at other places on 2038-01-19 03:14:08)
- */
- static inline unsigned int
- my_mktime (unsigned int year, unsigned int mon,
- unsigned int day, unsigned int hour,
- unsigned int min, unsigned int sec)
- {
- if(_timezone == MAX_TIME_DIFF+1)
- {
- // 表示_timezone没有初始化
- struct timeval tv;
- struct timezone tz;
- gettimeofday(&tv, &tz);
- _timezone = tz.tz_minuteswest*60;
- }
-
-
- if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
- mon += 12; /* Puts Feb last since it has leap day */
- year -= 1;
- }
-
- /*START 防止"1970-01-01 00:00:00"到"1970-01-01 08:00:00"时间段的错误*/
-
- unsigned int iRet = (((
- (year/4 - year/100 + year/400 + 367*mon/12 + day) +
- year*365 - 719499
- )*24 + hour /* now have hours */
- )*60 + min /* now have minutes */
- )*60 + sec /* finally seconds */
- + _timezone; /* time_zone */
-
- if(iRet < 0)
- {
- iRet = 0;
- }
-
- return iRet;
-
- /*END*/
- }
-
-
- static long _timezone_ = MAX_TIME_DIFF+1;
- static const unsigned short int __mon_yday[2][13] =
- {
- /* Normal years. */
- { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
- /* Leap years. */
- { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
- };
-
-
- int my_localtime_r(unsigned int *timep, struct tm *result)
- {
- const unsigned short int *ip;
- if(_timezone_ == MAX_TIME_DIFF + 1)
- {
- struct timeval tv;
- struct timezone tz;
- gettimeofday(&tv, &tz);
- _timezone_ = tz.tz_minuteswest*60;
- }
-
- int days = (*timep) / SECS_PER_DAY;
- unsigned int rem = (*timep) % SECS_PER_DAY;
- rem -= _timezone_;
- while (rem < 0)
- {
- rem += SECS_PER_DAY;
- --days;
- }
- while (rem >= SECS_PER_DAY)
- {
- rem -= SECS_PER_DAY;
- ++days;
- }
-
- result->tm_hour = rem / SECS_PER_HOUR;
- rem %= SECS_PER_HOUR;
- result->tm_min = rem / 60;
- result->tm_sec = rem % 60;
- /* January 1, 1970 was a Thursday. */
- result->tm_wday = (4 + days) % 7;
- if (result->tm_wday < 0)
- result->tm_wday += 7;
-
- int y = 1970;
-
- #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
- #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
- #ifndef __isleap
- /* Nonzero if YEAR is a leap year (every 4 years,
- * * except every 100th isn't, and every 400th is). */
- # define __isleap(year) \
- ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
- #endif
-
- while (days < 0 || days >= (__isleap (y) ? 366 : 365))
- {
- /* Guess a corrected year, assuming 365 days per year. */
- long int yg = y + days / 365 - (days % 365 < 0);
-
- /* Adjust DAYS and Y to match the guessed year. */
- days -= ((yg - y) * 365
- + LEAPS_THRU_END_OF (yg - 1)
- - LEAPS_THRU_END_OF (y - 1));
- y = yg;
- }
- result->tm_year = y - 1900;
- if (result->tm_year != y - 1900)
- {
- /* The year cannot be represented due to overflow. */
- return -1;
- }
- result->tm_yday = days;
- ip = __mon_yday[__isleap(y)];
- for (y = 11; days < (long int) ip[y]; --y)
- continue;
- days -= ip[y];
- result->tm_mon = y;
- result->tm_mday = days + 1;
-
- return 0;
- }
-
-
-
- // return readable format time
- size_t get_date_str(time_t tsrc, char *buffer, size_t len)
- {
- struct tm tm = {0};
-
- /*
- * modify
- */
- //localtime_r(&tsrc, &tm);// the reentrant version
- my_localtime_r((unsigned int *)&tsrc, &tm);
-
-
- int iMicrosec = get_time_of_day() % 1000000;
-
- return snprintf(buffer, len, "%04d-%02d-%02d %02d:%02d:%02d %d",
- tm.tm_year + 1900,
- tm.tm_mon + 1,
- tm.tm_mday,
- tm.tm_hour,
- tm.tm_min,
- tm.tm_sec,
- iMicrosec);
- }
-
-
- int main(int argc, char** argv)
- {
-
- unsigned int now = get_time_of_day()/1000000;
- printf("unixi timestamp: %u\n", now);// date +%s
-
- char szTime[128] = {0};
- get_date_str(now, szTime, sizeof(szTime));
- printf("current time: [%s]\n", szTime);
-
-
- #if 1
- /* test for localtime_r*/
-
- // [1]
- now = 0;
- memset(szTime, 0x0, sizeof(szTime));
- get_date_str(now, szTime, sizeof(szTime));
- printf("time: [%s]\n", szTime);
-
- // [2]
- now = 4294967295U;// max of unsigned int
- memset(szTime, 0x0, sizeof(szTime));
- get_date_str(now, szTime, sizeof(szTime));
- printf("time: [%s]\n", szTime);
-
- // [3]
- now = 2147483647;// max of int
- memset(szTime, 0x0, sizeof(szTime));
- get_date_str(now, szTime, sizeof(szTime));
- printf("time: [%s]\n", szTime);
-
-
- #endif
-
-
- /* test for mktime */
- time_t rawtime;
- struct tm * timeinfo;
- int year, month, day;
- // prompt user for date
- printf("Enter year: ");scanf("%d", &year);
- printf("Enter month: ");scanf("%d", &month);
- printf("Enter day: ");scanf("%d", &day);
-
- // get current timeinfo and modify it to the user's choice
- time(&rawtime);
- timeinfo = localtime(&rawtime);
- timeinfo->tm_year = year - 1900;
- timeinfo->tm_mon = month -1;
- timeinfo->tm_mday = day;
-
- unsigned int rettime;
- /*if (-1 != (rettime = mktime(timeinfo)))
- {
- printf("mktime ret: %d\n", rettime);
- }
- else
- {
- printf("mktime err!\n");
- }*/
-
- if(timeinfo->tm_year + 1900 > 2106
- || (timeinfo->tm_year + 1900 == 2106 && timeinfo->tm_mon + 1 > 2)
- || (timeinfo->tm_year + 1900 == 2106 && timeinfo->tm_mon + 1 == 2 && timeinfo->tm_mday > 6))
- {
- printf("Error, overflow 4294967295!\n");
- }
- else
- {
- rettime = my_mktime(year, month, day, 0, 0, 0);
- printf("mktime ret: %u\n", rettime);
- }
-
-
-
- return 0;
- }
- /*
- output:
-
- unixi timestamp: 1345548878
- current time: [2012-08-21 19:34:38 737638]
- time: [1970-01-01 08:00:00 737648]
- time: [2106-02-07 14:28:15 737652]
- time: [2038-01-19 11:14:07 737655]
-
-
- */
参考
[1] Linux源码中的mktime算法解析
(关于Gauss算法的解释)
|