c時(shí)間函數(shù)strftime懒棉、struct timespec 和 struct timeval

時(shí)間和日期

由UNIX內(nèi)核提供的基本時(shí)間服務(wù)是計(jì)算自協(xié)調(diào)世界時(shí)(Coordinated Universal Time,UTC)公元1970年1月1日00:00:00這一特定 時(shí)間以來(lái)經(jīng)過的秒數(shù)逃沿。1.10節(jié)中曾提及這種秒數(shù)是以數(shù)據(jù)類型time_t表示 的烫幕,我們稱它們?yōu)槿諝v時(shí)間。日歷時(shí)間包括時(shí)間和日期澡腾。UNIX在這方 面與其他操作系統(tǒng)的區(qū)別是:(a)以協(xié)調(diào)統(tǒng)一時(shí)間而非本地時(shí)間計(jì) 時(shí);(b)可自動(dòng)進(jìn)行轉(zhuǎn)換沸伏,如變換到夏令時(shí);(c)將時(shí)間和日期作為 一個(gè)量值保存。

一般由函數(shù)int clock_gettime(clockid_t, struct timespec *)獲取特定時(shí)鐘的時(shí)間动分,常用如下4種時(shí)鐘:
CLOCK_REALTIME 統(tǒng)當(dāng)前時(shí)間毅糟,從1970年1.1日算起
CLOCK_MONOTONIC 系統(tǒng)的啟動(dòng)時(shí)間,不能被設(shè)置
CLOCK_PROCESS_CPUTIME_ID 本進(jìn)程運(yùn)行時(shí)間
CLOCK_THREAD_CPUTIME_ID 本線程運(yùn)行時(shí)間

struct tm *localtime(const time_t *clock);  //線程不安全
struct tm* localtime_r( const time_t* timer, struct tm* result );//線程安全
size_t strftime (char* ptr, size_t maxsize, const char* format,const struct tm* timeptr );

time函數(shù)返回當(dāng)前時(shí)間和日期澜公。

#include <time.h>
time_t time(time_t *calptr);

返回值:若成功姆另,返回時(shí)間值;若出錯(cuò),返回-1 時(shí)間值作為函數(shù)值返回坟乾。如果參數(shù)非空迹辐,則時(shí)間值也存放在由calptr
指向的單元內(nèi)。

POSXI.1的實(shí)時(shí)擴(kuò)展增加了對(duì)多個(gè)系統(tǒng)時(shí)鐘的支持甚侣。在Single UNIX
Specification V4中明吩,控制這些時(shí)鐘的接口從可選組被移至基本組。時(shí)鐘 通過clockid_t類型進(jìn)行標(biāo)識(shí)殷费。圖6-8給出了標(biāo)準(zhǔn)值印荔。


image.png

clock_gettime函數(shù)可用于獲取指定時(shí)鐘的時(shí)間低葫,返回的時(shí)間在4.2節(jié) 介紹的timespec結(jié)構(gòu)中,它把時(shí)間表示為秒和納秒仍律。

#include <sys/time.h>
int clock_gettime(clockid_t clock_id, struct timespec *tsp);

寫一段簡(jiǎn)單的代碼

#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>


int main() {
    time_t time_unix = time(NULL);
    printf("this  code is intended for time\n");
    printf("unix CST: %ld\n", time_unix);

    /* test clock_gettime. */
    struct timespec time_sys;
    int ret = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time_sys);
    printf("tv_nsec: %ld ns, tv_sec: %ld s\n", time_sys.tv_nsec, time_sys.tv_sec);
    return 0;
}
image.png

當(dāng)時(shí)鐘ID設(shè)置為CLOCK_REALTIME時(shí)嘿悬,clock_gettime函數(shù)提供了
與time函數(shù)類似的功能,不過在系統(tǒng)支持高精度時(shí)間值的情況下水泉, clock_gettime可能比time函數(shù)得到更高精度的時(shí)間值善涨。

#include <sys/time.h>
int clock_getres(clockid_t clock_id, struct timespec *tsp);

返回值:若成功,返回0;若出錯(cuò)茶行,返回-1 clock_getres函數(shù)把參數(shù)tsp指向的timespec結(jié)構(gòu)初始化為與clock_id參
數(shù)對(duì)應(yīng)的時(shí)鐘精度躯概。例如,如果精度為1毫秒畔师,則tv_sec字段就是0娶靡, tv_nsec字段就是1 000 000。

例如:

/*
 * @Author: machineplay
 * @Date: 2020-02-04 20:25:49
 * @Description: only for fun
 */
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/utsname.h>
#include <time.h>
#include <sys/time.h>
#include <string.h>


