整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          【嵌入式】自己寫mktime、localtime函數

          世紀秒指自1970年1月1日0時0分0秒至某一日期時間經過的秒數。有些應用場景中,需要將日期時間轉換為世紀秒,或者將世紀秒轉換為日期時間。

          c/c++庫中已經有相關的函數,由time.h中的mktime函數和函數分別實現上述兩個轉換。但time.h只能實現32位的世紀秒運算,最大支持到2038年;且mktime、默認的時間基準年份都是1970年1月1日,倘若需要獲得以任意年為基準的“世紀秒”,還需要考慮自己寫函數實現。

          下面通過自己寫這兩個函數,相比于mktime、有以下兩個優點:

          1.用64位大大擴大了時間戳,最長時間戳為,而時間戳為時就已經到3137年10月10日5:43:28了。彌補了時間戳最大截至到2038年的缺點;

          2.可定義年為基準,不僅僅是1970.

          我在以下函數中實現了兩種轉換,分別是和,用最簡單粗暴、容易理解的邏輯書寫,效率肯定比不上linux中的短小精悍的mktime函數,但是可以彌補以上兩個缺點。有興趣的可以去看一下理解一下Linux源碼中的mktime算法解析

          需要注意的地方都以注釋說明。在main函數中進行了從1970年1月1日到2030年1月1日步進為1秒的函數正確性測試,分別驗證自己寫的函數是否和mktime、計算結果一至,結果表明沒有問題。

          #include
          #include
          #define BASE_YEAR	70	//世紀秒的年份基準,BASE_YEAR = 基準年份 - 1900
          #define BASE_MON	1	//世紀秒的月份基準,一般是1月
          #define BASE_DAY	1	//世紀秒的日基準  ,一般是1日
          						//時分秒都默認是0
          //初始時間
          #define YEAR	(1970 - 1900)	
          #define MON		(1 - 1)			//月[0,11],以適應time.h中的struct tm
          #define DAY		1
          #define HOUR	8
          #define MIN		0
          #define SEC		0
          //是否是UTC時間,單片機中使用為1(因為沒有設置時區),電腦中使用需要為0(因為電腦調用time.h中的相關函數時,調用了系統時區)
          #define USE_UTC 0
          //月份天數表
          unsigned char Montbl[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
          //是否閏年
          unsigned char IsLeap(int year)
          {
          	unsigned char res = 0;
          	if( (year % 4 == 0) && (year % 4 != 100) )
          	{
          		res = 1;
          	}
          	return res;
          }
          //計算世紀秒 從BASE_YEAR-BASE_MON-BASE_DAY 0時0分0秒到某一時間經過的秒
          //注意,tm_mon = [0,11]
          //后期要對輸入的時間加合法判定
          _int64 my_mktime(struct tm* p)
          {
          	_int64 res = 0;
          	int year_s = BASE_YEAR, mon_s = 0;
          	unsigned char leap = 0;//最新年份是否閏年
          	if( IsLeap(p->tm_year + 1900))
          	{
          		leap = 1;
          	}
          	//按年累加
          	while(year_s < p->tm_year)
          	{
          		res += 365 * 24 * 3600;
          		if(IsLeap(year_s + 1900))
          		{
          			res += 24 * 3600;
          		}
          		year_s++;
          	}
          	//具體到月
          	while(mon_s < p->tm_mon)
          	{
          		//如果月份為2且是閏年
          		if(mon_s == 1 && leap)
          		{
          			res += (Montbl[mon_s] + 1) * 24 * 3600;
          		}
          		else
          		{
          			res += Montbl[mon_s] * 24 * 3600;
          		}
          		mon_s++;
          	}
          	//具體到日
          	res += (p->tm_mday - 1) * 24 * 3600;
          	//具體到時分秒
          

          linux系統時間時間秒數_時間linux_linux時間戳換算

          res += 3600 * p->tm_hour + 60 * p->tm_min + p->tm_sec; //如果加上了本地時區(東八區) if(!USE_UTC) { res -= 3600 * 8; } return res; } //世紀秒轉換成日期時間 void my_localtime(_int64 cs,struct tm *p) { int year_s = BASE_YEAR,mon_s = 0 ; //如果加上了本地時區(東八區) if(!USE_UTC) { cs += 3600 * 8; } //算年份 while(1) { if(IsLeap(year_s + 1900)) { if((cs - 3600 * 24 * 366) >= 0) { cs -= 3600 * 24 * 366; year_s++; } else { break; } } else { if((cs - 3600 * 24 * 365) >= 0) { cs -= 3600 * 24 * 365; year_s++; } else { break; } } } p->tm_year = year_s; //算月份 while(1) { //如果到了2月,且是閏年 if(mon_s == 1 && IsLeap(year_s + 1900)) { if(cs - (Montbl[mon_s] + 1)* 24 * 3600 >= 0) { cs -= (Montbl[mon_s] + 1)* 24 * 3600 ; mon_s++; } else { break; } } else { if(cs - Montbl[mon_s] * 24 * 3600 >= 0) { cs -= Montbl[mon_s] * 24 * 3600; mon_s++; } else { break; } } } p->tm_mon = mon_s; //算日期 p->tm_mday = cs / (3600 * 24) + 1; //算時分秒 cs %= (3600 * 24); p->tm_hour = cs / 3600; cs %= 3600; p->tm_min = cs / 60; cs %= 60; p->tm_sec = cs; }

          時間linux_linux時間戳換算_linux系統時間時間秒數

          int main(void) { _int64 sys_tm,my_tm;//系統函數計算的世紀秒和我自己的函數計算的世紀秒 struct tm* psys = (struct tm*)malloc(sizeof(struct tm));//系統函數計算的日期時間 struct tm* pmy = (struct tm*)malloc(sizeof(struct tm));//我自己的函數計算的日期時間 int cnt = 0;//用于打印 memset(psys,0,sizeof(struct tm)); memset(pmy,0,sizeof(struct tm)); psys->tm_year = YEAR; psys->tm_mon = MON; psys->tm_mday = DAY; psys->tm_hour = HOUR; psys->tm_min = MIN; psys->tm_sec = SEC; psys->tm_isdst = -1; //測試初始值2020-1-1 8:0:0 //迭代運算,與系統的mktime() localtime()做比較 //測試到2030-1-1 8:0:0 do { //由日期時間獲得世紀秒 sys_tm = mktime(psys); my_tm = my_mktime(psys); //判斷自己的函數和系統函數獲得的世紀秒是否相等 if(sys_tm != my_tm) { printf("err my_mktime when sys_tm is :%I64d\n",my_tm); break; } //世界秒加一 sys_tm++; //由世紀秒反推到日期時間 psys = localtime(&sys_tm); my_localtime(sys_tm,pmy); //判斷自己的函數和系統函數獲得的日期時間是否一樣 if(psys->tm_year != pmy->tm_year || psys->tm_mon != pmy->tm_mon || psys->tm_mday != pmy->tm_mday || psys->tm_hour != pmy->tm_hour || psys->tm_min != pmy->tm_min || psys->tm_sec != pmy->tm_sec) { printf("err my_localtime when sys_tm is :%d\n",sys_tm); break; } //秒每走過一天打印一次進度 //防止printf過多耗費大量時間 if(cnt++ >= 3600 * 24) { cnt = 0; //2030-1-1 8:0:0的世紀秒為1893456000 提前獲取這個值用于進度計算 printf(".2lf%%\t%d-d-d d:d:d\r", (double)(sys_tm)* 100 / (1893456000.0) , psys->tm_year+1900, psys->tm_mon + 1, psys->tm_mday, psys->tm_hour, psys->tm_min, psys->tm_sec); } }while(sys_tm <= 1893456000); printf("Test End\n"); return 0; }


          主站蜘蛛池模板: 国产日韩一区二区三区在线观看 | 色窝窝免费一区二区三区| 鲁大师成人一区二区三区| 无码国产精品一区二区免费模式| 视频一区二区三区在线观看| 精品中文字幕一区二区三区四区| 亚洲国产精品成人一区| 久久精品一区二区免费看| 区三区激情福利综合中文字幕在线一区亚洲视频1 | 成人精品视频一区二区| 黑人一区二区三区中文字幕| 国精产品一区一区三区免费视频| 国产精品视频一区二区三区经| 一区二区三区在线看| 3d动漫精品啪啪一区二区中| 国产一区二区草草影院| 精品一区精品二区| 精品无码国产一区二区三区AV| 伊人色综合网一区二区三区| 色一情一乱一伦一区二区三区日本| 一区二区三区影院| 海角国精产品一区一区三区糖心 | 国产成人精品无码一区二区 | 精品久久一区二区三区| 国产精品一区二区香蕉| 台湾无码一区二区| 国产在线不卡一区| 亚洲国产综合精品中文第一区| 日韩精品一区二区三区不卡| 久久精品无码一区二区WWW| 激情内射日本一区二区三区| 在线观看日韩一区| 国产情侣一区二区| 精品国产aⅴ无码一区二区| www.亚洲一区| 亚洲欧洲一区二区三区| 精品国产亚洲第一区二区三区| 激情内射亚洲一区二区三区| 中文字幕在线无码一区| 一区二区三区日本电影| 日韩精品一区二区三区不卡|