time.h 的 应用

基础知识

  1. 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 是不是夏令时

  2. time_t
    time_t 是一个整型,也就是可以加减
    代表UNIX时间戳
    从1970年1月1日 到 当前时间所经过的秒数
    有意思的和千年虫问题(Y2K bug)类似的出现的2038问题(Year 2038 problem)
    因为到2038年的某一天,UNIX时间戳int类型装不下了,然后世界就崩溃了.

  3. mktime
    tm到time_t
    我们可以用time_t mktime(tm*)这个函数来实现
    注意传入的tm的指针,返回的是一个time_t类型
    天知道为什么要用指针
    毕竟time.h是C语言的东西
    并且还算好用,主要是C++的时间库chrono更加奇葩,更看不懂.

  4. localtime&gmtime
    time_t 到 tm
    使用tm *localtime(time_t*)
    这个就是正常的转换
    如果使用gmtime,进一步转化UTC时间
    我们大中国是UTC+8,所以当然会差个8小时
    一般用localtime

  5. asctime
    asctime接受一个tm*类型的指针,然后返回一个字符串
    形如:Www Mmm dd hh:mm:ss yyyy的格式

  6. ctime
    ctime直接接受time_t*类型的指针,然后返回同样的上述表示时间的字符串
    ctime = asctime(local(time_t*))

  7. 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值