/**
 * main function.
 * @param 
 * @return: 0
 */
int main(int argc, char *argv[]) {

    /*  test time. */
    time_t now_time = time(NULL);
    printf("time_t :%ld\n", now_time);

    /* test sys_time. */
    int ret = 0;
    struct timespec time_sys;
    clock_getres(CLOCK_PROCESS_CPUTIME_ID, &time_sys);
    printf("process_time: %ld ns, %ld s\n", time_sys.tv_nsec, time_sys.tv_sec);
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time_sys);
    printf("process_time: %ld ns, %ld s\n", time_sys.tv_nsec, time_sys.tv_sec);

    

    return 0;
}

精度為1000ns


image.png

要對(duì)特定的時(shí)鐘設(shè)置時(shí)間看锉,可以調(diào)用clock_settime函數(shù)姿锭。

要對(duì)特定的時(shí)鐘設(shè)置時(shí)間,可以調(diào)用clock_settime函數(shù)伯铣。

#include <sys/time.h>
int clock_settime(clockid_t clock_id, const struct timespec *tsp);

返回值:若成功呻此,返回0;若出錯(cuò),返回-1 我們需要適當(dāng)?shù)奶貦?quán)來(lái)更改時(shí)鐘值腔寡,但是有些時(shí)鐘是不能修改的焚鲜。

SUSv4指定gettimeofday函數(shù)現(xiàn)在已棄用。然而放前,一些程序仍然使用 這個(gè)函數(shù)忿磅,因?yàn)榕ctime函數(shù)相比,gettimeofday提供了更高的精度(可到 微秒級(jí))凭语。

#include <sys/time.h>
int gettimeofday(struct timeval *restrict tp, void *restrict tzp);

tzp的唯一合法值是NULL葱她,其他值將產(chǎn)生不確定的結(jié)果。某些平臺(tái)
支持用tzp說(shuō)明時(shí)區(qū)似扔,但這完全依實(shí)現(xiàn)而定吨些,Single UNIX Specification對(duì) 此并沒有定義。

gettimeofday函數(shù)以距特定時(shí)間(1970年1月1日00 : 00 : 00)的秒數(shù)的 方式將當(dāng)前時(shí)間存放在tp指向的timeval結(jié)構(gòu)中炒辉,而該結(jié)構(gòu)將當(dāng)前時(shí)間表 示為秒和微秒豪墅。

一旦取得這種從上述特定時(shí)間經(jīng)過的秒數(shù)的整型時(shí)間值后,通常要 調(diào)用函數(shù)將其轉(zhuǎn)換為分解的時(shí)間結(jié)構(gòu)辆脸,然后調(diào)用另一個(gè)函數(shù)生成人們可 讀的時(shí)間和日期但校。圖6-9說(shuō)明了各種時(shí)間函數(shù)之間的關(guān)系。(圖中以虛 線表示的3個(gè)函數(shù)localtime啡氢、mktime和strftime都受到環(huán)境變量TZ的影響状囱, 我們將在本節(jié)的最后部分對(duì)其進(jìn)行說(shuō)明。點(diǎn)劃線表示了如何從時(shí)間相關(guān) 的結(jié)構(gòu)獲得日歷時(shí)間倘是。)
個(gè)函數(shù)localtime和gmtime將日歷時(shí)間轉(zhuǎn)換成分解的時(shí)間亭枷,并將這 些存放在一個(gè)tm結(jié)構(gòu)中。

struct  tm {     /* a broken-down time */ 
int  tm_sec;    /* seconds after the minute: [0 -
60] */
int  tm_min;    /* minutes after the hour: [0 - 59]
*/
int  tm_hour;   /* hours after midnight: [0 - 23] */ 
int  tm_mday;   /* day of the month: [1 - 31] */ 
int  tm_mon;    /* months since January: [0 - 11]
*/
int  tm_year;   /* years since 1900 */ 
int  tm_wday;   /* days since Sunday: [0 - 6] */ 
int  tm_yday;   /* days since January 1: [0 - 365]
*/
int  tm_isdst;  /* daylight saving time flag: <0, 0,
>0 */ };

秒可以超過59的理由是可以表示潤(rùn)秒搀崭。注意叨粘,除了月日字段,其他 字段的值都以0開始瘤睹。如果夏令時(shí)生效升敲,則夏令時(shí)標(biāo)志值為正;如果為 非夏令時(shí)時(shí)間,則該標(biāo)志值為0;如果此信息不可用轰传,則其值為負(fù)驴党。

