文章目錄
- ?介紹
- ?常量
- ??`CLOCKS_PER_SEC`
- ?類型
- ??`tm`
- ??`time_t`
- ??`clock_t`
- ??`timespec` (C11)
- ?函數-時間操作
- ??`time`
- 🏷?返回紀元開始經過的當前系統日歷時間
- ??`clock`
- 🏷?返回未加工的程序啟動時開始經過的處理器時間
- ??`difftime`
- 🏷?計算時間差
- ?函數-格式轉換-類型轉換
- ??`gmtime`
- 🏷?將從紀元開始的時間轉換成以協調世界時(UTC)表示的日歷時間
- 🏷?time_t -> tm
- ??`localtime`
- 🏷?將從紀元開始的時間轉換成以本地時間表示的日歷時間
- 🏷?time_t -> tm
- ??`mktime`
- 🏷?將日歷時間轉換成紀元開始經過的時間
- 🏷?tm -> time_t
- ?函數-格式轉換-文本表示
- ??`asctime`
- 🏷?將 `struct tm` 對象轉換成文本表示
- 🏷?tm -> str
- ??`ctime`
- 🏷?將 `struct time_t` 對象轉換成文本表示
- 🏷?time_t -> str
- ??`strftime`
- 🏷?將 `struct tm` 對象轉換成自定義文本表示
- 🏷?time_t -> copyToStr
- ?格式
- 🧮`Www Mmm dd hh:mm:ss yyyy\n`
- ?應用
- ??力扣[1185. 一周中的第幾天](https://leetcode.cn/problems/day-of-the-week/)
- ??力扣[1154. 一年中的第幾天](https://leetcode.cn/problems/day-of-the-year/)
- END
?介紹
日期和時間工具 - cppreference.com
<time.h>
是在C語言中的日期與時間工具。其中主要有三大模塊,常量,類型和函數。
在C++中推薦寫成<ctime>
,基本都是繼承.h中的東西。
函數主要分為兩類,時間操作
函數和格式轉換
函數。
本文主要為C語言中的標準操作,其中在C11和C23又添加和廢棄了許多內容,但這塊不會本文著重講解。
UTC 協調世界時
紀元(地球紀元)
夏令時
?常量
??CLOCKS_PER_SEC
- CLOCKS_PER_SEC - cppreference.com
- (宏常量)
- 處理器每秒的時間計數
- 一般來說都是數值1000
#include <stdio.h>
#include <time.h>int main(void) {clock_t beg = clock();clock_t end = clock();printf("Use time:%lf\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
}
?類型
??tm
-
tm - cppreference.com
-
(結構體)
-
日歷時間類型
struct tm {int tm_sec; // [秒 [0, 61] (C89) [0, 60] (C99)] seconds after the minuteint tm_min; // [分 [0, 59]] minutes after the hourint tm_hour; // [時 [0, 23]] hours since midnightint tm_mday; // [日 [1, 31]] day of the monthint tm_mon; // [月 [0, 11]] months since Januaryint tm_year; // [年 [1900:0]] years since 1900int tm_wday; // [周 [0, 6]] days since Sundayint tm_yday; // [第幾天 [0, 365]] days since January 1int tm_isdst; // [夏時令標簽] daylight savings time flag
};
#include <stdio.h>
#include <time.h>int main(void) {struct tm start = {.tm_mday = 1};mktime(&start);// Sun Jan 01 00:00:00 1900printf("%s\n", asctime(&start));
}
??time_t
- time_t - cppreference.com
- (typedef)
- 從紀元開始的日歷時間類型
??clock_t
- clock_t - cppreference.com
- (typedef)
- 從時點開始的處理器時間類型
??timespec
(C11)
- timespec - cppreference.com
- (結構體)
- 單位為秒和納秒的時間
// 保有時間間隔的結構體,將其拆分成秒數和納秒數。
struct timespec {time_t tv_sec; // [秒 >= 0] Seconds long tv_nsec; // [納秒 [0, 999999999]] Nanoseconds
};
timespec_get()
C11 返回基于給定時間基底的日歷時間
#include <stdint.h>
#include <stdio.h>
#include <time.h>int main(void) {struct timespec ts;// C11 函數// 修改 ts 所指向的 struct timespec 對象// 以保有以時間基底 base 表示的當前日歷時間。
#ifdef TIME_UTCtimespec_get(&ts, TIME_UTC);
#endifchar buff[100];strftime(buff, sizeof buff, "%D %T", gmtime(&ts.tv_sec));printf("Current time: %s.%09ld UTC\n", buff, ts.tv_nsec);printf("Raw timespec.time_t: %jd\n", (intmax_t)ts.tv_sec);printf("Raw timespec.tv_nsec: %09ld\n", ts.tv_nsec);
}
?函數-時間操作
??time
time - cppreference.com
🏷?返回紀元開始經過的當前系統日歷時間
time_t time( time_t *arg );
- 運行失敗
- return -1
- 運行成功
- 入參,返回值數值一致
#include <stdio.h>
#include <time.h>int main(void) {time_t in;time_t out = time(&in);// >success: out == in// >error: -1// 1709276388 = time(1709276388)printf("%ld = time(%ld)\n", out, in);return 0;
}
??clock
clock - cppreference.com
🏷?返回未加工的程序啟動時開始經過的處理器時間
clock_t clock(void);
最經典的應用就是計時器了。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>#define ARR_LEN (100000)// return (arg1 > arg2) - (arg1 < arg2); // 可行的簡寫
// return arg1 - arg2; // 錯誤的簡寫(若給出 INT_MIN 則會失敗)
int cmp(const void* a, const void* b) {int arg1 = *(const int*)a;int arg2 = *(const int*)b;if (arg1 < arg2) {return -1;}if (arg1 > arg2) {return 1;}return 0;
}int main(void) {int arr[ARR_LEN];clock_t beg = clock();qsort(arr, sizeof(arr) / sizeof(*arr), sizeof(int), cmp);clock_t end = clock();printf("Use time:%lf\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
}
??difftime
difftime - cppreference.com
🏷?計算時間差
double difftime( time_t time_end, time_t time_beg );
簡單測了下和直接相減效果一樣。可能是為了統一接口和適配器模式。
#include <stdio.h>
#include <time.h>int main(void) {time_t now = time(NULL);time_t beg = {0};// 計算時間差double during = difftime(now, beg);printf("Now:\t %lf\n", 1.0 * now);printf("During:\t %lf\n", during);
}
?函數-格式轉換-類型轉換
??gmtime
gmtime, gmtime_r, gmtime_s - cppreference.com
🏷?將從紀元開始的時間轉換成以協調世界時(UTC)表示的日歷時間
🏷?time_t -> tm
注意,這里存儲的是一個全局的靜態對象。
函數 gmtime
可能不是線程安全的。
struct tm *gmtime ( const time_t *timer );
#include <stdio.h>
#include <time.h>int main(void) {time_t t = time(NULL);struct tm *tm_p1 = gmtime(&t);struct tm *tm_p2 = gmtime(&t);// 指向同一個靜態對象printf("First struct tm* = %p\n", tm_p1);printf("Second struct tm* = %p\n", tm_p2);printf("UTC: %s", asctime(gmtime(&t)));printf("local: %s", asctime(localtime(&t)));
}
??localtime
localtime, localtime_r, localtime_s - cppreference.com
🏷?將從紀元開始的時間轉換成以本地時間表示的日歷時間
🏷?time_t -> tm
注意,這里存儲的是一個全局的靜態對象。
函數 localtime
可以不是線程安全的。
struct tm *localtime ( const time_t *timer );
#include <stdio.h>
#include <time.h>int main(void) {time_t t = time(NULL);struct tm *tm_p1 = localtime(&t);struct tm *tm_p2 = localtime(&t);// 指向同一個靜態對象printf("First struct tm* = %p\n", tm_p1);printf("Second struct tm* = %p\n", tm_p2);printf("UTC: %s", asctime(gmtime(&t)));printf("local: %s", asctime(localtime(&t)));
}
??mktime
mktime - cppreference.com
🏷?將日歷時間轉換成紀元開始經過的時間
🏷?tm -> time_t
time_t mktime( struct tm *time );
#include <stdio.h>
#include <stdlib.h>
#include <time.h>int main(void) {time_t now = time(NULL);// 獲取當前時間,并加一天struct tm tmm = *localtime(&now);tmm.tm_mday += 1;time_t nexDay = mktime(&tmm);printf("Now:\t%ld\n", now);printf("NexDay:\t%ld\n", nexDay);printf("OneDayTime:\t%lf\n", difftime(nexDay, now));printf("24*60*60=\t%d\n", 24 * 60 * 60);
}
?函數-格式轉換-文本表示
??asctime
asctime, asctime_s - cppreference.com
🏷?將 struct tm
對象轉換成文本表示
🏷?tm -> str
asctime
返回指向靜態數據的指針從而不是線程安全的。
char* asctime( const struct tm* time_ptr );
#include <stdio.h>
#include <time.h>int main(void) {struct tm tm = *localtime(&(time_t){time(NULL)});printf("%s\n", asctime(&tm));printf("%p\n", asctime(&tm));printf("%p\n", asctime(&tm));
}
??ctime
ctime, ctime_s - cppreference.com
🏷?將 struct time_t
對象轉換成文本表示
🏷?time_t -> str
char* ctime( const time_t* timer );
#include <stdio.h>
#include <time.h>int main(void) {time_t result = time(NULL);printf("%s\n", ctime(&result));printf("%p\n", ctime(&result));printf("%p\n", ctime(&result));
}
??strftime
strftime - cppreference.com
🏷?將 struct tm
對象轉換成自定義文本表示
🏷?time_t -> copyToStr
size_t strftime(char* str, size_t count, const char* format,const struct tm* time);
#include <stdio.h>
#include <time.h>int main(void) {struct tm now_tm = *localtime(&(time_t){time(NULL)});char buff[1024];// >strftime():Friday 03/01/24 19:41:24if (strftime(buff, sizeof buff, ">strftime():%A %c", &now_tm)) {puts(buff);} else {puts("strftime failed");}
}
?格式
🧮Www Mmm dd hh:mm:ss yyyy\n
// `asctime() & ctime()`以下固定的 25 字符表示形式: `Www Mmm dd hh:mm:ss yyyy\n`
errno_t asctime_s( char* buf, rsize_t bufsz, const struct tm* time_ptr );
errno_t ctime_s( char *buf, rsize_t bufsz, const time_t* timer );
Www
——來自time_ptr->tm_wday
的星期之日
的三字母英文縮寫,Mon
、Tue
、Wed
、Thu
、Fri
、Sat
、Sun
之一。Mmm
——來自time_ptr->tm_mon
的月
名的三字母英文縮寫,Jan
、Feb
、Mar
、Apr
、May
、Jun
、Jul
、Aug
、Sep
、Oct
、Nov
、Dec
之一。dd
——來自timeptr->tm_mday
的 2 位月之日
,如同由 sprintf 以%2d
打印hh
——來自timeptr->tm_hour
的 2 位時
,如同由 sprintf 以%.2d
打印mm
——來自timeptr->tm_min
的 2 位分
,如同由 sprintf 以%.2d
打印ss
——來自timeptr->tm_sec
的 2 位秒
,如同由 sprintf 以%.2d
打印yyyy
——來自timeptr->tm_year + 1900
的 4 位年
,如同由 sprintf 以%4d
打印
若是非法入參則行為未定義,如:
-
若
*time_ptr
的任何成員在其正常范圍外則行為未定義 -
若
time_ptr->tm_year
所指示的歷年擁有多于 4 位數或小于 1000 年則行為未定義。
自定義格式函數:
strftime()
的格式:strftime - cppreference.com
?應用
下面兩份是使用C++代碼表示。
其中主要用到的是<ctime>
的類型,還有一些別的庫中對時間操作的函數。
??力扣1185. 一周中的第幾天
給你一個日期,請你設計一個算法來判斷它是對應一周中的哪一天。
輸入為三個整數:
day
、month
和year
,分別表示日、月、年。您返回的結果必須是這幾個值中的一個
{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
。
static const std::string weekDays[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
};class Solution {
public:std::string dayOfTheWeek(int day, int month, int year) {std::tm ctm{};ctm.tm_year = year - 1900;ctm.tm_mon = month - 1;ctm.tm_mday = day;// a timestampstd::time_t ctime_t = std::mktime(&ctm);// return a static retctm = *std::localtime(&ctime_t);return weekDays[ctm.tm_wday];}
};
??力扣1154. 一年中的第幾天
給你一個字符串
date
,按YYYY-MM-DD
格式表示一個 現行公元紀年法 日期。返回該日期是當年的第幾天。
class Solution {
public:int dayOfYear(string date) {std::tm dt;std::istringstream(date) >> std::get_time(&dt, "%Y-%m-%d");return dt.tm_yday + 1;}
};