C/C++ 获取本地日期时间方法

1.跨平台方法

1.1 手动暴力法(snprintf)

snprintf() 函数用于格式化输出字符串到指定大小的缓冲,可以获取我们想要的日期时间格式。

#include <iostream>
#include <time.h>
using namespace std;
	
time_t t = time(NULL);
struct tm* stime=localtime(&t);
char tmp[32]{0};
snprintf(tmp,sizeof(tmp),"%04d-%02d-%02d %02d:%02d:%02d",1900+stime->tm_year,1+stime->tm_mon,stime->tm_mday, stime->tm_hour,stime->tm_min,stime->tm_sec);
cout<<tmp<<endl;

输出结果:2015-04-02 23:12:56

1.2 便捷快速法(strftime)

strftime() 函数用于将时间(struct tm)格式化为字符串,可用于替代 snprintf() 函数。

#include <iostream>
#include <time.h>
using namespace std;

time_t t = time(0); 
char tmp[32]={NULL};
strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S",localtime(&t)); 
cout<<tmp<<endl;

输出结果:2015-04-02 23:12:56

1.3 简获日历时间法

1.3.1 ctime() + time_t

ctime() 函数可用于将时间戳(time_t 值)转换为可读的日历时间(calendar time)字符串,转换结果格式为:

Www Mmm dd hh:mm:ss yyyy

其中Www是weekday, Mmm 表示Month,dd表示每月的多少号,hh:mm:ss表示time,yyyy表示year。具体示例如下:

#include <time.h>
#include <iostream>
#include <string>
using namespace std;

time_t ts=time(NULL);
char tmp[32]{0};
strncpy(tmp,ctime(&ts),sizeof(tmp));
cout<<tmp<<endl;

输出结果:Fri Aug 14 23:19:42 2015

1.3.2 asctime() + struct tm

asctime() 函数功能与 ctime() 函数类似,用于将 struct tm 表示的日期时间转换为可读的日历时间字符串,结果格式同 ctime()。asctime() 与 ctime() 不同之处是 asctime() 传入的参数类型是 struct tm 指针型,ctime() 的是 time_t 指针型。具体示例如下:

time_t ts=time(NULL);
struct tm stm=*localtime(&ts);
char tmp[32]{0};
strncpy(tmp,asctime(&stm),sizeof(tmp));
cout<<tmp<<endl;

输出结果:Fri Aug 14 23:19:42 2015

2.Windows 平台

#include <iostream>
using namespace std;
#include <time.h>
#include <windows.h>

SYSTEMTIME sys; 
GetLocalTime(&sys);
char tmp[64]={NULL};
sprintf(tmp,"%4d-%02d-%02d %02d:%02d:%02d ms:%03d",sys.wYear,sys.wMonth,sys.wDay,sys.wHour,sys.wMinute,sys.wSecond,sys.wMilliseconds); 
cout<<tmp<<endl;

输出结果:2015-08-14 23:41:56 ms:354

3.Unix 平台

#include <sys/time.h> 
#include <unistd.h>

struct timeval now_time;
gettimeofday(&now_time, NULL);
time_t tt = now_time.tv_sec;
tm *temp = localtime(&tt);
char time_str[32]={NULL};
sprintf(time_str,"%04d-%02d-%02d%02d:%02d:%02d",temp->tm_year+ 1900,temp->tm_mon+1,temp->tm_mday,temp->tm_hour,temp->tm_min, temp->tm_sec);
cout<<tmp<<endl;

输出时间:2015-08-14 23:41:56

4.日期时间与时间戳的相互转换

4.1 时间戳转日期时间

//@brief:时间戳转日期时间
static inline string getDateTimeFromTS(time_t ts) {
	if(ts<0) {
		return "";
	}
	struct tm tm = *localtime(&ts);
	static char time_str[32]{0};
	snprintf(time_str,sizeof(time_str),"%04d-%02d-%02d %02d:%02d:%02d",tm.tm_year+1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec);
	return string(time_str);
}

4.2 日期时间转时间戳

(1)跨平台方法。
使用sscanf将日期时间字符串转为struct tm,再转为time_t。

//@brief:日期时间转时间戳
static inline time_t getTSFromDateTime(const string& dateTime,const char* fmt) {
	int dY, dM, dD, dH, dMin, dS;
	sscanf(dateTime.c_str(),fmt, &dY, &dM, &dD, &dH, &dMin, &dS);
	struct tm stm;
	stm.tm_year = dY - 1900;
	stm.tm_mon = dM - 1;
	stm.tm_mday = dD;
	stm.tm_hour = dH;
	stm.tm_min = dMin;
	stm.tm_sec = dS;

	return mktime(&stm);	//返回时间戳
}

(2)Linux 平台方法。
使用glibc库函数strptime()将日期时间字符串转为struct tm,再转为time_t。strptime()函数的功能与strftime()函数功能相反,用于将日期时间字符串转换为struct tm。函数原型如下:

char *strptime(const char *s, const char *format, struct tm *tm)

参数说明:
s:struct tm格式化后的C字符串(以0结尾);
format:字符串格式,构建方式与strftime的format字符串完全一样;
struct tm *tm:转换后存储tm值的指针;

返回值:指向转换过程中第一个不能被处理的那个字符。

转换示例如下。

static inline time_t getTSFromDateTime(const string& dateTime, const char* fmt) {
    struct tm t;
    memset(&t, 0, sizeof(t));
    if(strptime(dateTime.c_str(),fmt,&t)!=NULL) {
        return mktime(&t);
    }
    return 0;
}

5.需知知识点