Single UNIX Specification的以前版本允許雙潤(rùn)秒,于是获茬, tm_sec值的有效范圍是0~61港庄。
UTC的正式定義不允許雙潤(rùn)秒,所以恕曲,現(xiàn)在tm_sec值的有效范圍定 義為0~60鹏氧。


time
#include <time.h>
struct tm *gmtime(const time_t *calptr); struct tm *localtime(const time_t *calptr);

兩個(gè)函數(shù)的返回值:指向分解的tm結(jié)構(gòu)的指針;若出錯(cuò),返回NULL localtime和gmtime之間的區(qū)別是:localtime將日歷時(shí)間轉(zhuǎn)換成本地時(shí)
間(考慮到本地時(shí)區(qū)和夏令時(shí)標(biāo)志)佩谣,而 gmtime 則將日歷時(shí)間轉(zhuǎn)換成 協(xié)調(diào)統(tǒng)一時(shí)間的年把还、月、日茸俭、時(shí)吊履、分、秒瓣履、周日分解結(jié)構(gòu)率翅。
函數(shù)mktime以本地時(shí)間的年、月袖迎、日等作為參數(shù)冕臭,將其變換成 time_t值。

#include <time.h>
time_t mktime(struct tm *tmptr);

返回值:若成功燕锥,返回日歷時(shí)間;若出錯(cuò)辜贵,返回-1

函數(shù)strftime是一個(gè)類似于printf的時(shí)間值函數(shù)。它非常復(fù)雜归形,可以
通過可用的多個(gè)參數(shù)來(lái)定制產(chǎn)生的字符串托慨。

#include <time.h>
size_t strftime(char *restrict buf, size_t maxsize,
              const char *restrict format,
const struct tm *restrict tmptr);
size_t strftime_l(char *restrict buf, size_t maxsize,
              const char *restrict format,
const struct tm *restrict tmptr, locale_t locale);

兩個(gè)函數(shù)的返回值:若有空間,返回存入數(shù)組的字符數(shù);否則暇榴,返回0
兩個(gè)較早的函數(shù)——asctime和ctime能用于產(chǎn)生一個(gè)26字節(jié)的可打 印的字符串厚棵,類似于date(1)命令默認(rèn)的輸出蕉世。然而,這些函數(shù)現(xiàn)在已 經(jīng)被標(biāo)記為棄用婆硬,因?yàn)樗鼈円资艿骄彌_區(qū)溢出問題的影響狠轻。

strftime_l允許調(diào)用者將區(qū)域指定為參數(shù),除此之外彬犯,strftime和 strftime_l函數(shù)是相同的向楼。strftime使用通過TZ環(huán)境變量指定的區(qū)域。
tmptr參數(shù)是要格式化的時(shí)間值谐区,由一個(gè)指向分解時(shí)間值tm結(jié)構(gòu)的 指針說(shuō)明湖蜕。格式化結(jié)果存放在一個(gè)長(zhǎng)度為maxsize個(gè)字符的buf數(shù)組中, 如果buf長(zhǎng)度足以存放格式化結(jié)果及一個(gè)null終止符宋列,則該函數(shù)返回在buf 中存放的字符數(shù)(不包括null終止符);否則該函數(shù)返回0昭抒。
format參數(shù)控制時(shí)間值的格式。如同printf函數(shù)一樣虚茶,轉(zhuǎn)換說(shuō)明的形 式是百分號(hào)之后跟一個(gè)特定字符戈鲁。format中的其他字符則按原樣輸出。 兩個(gè)連續(xù)的百分號(hào)在輸出中產(chǎn)生一個(gè)百分號(hào)嘹叫。與printf函數(shù)的不同之處 是婆殿,每個(gè)轉(zhuǎn)換說(shuō)明產(chǎn)生一個(gè)不同的定長(zhǎng)輸出字符串,在format字符串中沒有字段寬度修飾符罩扇。圖6-10中列出了37種ISO C規(guī)定的轉(zhuǎn)換說(shuō)明婆芦。

image.png
#include <iostream>
#include <time.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>

