基础知识
tm
tm 是一个结构体,毕竟是C语言的产物,结构体居然不大写,还是这种两个字母的简写,看到我强迫症都要犯了.
tm有7个成员变量 全部是 int 类型
tm_sec 秒
tm_min 分
tm_hour 时
tm_mday 这个月的几号
tm_mon 月份
注意: 需要+1 i.e 0代表1月
tm_year 年份
注意: 1900年加上当前tm_year是代表的当前年份
tm_wday 星期几
注意 在同样需要+1 并且是从 Sunday开始,0代表Sun
tm_yday 一年中的第几天
tm_isdst 是不是夏令时time_t
time_t 是一个整型,也就是可以加减
代表UNIX时间戳
从1970年1月1日 到 当前时间所经过的秒数
有意思的和千年虫问题(Y2K bug)类似的出现的2038问题(Year 2038 problem)
因为到2038年的某一天,UNIX时间戳int类型装不下了,然后世界就崩溃了.mktime
tm到time_t
我们可以用time_t mktime(tm*)这个函数来实现
注意传入的tm的指针,返回的是一个time_t类型
天知道为什么要用指针
毕竟time.h是C语言的东西
并且还算好用,主要是C++的时间库chrono更加奇葩,更看不懂.localtime&gmtime
time_t 到 tm
使用tm *localtime(time_t*)
这个就是正常的转换
如果使用gmtime,进一步转化UTC时间
我们大中国是UTC+8,所以当然会差个8小时
一般用localtimeasctime
asctime接受一个tm*类型的指针,然后返回一个字符串
形如:Www Mmm dd hh:mm:ss yyyy的格式ctime
ctime直接接受time_t*类型的指针,然后返回同样的上述表示时间的字符串
ctime = asctime(local(time_t*))time
time_t stamp = time(NULL)
这个命令直接返回当前时间的时间戳
两个栗子
1.
下面构造一个时间1997/04/23
首先定义tm类型 变量 day
tm day = {0};
注意,{0}将全部的赋值成员赋值为0
day.tm_year = 97;
day.tm_mon = 3;
day.tm_day = 23;
这样就定义好了tm这个日期
我们试一下asctime
printf("%s\n", asctime(&day));
只要记住所有time.h库中的函数的参数都是指针类型,就好了
输出 Sun Apr 23 00:00:00 1997
看样子好像是对的
我们试一下
4月24日
day.tm_mday = 24;
输出 Sun Apr 24 00:00:00 1997
还是星期天,这就有点奇怪了.
所以必须加上mktime
time_t stamp = mktime(&day);
只需要加上这一句
再次运行 day.tm_mday = 23
输出 Wed Apr 23 00:00:00 1997
day.tm_day = 24
输出 Thu Apr 24 00:00:00 1997
这样就对了
我的理解就是通过mktime把一个有问题的tm结构体类型变量转换成了time_t的同时,结构体本身也变成对了的,相当于激活
2.
这次我们构造一个当前时间的时间戳,通过time函数,再转成tm类型
time_t stamp = time(NULL);
tm *day = localtime(&stamp);
printf("%s", asctime(day));
这段代码会显示出当前时间
再使用gmtime
看一下
加上
tm *day2 = gmtime(&stamp);
printf("%s", asctime(day2));
此时输出
Thu Feb 9 18:36:09 2017
Thu Feb 9 10:36:09 2017
可见我们确实是UTC+8
实际应用中,不要用gmtime就好了
strftime
asctime可以将tm类型的转换成字符串
ctime可以将time_t类型的转换成字符串
而
strftime可以格式化字符串,想怎么输出就怎么输出
具体参考
http://www.cplusplus.com/reference/ctime/strftime/
下面举比较我认为比较有用的%F %T来说明
%F Short YYYY-MM-DD date, equivalent to %Y-%m-%d 2001-08-23
%T ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S 14:55:02
size_t strftime (char* ptr, size_t maxsize, const char* format, const struct tm* timeptr );
第1个参数 字符串名
第2个参数 字符串长度不知道加这个干哈
第3个参数 字符串格式” 我用 ” %F %T”
第4个是 tm类型指针
整个程序如下
#include <bits/stdc++.h>
using namespace std;
int main()
{
time_t stamp = time(NULL);
tm *day = localtime(&stamp);
char s[100];
strftime(s, 100, "%F %T", day);
puts(s);
}
这个程序会显示当前时间
注意,一旦使用了gmtime(&stamp)函数,那么day就会改变
如以下程序
#include <bits/stdc++.h>
using namespace std;
int main()
{
time_t stamp = time(NULL);
tm *day = localtime(&stamp);
tm *day2 = gmtime(&stamp);
char s[100];
strftime(s, 100, "%F %T", day);
puts(s);
}
这会显示UTC时间,而不是UTC+8时间
蓝桥杯应用
1.2012年决赛-1:
1949年的国庆节(10月1日)是星期六。
今年(2012)的国庆节是星期一。
那么,从建国到现在,有几次国庆节正好是星期日呢?
首先输出看一看1949/10/1是不是星期六,发现是
然后循环改变tm_year
通过tm_wday == 0判断是不是星期日
#include <bits/stdc++.h>
using namespace std;
int main()
{
tm day = {0};
day.tm_year = 49;
day.tm_mon = 9;
day.tm_mday = 1;
mktime(&day);
printf("%s\n", asctime(&day));
int ans = 0;
for (int i = 49; i <= 112; i++) {
day.tm_year = i;
mktime(&day);
ans += day.tm_wday == 0;
}
cout << ans << endl;
}
答案9
2.2015 省赛 2
2.2015 省赛 2
星系炸弹
在X星系的广袤空间中漂浮着许多X星人造“炸弹”,用来作为宇宙中的路标。
每个炸弹都可以设定多少天之后爆炸。
比如:阿尔法炸弹2015年1月1日放置,定时为15天,则它在2015年1月16日爆炸。
有一个贝塔炸弹,2014年11月9日放置,定时为1000天,请你计算它爆炸的准确日期。
请填写该日期,格式为 yyyy-mm-dd 即4位年份2位月份2位日期。比如:2015-02-19
请严格按照格式书写。不能出现其它文字或符号。
在个更简单
只要mktime了,那么日期不对的日期
所以可以这么写
#include <bits/stdc++.h>
using namespace std;
int main()
{
tm day = {0};
day.tm_year = 114;
day.tm_mon = 10;
day.tm_mday = 9;
mktime(&day);
printf("%s\n", asctime(&day));;
day.tm_mday += 1000;
mktime(&day);
printf("%s\n", asctime(&day));;
}
输出
Sun Nov 9 00:00:00 2014
Sat Aug 5 00:00:00 2017
如果不确定Aug是不是8月
那么就可以用strftime来写
char s[100];
strftime(s, 100, "%F", &day);
puts(s);
答案
2017-08-15