C语言中的时间
高斯日记:
大数学家高斯有个好习惯:无论如何都要记日记。
他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210
后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?
高斯出生于:1777年4月30日。
在高斯发现的一个重要定理的日记上标注着:5343,因此可算出那天是:1791年12月15日。
高斯获得博士学位的那天日记上标着:8113
请你算出高斯获得博士学位的年月日。
提交答案的格式是:yyyy-mm-dd, 例如:1980-03-21
看到这个题目,我只想吐槽.....这真是好习(hen)惯(tai)啊.....= W =
关于tm结构体:
在标准C/C++中,我们可通过tm结构来获得日期和时间,tm结构在time.h中的定义如下:
#ifndef _TM_DEFINED
struct tm {
int tm_sec; /* 秒–取值区间为[0,59] */
int tm_min; /* 分 - 取值区间为[0,59] */
int tm_hour; /* 时 - 取值区间为[0,23] */
int tm_mday; /* 一个月中的日期 - 取值区间为[1,31] */
int tm_mon; /* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */
int tm_year; /* 年份,其值从1900开始 */
int tm_wday; /* 星期–取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 */
int tm_yday; /* 从每年的1月1日开始的天数–取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推 */
int tm_isdst; /* 夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负。*/
long int tm_gmtoff; /*指定了日期变更线东面时区中UTC东部时区正秒数或UTC西部时区的负秒数*/
const char *tm_zone; /*当前时区的名字(与环境变量TZ有关)*/
};
关于time_t:
包含文件:
#ifndef __TIME_T
#define __TIME_T
/*
避免重复定义
time_t */
typedef long
time_t; /*
时间值
time_t 为长整型的别名*/
#endif
既然time_t实际上是长整型,到未来的某一天,
从一个时间点(一般是1970年1月1日0时0分0秒)到那时的秒数(即日历时间)
,超出了长整形所能表示的数的范围怎么办?对time_t数据类型的值来说,它所表示的时间不能晚于2038年1月18日19时14分07秒。为了能够表示更久远的时间,一些编译器厂商引入了64位甚至更长的整形数来保存日历时间。比如
微软在Visual C++中采用了__time64_t数据类型来保存日历时间,并通过_time64()函数来获得日历时间
(而不是通过使用32位字的time()函数),这样就可以通过该数据类型保存3001年1月1日0时0分0秒(不包括该时间点)之前的时间。
在time.h头文件中,我们还可以看到一些函数,它们都是以time_t为参数类型或返回值类型的函数:
double difftime(time_t time1, time_t time0);
time_t mktime(struct tm * timeptr);
time_t time(time_t * timer);
char * asctime(const struct tm * timeptr);
char * ctime(const time_t *timer);
此外,time.h还提供了两种不同的函数将日历时间(一个用time_t表示的整数)转换为我们平时看到的把年月日时分秒分开显示的时间格式tm:
struct tm * gmtime(const time_t *timer);
struct tm * localtime(const time_t * timer);
通过查阅MSDN,我们可以知道Microsoft C/C++ 7.0中时间点的值(time_t对象的值)是从1899年12月31日0时0分0秒到该时间点所经过的秒数,而其它各种版本的Microsoft C/C++和所有不同版本的Visual C++都是计算的从1970年1月1日0时0分0秒到该时间点所经过的秒数。
(转载于http://www.eefocus.com/xuefu2009/blog/10-03/187348_f456a.html)
实例:
0、关于 time_t 类型:
time_t t = time(NULL);
printf("time: %d\n", t);
可取当前时间。
1、关于 gmtime
包含头文件:time.h
原型:struct tm *gmtime(const time_t *time);
功能:把日期和时间转换为格林威治(GMT)时间的函数。将参数time 所指的time_t 结构中的信息转换成真实世界所使用的时间日期表示方法,然后将结果由结构tm返回。
struct tm* t1 = gmtime(&t);
printf("%d %d %d %d:%d:%d\n", t1->tm_year+1900, t1->tm_mon+1, t1->tm_mday, t1->tm_hour, t1->tm_min, t1->tm_sec);
2、
关于 localtime
功 能: 把从1970-1-1零点零分到当前时间系统所偏移的秒数时间转换为本地时间,而gmtime函数转换后的时间没有经过时区变换,是UTC时间 。
说明:此函数获得的tm结构体的时间是日历时间。
用 法: struct tm *localtime(const time_t *clock);
返回值:返回指向tm 结构体的指针.tm结构体是time.h中定义的用于分别存储时间的各个量(年月日等)的结构体.
struct tm* t2 = localtime(&t);
printf("%d %d %d %d:%d:%d\n", t2->tm_year+1900, t2->tm_mon+1, t2->tm_mday,t2->tm_hour, t2->tm_min, t2->tm_sec);
3、关于mktime
功能:将时间转换为自1970年1月1日以来失去时间的秒数,发生错误时返回-1.
表头文件:#include <time.h>
函数定义:time_t mktime(struct tm * timeptr);
函数说明:mktime()用来将参数timeptr所指的tm结构数据转换成从公元1970年1月1日0时0分0 秒算起至今的UTC时间所经过的秒数。
返回值: 返回经过的秒数。
// 计算时间差 1997年7月1日 到 今天过去了多少天?
struct tm tm1;
tm1.tm_year = 1997 - 1900;
tm1.tm_mon = 7 - 1;
tm1.tm_mday = 1;
tm1.tm_hour = 12;
tm1.tm_min = 0;
tm1.tm_sec = 0;
int delta = (time(NULL) - mktime(&tm1))/(24*60*60);
4、关于difftime
功 能:返回两个time_t型变量之间的时间间隔,即 计算两个时刻之间的时间差。
用 法: double difftime(time_t time2, time_t time1);
头文件:time.h
5、关于 time
头文件:time.h
函数原型:time_t time(time_t * timer)
功能: 获取当前的系统时间,返回的结果是一个time_t类型,其实就是一个大整数,其值表示从CUT(Coordinated Universal Time)时间1970年1月1日00:00:00(称为UNIX系统的Epoch时间)到当前时刻的秒数。然后调用localtime
将time_t所表示的CUT时间转换为本地时间(我们是+8区,比CUT多8个小时)并转成struct tm类型,该类型的各数据成员分别表示年月日时分秒。
补充说明:time函数的原型也可以理解为 long time(long *tloc),即返回一个long型整数。因为在time.h这个头文件中time_t实际上就是:
#ifndef _TIME_T_DEFINED
typedef long time_t; /* time value */
#define _TIME_T_DEFINED /* avoid multiple defines of time_t */
#endif
即long。
5、关于 asctime
把timeptr指向的tm结构体中储存的时间转换为字符串字符串格式返回,格式为:Www Mmm dd hh:mm:ss yyyy。其中Www为星期;Mmm为月份;dd为日;hh为时;mm为分;ss为秒;yyyy为年份。
6、关于 ctime
功 能: 把日期和时间转换为字符串
那么本题是:
#include <iostream>
#include <time.h>
using namespace std;
int main() {
struct tm tm1 ;
tm1.tm_year = 1991 - 1900;
tm1.tm_mon = 12 - 1;
tm1.tm_mday = 15 + 8113 - 5343;
tm1.tm_hour = 1;
tm1.tm_min = 0;
tm1.tm_sec = 0;
time_t t3 = mktime(&tm1);
struct tm * t2 = localtime( &t3 );
cout<<t2->tm_year+1900<<" "<<t2->tm_mon+1<<" "<<t2->tm_mday<<endl;
return 0;
}
得到的答案是1999 7 16
标准日期1991的下一年是闰年,1791的下一年也是闰年,不用准换了。
由于将标准日期加来了200年,所以是1799 7 16
世纪末的星期
曾有邪教称1999年12月31日是世界末日。当然该谣言已经不攻自破。
还有人称今后的某个世纪末的12月31日,如果是星期一则会....
有趣的是,任何一个世纪末的年份的12月31日都不可能是星期一!!
于是,“谣言制造商”又修改为星期日......
1999年的12月31日是星期五,请问:未来哪一个离我们最近的一个世纪末年(即xx99年)的12月31日正好是星期天(即星期日)?
请回答该年份(只写这个4位整数,不要写12月31等多余信息)
#include <iostream>
#include <time.h>
#include <windows.h>
using namespace std;
int main() {
struct tm * tm1 = new tm();
tm1->tm_mon = 12 - 1;
tm1->tm_mday = 31;
tm1->tm_year = 1999 - 1900;
tm1->tm_hour = 1;
tm1->tm_min = 0;
tm1->tm_sec = 0;
time_t t = mktime( tm1 );
tm1 = localtime( &t );
while( tm1->tm_wday != 0 )
{
cout<<tm1->tm_year + 1900<<" "<<tm1->tm_wday<<endl;
tm1->tm_year += 100;
time_t t1 = mktime( tm1 );
tm1 = localtime( &t1 );
cout<<tm1->tm_year+1900<<" "<<tm1->tm_wday<<endl;
}
cout<<tm1->tm_year + 1900<<endl;
return 0;
}
最后答案是2299年.....