int main() {
    /* time of timeval. */
    struct timeval now_time;

    int ret = gettimeofday(&now_time, NULL);
    printf("now_time since 1970: %d us, %ld s\n", now_time.tv_usec, now_time.tv_sec);

    /* time of timespec. */
    struct timespec time_spec;

    /* struct of tm*/
    struct tm detail_time;
    struct tm *tm_ptr = &detail_time;

    time_t tmp_time = time(NULL);
    printf("time_t : %ld\n", tmp_time);

    /* gmtime. */
    tm_ptr = gmtime(&tmp_time);


    /* show detail time. */
    printf("year: %d\n, month: %d\n, day: %d\n, hour: %d\n, min: %d\n, second %d\n",
           detail_time.tm_year, 
           detail_time.tm_mon, 
           detail_time.tm_mday, 
           detail_time.tm_hour, 
           detail_time.tm_min, 
           detail_time.tm_sec);

    /* test mktime. */
    tmp_time = mktime(tm_ptr);
    printf("timt_t after mktime %ld\n", tmp_time);

    /* change to localtime. */
    tm_ptr = localtime(&tmp_time);
    /* test strftime. */
    char buf[255];
    strftime(buf, sizeof(buf), "%c", tm_ptr);
    printf("strftime time: %s\n", buf);



    /* time */
    memset(buf, 0, 255);
    strftime(buf, sizeof(buf), "%Y%m%d,%H:%M:%S", tm_ptr);
    printf("time: %s\n", buf);
    return 0;

    /* local time. */
}


image.png
strptime函數(shù)是strftime的反過來(lái)版本,把字符串時(shí)間轉(zhuǎn)換成分解
時(shí)間喂饥。
#include <time.h>
char *strptime(const char *restrict buf, const char
*restrict format,
              struct tm *restrict tmptr);

所以記得strftime年月日時(shí)分秒

%Y-%m-%d %H:%M:%S
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末消约,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子员帮,更是在濱河造成了極大的恐慌或粮,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捞高,死亡現(xiàn)場(chǎng)離奇詭異氯材,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)硝岗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門氢哮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人型檀,你說(shuō)我怎么就攤上這事冗尤。” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵裂七,是天一觀的道長(zhǎng)皆看。 經(jīng)常有香客問我,道長(zhǎng)碍讯,這世上最難降的妖魔是什么悬蔽? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任扯躺,我火速辦了婚禮捉兴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘录语。我一直安慰自己倍啥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布澎埠。 她就那樣靜靜地躺著虽缕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蒲稳。 梳的紋絲不亂的頭發(fā)上氮趋,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音江耀,去河邊找鬼剩胁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛祥国,可吹牛的內(nèi)容都是我干的昵观。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼舌稀,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼啊犬!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起壁查,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤觉至,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后睡腿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體语御,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年嫉到,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沃暗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡何恶,死狀恐怖孽锥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤惜辑,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布唬涧,位于F島的核電站,受9級(jí)特大地震影響盛撑,放射性物質(zhì)發(fā)生泄漏碎节。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一抵卫、第九天 我趴在偏房一處隱蔽的房頂上張望狮荔。 院中可真熱鬧,春花似錦介粘、人聲如沸殖氏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)雅采。三九已至,卻和暖如春慨亲,著一層夾襖步出監(jiān)牢的瞬間婚瓜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工刑棵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留巴刻,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓铐望,卻偏偏與公主長(zhǎng)得像冈涧,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子正蛙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一.概念 在C/C++中督弓,通過學(xué)習(xí)許多C/C++庫(kù),你可以有很多操作乒验、使用時(shí)間的方法愚隧。但在這之前你需要了解一些“時(shí)...
    小辰帶你看世界閱讀 1,334評(píng)論 0 1
  • 一、Linux時(shí)間類型 在Linux系統(tǒng)當(dāng)中锻全,時(shí)間分為兩種類型:格林威治時(shí)間和日歷時(shí)間狂塘。 Coordinated ...
    konishi5202閱讀 3,461評(píng)論 0 4
  • 在Python中,日期和時(shí)間的應(yīng)用非常普遍鳄厌。在實(shí)際應(yīng)用中荞胡,大部分?jǐn)?shù)據(jù)的記錄和日志的處理都需要使用時(shí)間。這里將介紹P...
    瀧汰泱閱讀 883評(píng)論 0 0
  • 總結(jié)了一些開發(fā)中常用的函數(shù): usleep() //函數(shù)延遲代碼執(zhí)行若干微秒了嚎。 unpack() //函數(shù)從二進(jìn)制...
    ADL2022閱讀 454評(píng)論 0 3
  • 早上好泪漂,周一廊营。轉(zhuǎn)了陳為英500-500。合計(jì)1000元萝勤。交了尚莊電費(fèi)露筒。連續(xù)2個(gè)周末沒有休息去了九江,瑞昌敌卓,都昌慎式,九江等。
    b538b2ad5da3閱讀 151評(píng)論 0 0