`
public0821
  • 浏览: 238057 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

C/C++常用时间函数介绍

阅读更多

这几天一直做跟时间有关的操作,今天有空,特地整理一下

 

在介绍之前,先介绍两个概念

 

Coordinated Universal Time(UTC):协调世界时,又称为世界标准时间,也就是大家所熟知的格林威治标准时间(Greenwich Mean Time,GMT)。比如,中国内地的时间与UTC的时差为+8,也就是UTC+8。美国是UTC-5。

 

Calendar Time:日历时间,是用“从一个标准时间点到此时的时间经过的秒数”来表示的时间。这个标准时间点对不同的编译器来说会有所不同,但对一个编译系统来说,这个标准时间点是不变的,该编译系统中的时间对应的日历时间都通过该标准时间点来衡量,所以可以说日历时间是“相对时间”,但是无论你在哪一个时区,在同一时刻对同一个标准时间点来说,日历时间都是一样的。(简单点说,可以理解为CT时间就是UTC时间减去1900-01-01 00:00:00)

 

与日期和时间相关的数据结构

 

typedef long time_t;         /* 时间值 */

 

    大家可能会产生疑问:既然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秒(不包括该时间点)之前的时间。

 

struct tm 
{ 
    int tm_sec; /* 秒 - 取值区间为[0,59] */ 
    int tm_min; /* 分 - 取值区间为[0,59] */ 
    int tm_hour; /* 时 - 取值区间为[0,23] */ 
    int tm_mday; /* 一个月中的日期 - 取值区间为[1,31] */ i
    nt 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()为负。
                    夏令时可以在网上找到答案,在中国,已经不再使用夏令时*/ 
};

 

typedef long clock_t;     从"开启这个程序进程"到"程序中调用clock()函数"时之间的CPU时钟计时单元(clock tick)数

 

clock(取得CPU时钟计时单元(clock tick)数)
函数定义
clock_t clock( void )


函数说明
函数返回从"开启这个程序进程"到"程序中调用clock()函数"时之间的CPU时钟计时单元(clock tick)数。其中clock_t是用来保存时间的数据类型


返回值
从"开启这个程序进程"到"程序中调用clock()函数"时之间的CPU时钟计时单元(clock tick)数

 

在time.h文件中,定义了一个常量CLOCKS_PER_SEC,它用来表示一秒钟会有多少个时钟计时单元,其定义如下:

#define CLOCKS_PER_SEC ((clock_t)1000)

可以看到每过千分之一秒(1毫秒),调用clock()函数返回的值就加1。

 

范例:

#include "stdio.h"
#include "time.h"

int main( void )
{
   long    i = 10000000L;
   clock_t start, end;
   double  timeUsed;
   start = clock();
   while( i-- )      ;
   end = clock();
   timeUsed = (double)(end - start) / CLOCKS_PER_SEC;
   printf( "执行10000000次空循环用时%f秒\n", timeUsed );
}

 

输出结果
    执行10000000次空循环用时0.031000秒

 

time(取得目前的时间)
函数定义
time_t time(time_t *t);


函数说明
此函数会返回从公元1970年1月1日的0时0分0秒算起到现在所经过的秒数(CT时间)。如果t是非空指针的话,此函数也会将返回值存到t指针所指的内存。


返回值
成功则返回秒数,失败则返回((time_t)-1)值,错误原因存于errno中。

 

注意:由于返回的是CT时间,所以在做时间判断的时候一定要注意时区

 

范例

#include <stdio.h>
#include <time.h>

#define DAY_SECONDS (24*60*60)

int main(int argc, char**argv)
{
	time_t timeNow = time(NULL);

	time_t timeDayNow =  timeNow%DAY_SECONDS;
	int hour = timeDayNow/3600;
	int min = (timeDayNow%3600)/60;
	int sec = timeDayNow%60;

	printf("现在时间%d:%d:%d\n", hour, min, sec); 

	return 0;
};

 

输出结果会比你当前系统的时间早8个小时,那是因为中国内地的时间与UTC的时差为+8

 


localtime(取得当地目前时间和日期)
函数定义
struct tm *localtime(const time_t * timep);


函数说明
将参数timep所指的time_t结构中的信息转换成真实世界所使用的时间日期表示方法,然后将结果由结构tm返回。结构tm的定义请参考上面。此函数返回的时间日期已经转换成当地时区。


返回值
返回结构tm代表目前的当地时间。

 

gmtime(取得当地目前时间和日期)
函数定义
struct tm *gmtime()(const time_t * timep);


函数说明
将日历时间转化为世界标准时间(即格林尼治时间),并返回一个tm结构体来保存这个时间


返回值
返回结构tm代表目前的当地时间。

 

上面这个两个函数的参数和返回值都一样,唯一区别是localtime做了时区处理,返回当前时区的时间,而gmtime返回UTC时间

 

范例

#include <stdio.h>
#include <time.h>

int main(int argc, char**argv)
{
	const char *wday[]={"星期天","星期一","星期二","星期三","星期四","星期五","星期六"}; 

	time_t timeNow = time(NULL);

	struct tm* p = localtime(&timeNow); 

	struct tm* pp;

	printf("%d年%d月%d日 %d:%d:%d %s\n",p->tm_year+1900,p->tm_mon+1,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec, wday[p->tm_wday]); 

	pp = gmtime(&timeNow);

	printf("%d年%d月%d日 %d:%d:%d %s\n",pp->tm_year+1900,pp->tm_mon+1,pp->tm_mday,pp->tm_hour,pp->tm_min,pp->tm_sec, wday[pp->tm_wday]); 

	return 0;
};

 

输出结果
2010年4月1日 15:16:22 星期四
2010年4月1日 7:16:22 星期四


  其中localtime的结果和当前系统时间相同,gmtime比当前时间少8个小时

 

  注意:由于localtime和gmtime都使用全局变量存储结果,所以在使用时一定要注意,特别是在多线程中,他们都不是线程安全的函数


范例

#include <stdio.h>
#include <time.h>

int main(int argc, char**argv)
{
	time_t timeNow = time(NULL);
	struct tm *p = localtime(&timeNow); 

	struct tm *pp;
	timeNow += 10000;
	pp = localtime(&timeNow);

	printf("当前时间:%d年%d月%d日 %d:%d:%d\n",p->tm_year+1900,p->tm_mon+1,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec ); 
	printf("相加后时间:%d年%d月%d日 %d:%d:%d\n",pp->tm_year+1900,pp->tm_mon+1,pp->tm_mday,pp->tm_hour,pp->tm_min,pp->tm_sec ); 

	return 0;
};

 

输出:
当前时间:2010年4月1日 18:42:46
相加后时间:2010年4月1日 18:42:46


虽然后面的时间加了10000秒,但由于他们共用同样的全局变量,所以两个的时间是一样的

 

mktime(将时间结构数据转换成经过的秒数)

函数定义
time_t mktime(strcut tm * timeptr);


函数说明
mktime()用来将参数timeptr所指的tm结构数据转换成从公元1970年1月1日0时0分0 秒算起至今的UTC时间所经过的秒数。


返回值
返回经过的秒数。


注意:这里传入的参数必须是本地时间,不然就乱了

 

范例

#include <stdio.h>
#include <time.h>

int main(int argc, char**argv)
{
	time_t timeNow = time(NULL);

	struct tm* p = localtime(&timeNow); 

	time_t timeNow1 = mktime(p); 

	struct tm* pp = gmtime(&timeNow);

	time_t timeNow2 = mktime(pp);

	printf("%ld\n%ld\n%ld\n", timeNow, timeNow1, timeNow2);

	return 0;
};

 

输出结果
1270106860
1270106860
1270078060


可以发现当传UTC时间给mktime的时候,就还原不回去了,会比当前时间少28800秒,刚好8个小时

 


夏令时间
    夏令时比标准时快一个小时。例如,在夏令时的实施期间,标准时间的上午10点就成了夏令时的上午11点。


  夏令时,又称“日光节约时制”或“夏时制”,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间提前一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏令时的国家具体规定不同。目前全世界有近110个国家每年要实行夏令时。(各时区多数位于其理想边界之西,导致实际上全年实施夏令时。),中国现在已经不实行夏令时

 

范例

#include <stdio.h>
#include <time.h>

int main(int argc, char**argv)
{
	time_t timeNow = time(NULL);

	struct tm p = *(localtime(&timeNow)); 
	struct tm pp = p;

	printf("当前时间:%ld\n", mktime(&p));

	pp.tm_isdst = 1;

	printf("启动夏令时后的时间:%ld\n", mktime(&pp));

	return 0;
};

 
输出:
当前时间:1270109197
启动夏令时后的时间:1270109197

 

从这里的输出发现,设置这个值好像没什么用处,同时我试了下调试运行,发现执行了mktime(&pp)后,pp中的tm_isdst又等于0了
暂时没发现tm_isdst变量的实际用途


还有一点要注意,struct tm结构体中字段tm_mday的值是从1开始,所以在构造月初时间的时候一定要把这个字段置为1

#include <stdio.h>
#include <time.h>

int main(int argc, char**argv)
{
	time_t timeNow = time(NULL);
	struct tm *p = localtime(&timeNow); //取得当前时间

	struct tm pp;
	memset(&pp, '\0', sizeof(pp));
	pp.tm_year = p->tm_year;
	pp.tm_mon = p->tm_mon;//设置成了当前月
	
	time_t timePP = mktime(&pp);

	printf("时间:%d年%d月%d日 %d:%d:%d\n",pp.tm_year+1900,pp.tm_mon+1,pp.tm_mday,pp.tm_hour,pp.tm_min,pp.tm_sec ); 

	return 0;
};

 
输出结果:时间:2010年3月31日 0:0:0

 

我们期待的输出是“2010年4月1日 0:0:0”,但由于pp.tm_mday等于0,所以最后得到的时间timePP是上个月月底,相差了一天,正确的做法是设置pp.tm_mday等于1

分享到:
评论
1 楼 chase_the_air 2014-09-03  
谢谢博主,不过有点小疑问:就是调用clock()函数求出的程序运行时间是不是还包括调用clock()函数自身的运行时间啊?

相关推荐

    C/C++ 常用函数查找大全

    "C/C++ 常用函数查找大全"是一个非常实用的资源,它提供了详尽的函数参考信息,帮助开发者快速定位并理解所需的函数功能。 这个资源包含三个帮助文件,这意味着它可能从不同的角度对函数进行了分类和解释,比如按照...

    c/c++常用工具函数

    c++开发过程中经常遇到的一些工具型函数,如字符拆分

    c/c++函数大全(标准函数)

    下面将详细介绍一些重要的C/C++标准函数。 1. 输入/输出函数: - `printf` 和 `scanf`:这是最常用的输入输出函数,`printf` 用于格式化输出,`scanf` 用于格式化输入。 - `fprintf` 和 `fscanf`:与 `printf` 和...

    c/c++语言常用函数手册

    以上只是C/C++常用函数的一部分,实际编程中还有许多其他函数,如排序算法(`qsort()`)、时间操作(`time()`、`strftime()`)等。理解并熟练运用这些函数,能够提升编程效率,减少错误,并使代码更易读、更健壮。在...

    vs code C/C++语法高亮配置文件(C/C++ Themes插件)

    vscode配色插件的c/c++语法高亮配置文件,主题插件为C/C++ Themes。 可以对诸如const、enum、typedef别名、结构体引用等语法高亮进行设置,语言本身的关键字自然不用说了,比one dark pro等热门的插件颜色丰富的多。...

    C/C++常用工具函数类 - 以前累积的一些工具函数源码

    开发过程中的一些实用工具函数源码:获得当前程序的路径、获得ini文件内容、设置ini文件内容、获得ini的节点名称、校验文件/路径是否存在、创建路径、获得/写入文件内容/遍历文件夹、字符串转换、文件复制、字符编码...

    c/c++常用函数手册.rar

    《C/C++常用函数手册》是一本非常实用的编程参考资料,尤其对于正在学习或工作中涉及C++编程语言的开发者来说,它提供了丰富的函数用法、解释以及实例。这份手册中文版的出现,使得国内的学习者在理解上更为便捷,...

    c/c++中文帮助文档(API)

    在C/C++中,API主要由头文件组成,这些头文件定义了库函数的原型,允许程序员在自己的程序中调用这些函数。本资源“c/c++中文帮助文档(API)”为开发者提供了一个全面的参考,帮助他们理解和使用C和C++的各种库函数...

    C/C++常用算法手册(带详细书签目录)

    《C/C++常用算法手册》是一本专门为C和C++编程者设计的算法参考书籍,旨在帮助读者理解和掌握各种常见的算法。这本书包含了丰富的算法实例,每个算法都配有详细的分析和解释,使得学习过程更为直观易懂。对于C++算法...

    C/C++常用库函数【肝就完了】

    根据给定文件的信息,我们可以总结出以下详细的C/C++常用库函数知识点: ### 1. `&lt;string.h&gt;` — 字符串处理函数 #### `strcpy()` — 字符串拷贝 **原型**: `char* strcpy(char* dest, const char* src);` **功能...

    c/c++常用函数中文参考(c99标准api)

    本资料集合了C99标准API的中文参考,对于学习和理解C/C++的常用函数非常有帮助。 1. **操作符优先级**: C/C++中,操作符的优先级决定了表达式的计算顺序。例如,乘法和除法的优先级高于加法和减法,括号可以用来...

    C/C++/Linux C函数手册

    《C/C++/Linux C函数手册》是一份涵盖了C、C++以及Linux C编程语言中常用函数的详尽参考资料,旨在帮助程序员深入理解和熟练运用这些关键功能。这份手册的全面性使得开发者无论是在进行系统级编程还是应用开发,都能...

    c语言常用时间函数

    "C语言常用时间函数" 时间函数是C/C++语言中对日期和时间操作的基础概念。在C/C++中,时间函数主要用于获取、计算和显示时间。下面将详细介绍C/C++中时间函数的概念、类型、函数和使用方法。 概念: * ...

    C/C++ API 帮助文档大全(中文,chm格式)

    6. **C库的C++封装**:C++对C库中的函数进行了封装,如头文件和分别对应C语言的和,使得C++代码能以更现代的方式来使用这些函数。 7. **C++11及后续版本的新特性**:从C++11开始,C++引入了一系列新特性,如lambda...

    C/C++函数部分重点内容详解

    首先,这部分资源主要描述了三个常用头文件,其次,拓展部份讲述了C/C++当中C2371重定义报错的原因以及解决办法和函数相关的注意事项,最后,解决了如何导入静态库。 这部分资源比较适合有一定基础的C/C++的人群,...

    vscode c/c++扩展(cpptools v0.26.3)离线安装包

    2. **代码片段**:扩展内含预定义的C/C++代码片段,如常用的循环、条件语句等,可以快速输入,减少手动键入时间。 3. **智能感知与自动完成**:基于 IntelliSense 技术,`cpptools`能提供代码补全功能,根据上下文...

    c c++函数手册.rar

    《C/C++函数手册》是一本全面覆盖C和C++编程语言中常用函数的参考资料,旨在为程序员提供方便快捷的查询途径。这份手册不仅包含了C和C++的标准库函数,还可能涵盖了各种常用第三方库中的函数,使得开发者能够快速...

    linux c/c++基础学习资料(百度云链接和提取码)

    例如,“ls”用于查看目录内容,“cd”用于切换目录,“grep”用于搜索文件中的特定文本,“vi/vim”是常用的文本编辑器,而“gcc/g++”则是C/C++的编译器。了解并熟练使用这些基础命令是Linux环境下编程的第一步。 ...

    c/c++常用头文件汇总

    在C/C++编程中,头文件是至关重要的,它们包含了函数声明、类定义和其他编程元素,使得代码可以正确地编译和链接。本篇将详细讲解这些头文件及其包含的知识点。 1. `&lt;algo.h&gt;`:这是一个非标准的头文件,通常在一些...

Global site tag (gtag.js) - Google Analytics