(1)UTC (Coordinated Universal Time),协调世界时,又称世界标准时间,曾由格林威治平均时间(GMT,Greenwich Mean Time)提供。现行的协调世界时根据国际电信联盟的建议《Standard-frequency and time-signal emissions》(ITU-R TF.460-6)所确定[6]。 UTC基于国际原子时,并通过不规则的加入闰秒来抵消地球自转变慢的影响。闰秒在必要的时候会被插入到UTC中,以保证协调世界时(UTC)与世界时(UT1)相差不超过0.9秒。比如,中国内地时间与UTC的时差为+8,也就是UTC+8,美国是UTC-5。

(2)GMT(Greenwich Mean Time),格林威治平时,格林威治平太阳时,又译为格林尼治平时,格林尼治平太阳时,是指位于英国伦敦郊区的皇家格林威治天文台当地的平太阳时,因为本初子午线(经度为0的经线)被定义为通过那里的经线。自1924年2月5日开始,格林威治天文台负责每隔一小时向全世界发放调时信息。

格林威治平时的正午是指当平太阳横穿格林尼治子午线时(也就是在格林尼治上空最高点时)的时间。由于地球每天的自转是有些不规则的,而且正在缓慢减速,因此格林尼治平时基于天文观测本身的缺陷,已经被原子钟报时的协调世界时(UTC)所取代。

(3)国际原子时(International Atomic Time,TAI,缩写源自法语temps atomique international)。1967年第13届国际计量大会上通过一项决议,定义1秒为铯-133原子基态两个超精细能级间跃迁辐射9,192,631,770周所持续的时间。TAI是1971年由国际时间局建立,现改为国际计量局(BIPM)的时间部门在维持,根据全球约60个实验室中的大约240台自由运转的原子钟提供的数据进行处理,得出的统一的原子时。

(4)世界时(Universal Time,UT),即格林威治平太阳时,是指格林威治所在地的标准时间,也是表示地球自转速率的一种形式,以地球自转为基础的时间计量系统。地球自转的角度可用地方子午线相对于地球上的基本参考点的运动来度量。为了测量地球自转,人们在地球上选取了两个基本参考点:春分点和平太阳点,由此确定的时间分别称为恒星时和平太阳时。

世界时的精度受到地球自转不均匀变化和极移的影响,为了解决这种影响,1955年国际天文联合会定义了UT0、UT1和UT2三个系统:

  • UT0系统是由一个天文台的天文观测直接测定的世界时,没有考虑极移造成的天文台地理坐标变化。该系统曾长期被认为是稳定均匀的时间计量系统,得到过广泛应用;
  • UT1系统是在UT0的基础上加入了极移改正 Δλ,修正地轴摆动的影响。UT1是目前使用的世界时标准。被作为目前世界民用时间标准UTC在增减闰秒时的参照标准;
  • UT2系统是UT1的平滑处理版本,在UT1基础上加入了地球自转速率的季节性改正 ΔT。UT2即GMT。

三者关系如下:

UT1 = UT0 + Δλ
UT2 = UT1 + ΔT

(5)clock tick,时钟计时单元,一个时钟计时单元的时间长短是由CPU控制的。一个clock tick不是CPU的一个时钟周期,而是C/C++的一个基本计时单位。在VC++的time.h文件中,我们可以找到相关的定义:

#ifndef _CLOCK_T_DEFINED
typedef long clock_t;
#define _CLOCK_T_DEFINED
#endif

#define CLOCKS_PER_SEC ((clock_t)1000)

clock_t clock( void );

这个函数返回从“进程启动”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数,在MSDN中称之为挂钟时间(wal-clock)。

//获取逝去时间
clock_t start, finish;
start=clock();
…
finish=clock();
	
//逝去多少秒
long duration=(finish- start)/CLOCKS_PER_SEC;

(5)头文件<time.h>还提供了两种不同的函数将时间戳转换为年月日时分秒分开显示的日历时间格式struct tm。

struct tm* gmtime(const time_t* timer);
struct tm* localtime(const time_t* timer);

其中 gmtime() 函数是将时间戳转化为 UTC+0 的日历时间,即0时区的世界标准时间,并返回一个struct tm结构体来保存这个时间。而localtime()函数考虑时区,将时间戳转为本地日历时间。比如用gmtime()函数获得的时间是2018-07-30 00:00:00,那么用localtime()函数在中国地区获得的本地时间会比世界标准时间早8个小时,即2018-07-30 08:00:00。示例程序(VC++)如下:

#include <time.h>
#include <string>
#include <iostream>
using namespace std;

int main() {
	time_t ts = 0;
	struct tm stm1;
	gmtime_s(&stm1,&ts);
	char tmp[32]{0};
	asctime_s(tmp, &stm1);
	cout<<tmp;

	struct tm stm2;
	localtime_s(&stm2, &ts);
	asctime_s(tmp, &stm2);
	cout <<tmp;
}

程序输出:

Thu Jan  1 00:00:00 1970
Thu Jan  1 08:00:00 1970

(6)分解时间就是以年月日时分秒等分量保存的时间结构,在C/C++中是struct tm结构。我们可以使用mktime()函数将用struct tm结构表示的日历时间转化为时间戳,其作用与gmtime()和localtime()函数具有相反。其函数原型如下:

time_t mktime(struct tm* timeptr);

参考文献

C/C++中怎样获取日期和时间
格林尼治平时.维基百科
协调世界时.维基百科
国际原子时.维基百科
世界时.维基百科
一些时间的概念与区分(UTC、GMT、LT、TAI等)
strptime(3) manual

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值