C&C++中的时间函数和时间类
现代标准时间:协调世界时,又称世界统一时间、世界标准时间、国际协调时间。由于英文(CUT)和法文(TUC)的缩写不同,作为妥协,简称UTC。协调世界时是以原子时秒长为基础,在时刻上尽量接近于世界时的一种时间计量系统。
C语言的 time 函数和 localtime 函数 (基于格林威治标准时间(GMT))
#pragma warning(disable : 4996)//disable error C4996 #include <time.h> int main() { time_t t = time(NULL);//获取当前时间句柄, time_t 就是 int64 tm* ptime = localtime(&t);//将时间句柄转换为时间结构体tm, localtime 以前的函数可能会报 error C4996 /* 用 localtime_s() tm time; localtime_s(&time, &t); tm* ptime = &time; */ int nYear = ptime->tm_year + 1900; int nMonth = ptime->tm_mon + 1; int nDay = ptime->tm_mday; int nHour = ptime->tm_hour; int nMinute = ptime->tm_min; int nSecond = ptime->tm_sec; printf("%d-%02d-%02d %02d:%02d:%02d", nYear, nMonth, nDay, nHour, nMinute, nSecond); // time_t t = time(NULL); // char* s = ctime(&t);//"Sat Sep 14 11:06:08 2019\n" return 0; }
C++的CTime类(MFC中),其实就是对上面的封装。(基于格林威治标准时间(GMT))
#define _AFXDLL #include <afx.h> int main() { CTime t = CTime::GetCurrentTime(); int nYear = t.GetYear(); int nMonth = t.GetMonth(); int nDay = t.GetDay(); int nHour = t.GetHour(); int nMinute = t.GetMinute(); int nSecond = t.GetSecond(); printf("%d-%02d-%02d %02d:%02d:%02d", nYear, nMonth, nDay, nHour, nMinute, nSecond); //或者直接format CString s = t.Format("%Y-%m-%d %H:%M:%S");//2019-09-14 10:47:03 return 0; }
VC6.0下,在CTime中,年的范围是1970到2038(包含2038)。距1970-1-1 12:0:0 am 也就是2的32次方秒. (当 time_t 是32位的)
在time_t 是 int64 时,CTime类表示日期上限是3000年12月31日,下限是1970年1月1日 12:00:00 AM GMT。
2038年问题
和21世纪初的千年虫(the Millennium bug)问题类似,32位的Unix操作系统和Linux操作系统时间溢出问题又称为2038年问题(the Year 2038 problem)。如果你想知道什么是2038问题的话,你需要知道一些技术上的东西。这个bug是由用来写Unix/Linux的C语言引起的,C语言中用 time_t 来代表时间和日期,time_t 是整数(int)型的,它用来记载从1970年1月1日到2000年所经历的秒数。
这个数据是以32位存储的,第一位是符号位,其余的31位用来存数字,而这31位数字可以存储的最大数字为2147483647。
从1970年开始计算,这31位的数字可以表示的秒数最多可以用到2038年01月19日03时14分07秒,当时间到达这个数字的时候系统将会出现问题,到时候数字不会自动增加,而是会变为-2147483648,而这串数字代表的时间是1901年12月13日20时45分52秒,这会导致很多的程序出现问题,甚至崩溃。
2038年问题不仅比千年虫更隐蔽,而且比之前千年虫问题更具有破坏力,因为千年虫问题只会导致应用层的程序出现问题,比如信用卡支付系统,或者管理系统。而2038这个bug,将会影响系统最底层的时间控制的功能。
要解决这个问题,最简单的方式是扩展Unix时间的长度,用64位数字来表示它。64位二进制数的实际可用位数是63位,最大表示到公历的UTC时间292,277,026,596年12月4日15时30分08秒. 如果那个时候人类文明还存在的话,公元纪年很可能已经因为太难用而被抛弃了. 理想的情况是到2038年,64位系统已经成为主流,从而避免特意去修正这个问题所需要的大量开销。否则,人们就必须把新的64位时间拆分成两部分并分别保存在两个变量里,这是一个麻烦而且效率低下的选择.
MFC中的 COleDateTime,COleDateTime类处理了从100年1月1日到9999年12月31日的日期。
#define _AFXDLL #include <afx.h> #include <afxdisp.h> int main() { COleDateTime t = COleDateTime::GetCurrentTime(); int nYear = t.GetYear(); int nMonth = t.GetMonth(); int nDay = t.GetDay(); int nHour = t.GetHour(); int nMinute = t.GetMinute(); int nSecond = t.GetSecond(); printf("%d-%02d-%02d %02d:%02d:%02d", nYear, nMonth, nDay, nHour, nMinute, nSecond); //或者直接format CString s = t.Format(_T("%Y-%m-%d %H:%M:%S"));//2019-09-14 10:47:03 return 0; }
%a: 周的英文缩写形式。 %A: 周的英文全名形式。 %b: 月的英文缩写形式。 %B: 月的英文全名形式。 %c: 完整的日期和时间。 %d: 十进制形式的日期(01-31)。 %H: 24小时制的小时(00-23)。 %I: 12小时制的小时(00-11)。 %j: 十进制表示的一年中的第几天(001-366)。 %m: 月的十进制表示(01-12)。 %M: 十进制表示的分钟(00-59)。 %p: 12小时制的上下午标示(AM/PM)。 %S: 十进制表示的秒(00-59)。 %U: 一年中的第几个星期(00-51),星期日是一周的第一天。 %W: 一年中的第几个星期(00-51),星期一是一周的第一天。 %w: 十进制表示的星期几(0-6)。 %Y: 十进制表示的年。
常记溪亭日暮,沉醉不知归路。兴尽晚回舟,误入藕花深处。争渡,争渡,惊起一滩鸥鹭。
昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否?知否?应是绿肥红瘦。