VC++时间函数总结

1基本概念    1

1.1 基本概念    1

1.2 时间表示法    2

2 Win32 API    3

2.1 获取    3

2.1.1 时间间隔    3

2.1.2 时刻    3

2.1.3 时区    3

2.1.4 时区信息    5

2.2 设置    6

2.2.1 时刻    6

2.2.2 时区    7

2.2.3 时间基准    7

2.3 比较    7

2.4 转换    7

2.4.1 DOS时间与FILETIME转换    8

2.4.2 SYSTEMTIMEFILETIME转换    8

2.4.3 本地时间与UTC时间转换    8

3 C运行时库函数    9

3.1 获取    9

3.1.1 时间间隔    9

3.1.2 时刻    9

3.2 设置    10

3.2.1 时刻    10

3.2.2 时区    10

3.3 比较    10

3.4 转换    11

3.4.1 time_tstruct tm    11

3.5 格式化    12

3.5.1 asctime    12

3.5.2 ctime    12

3.5.3 strftime    12

4 MFC    13

 

1基本概念

1.1 基本概念

GMTGreenwich Mean Time)是格林尼治标准时间。它是通过观测太阳来确定时间的,即力学时。力学时的精确度不是很高,所以它被协调世界时(Coordinate Universal Time,简称UTC)所取代。UTC采用原子钟计时,所以它的精确度很高。Windows中,GMTUTC没有区别,被统称为系统时间(System Time)。

标准时(Standard Time)等于UTC时间加上时差,如:中国的时区为+8:00,北京时间就是UTC时间加上8小时。

某些国家在夏季还将执行夏令时,也就是日光节能时(Daylight Saving Time,简称DST)。就是在夏季将时钟拨快1小时,早起早睡充分利用太阳光以达到节约能源的目的。UTC时间、标准时、夏令时的关系请参考下面两张图形:

图1.1 北半球一年内的时间

图1.2 南半球一年内的时间

Windows中,标准时和夏令时被统称为本地时间(Local Time)。本地时间有时会有歧义,如图1.1和图1.2中的绿色部分,它所表示的本地时间是标准时还是夏令时?

1.2 时间表示法

VC中对时间的表示一般有两种方法。一种是人们熟知的年、月、日、时、分、秒,如:SYSTEMTIMEstruct tm,这种表示方法被称之为broken-down time

另一种是从基准时刻到当前时刻的时间间隔,如:time_t表示197011日到当前时刻的秒数,称这种表示方法为calendar time。类似的还有FILETIME,它其实就是一个__int64,表示160111日到当前时刻的时间间隔(单位10-7 秒,即100纳秒,万分之一毫秒)。

 

2 Win32 API

2.1 获取

2.1.1 时间间隔

GetTickCountGetTickCount64返回启动Windows后到现在的毫秒数。GetTickCount返回一个DWORD,最大为0xFFFFFFFF秒,约为49.71天。也就是说连续运行Windows系统 50 天后,GetTickCount会从零开始计时。

GetTickCount64返回一个unsigned __int64,最大为0xFFFFFFFFFFFFFFFF秒,约为 5.8亿年。再也不用担心计时重新归零的问题了。

2.1.2 时刻

GetSystemTime用于获取毫秒级UTC时刻。

GetSystemTimeAsFileTime用于获取10-7 秒级的UTC时刻。

GetLocalTime用于获取本地时刻。要想知道这个时刻为标准时还是夏令时请通过GetTimeZoneInformation的返回值进行判断:返回TIME_ZONE_ID_DAYLIGHT表示夏令时,返回TIME_ZONE_ID_STANDARDTIME_ZONE_ID_UNKNOWN表示标准时。TIME_ZONE_ID_UNKNOWN还表明了系统未启用夏令时。

GetFileTime用于获取打开文件(或文件夹)的UTC时刻。为了获取未打开文件的UTC时刻,请使用FindFirstFile函数。

2.1.3 时区

GetTimeZoneInformation函数可以获取时区信息,包括:时差、标准时偏差、夏令时偏差、夏令时开始时刻(标准时)、夏令时结束时刻(夏令时)。它获取的时区信息保存在结构TIME_ZONE_INFORMATION内:

typedef struct _TIME_ZONE_INFORMATION { // tzi

LONG                Bias;

WCHAR            StandardName[32];

SYSTEMTIME        StandardDate;

LONG                StandardBias;

WCHAR            DaylightName[32];

SYSTEMTIME        DaylightDate;

LONG                DaylightBias;

} TIME_ZONE_INFORMATION;

这个结构各个成员变量的含义请参考下图:

图2.1 时区信息

Bias是时区时差的相反数,StandardBias为标准时偏差(没发现不为零的情况),DaylightBias为夏令时偏差(一般为-60),它们的单位都是分钟。UTC与标准时、夏令时的转换公式如下:

UTC=标准时 + Bias + StandardBias

UTC=夏令时 + Bias + DaylightBias

DaylightDate是夏令时的开始时刻,它是标准时。DaylightDate 各个成员变量的含义如下:

成员变量

示例数值

wYear; 

年,一般为零

0 

wMonth; 

月。0表示没有夏令时

4 

wDayOfWeek; 

06分别表示星期日至星期六

1 

wDay; 

第几个,范围[1,5]5表示最后一个。

0 

wHour; 

2 

wMinute; 

0 

wSecond; 

0 

wMilliseconds; 

毫秒

0 

以上表为例,夏令时的开始时刻为每年4月的第1个星期日的2:00:00.000

StandardDate是夏令时的结束时刻,它是夏令时。StandardDate各个成员变量的含义请参考上表。

注意:对于北半球而言,DaylightDate小于StandardDate,但是到了南半球则正好相反。

因为夏令时的开始、结束时间可能是变化的,自Vista后引入了下面两个函数:

GetTimeZoneInformationForYear

GetDynamicTimeZoneInformation

2.1.4 时区信息

时区信息全部存放在注册表里:

对于Windows 98而言,存放在如下位置:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Time Zones

对于Windows NT而言,存放在如下位置:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones

对于Windows CE而言,存放在如下位置:

HKEY_LOCAL_MACHINE\Time Zones

如:修改WinCE时区为北京时间:

[HKEY_LOCAL_MACHINE\Time Zones]
"Default"="China Standard Time"

注册表里的二进制数据TZI,其结构如下:

#pragma pack(push,1)

class TZI

{

LONG        Bias;        //时差,单位:分钟

LONG        StandardBias;    //标准时差,单位:分钟

LONG        DaylightBias;    //夏令时时差,单位:分钟

SYSTEMTIME    StandardDate;    //夏令时结束时刻

SYSTEMTIME    DaylightDate;    //夏令时开始时刻

};

#pragma pack(pop)

2.2 设置

2.2.1 时刻

SetSystemTime用于设置WindowsUTC时刻。

SetLocalTime用于设置Windows的本地时刻。如果Windows启用了夏令时,有时会出现意想不到地后果。举例说明:假定系统时区为-8:00,并启用了夏令时。现在调用代码 SetLocalTime(2000.07.07 10:11:12),将会有两种不同的结果:

如果当前系统正处于夏令时,首先把2000.07.07 10:11:12转换为UTC时刻,即2000.07.07 10:11:12+7:00=2000.07.07 17:11:12,然后调用SetSystemTime(2000.07.07 17:11:12)。因为2000.07.07 17:11:12处于夏令时,所以最终的本地时刻为2000.07.07 17:11:127:00=2000.07.07 10:11:12,这是一个令人满意的结果。

如果当前系统处于标准时,首先把2000.07.07 10:11:12转换为UTC时刻,即2000.07.07 10:11:12+8:00=2000.07.07 18:11:12,然后调用SetSystemTime(2000.07.07 18:11:12)。因为2000.07.07 18:11:12处于夏令时,所以最终的本地时刻为2000.07.07 18:11:127:00=2000.07.07 11:11:12,这个结果实在令人不可思议!

SetFileTime用于修改某个打开文件(或文件夹)的UTC时刻。不打开文件,如何修改其时刻?

2.2.2 时区

SetTimeZoneInformation

SetDynamicTimeZoneInformation

2.2.3 时间基准

将计算机的BIOS时间当作本地时间

REGEDIT4

 

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation]

"RealTimeIsUniversal"=dword:00000000

将计算机的BIOS时间当作UTC时间

REGEDIT4

 

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation]

"RealTimeIsUniversal"=dword:00000001

2.3 比较

CompareFileTime

2.4 转换

2.4.1 DOS时间与FILETIME转换

DosDateTimeToFileTime

FileTimeToDosDateTime

2.4.2 SYSTEMTIMEFILETIME转换

FileTimeToSystemTime

SystemTimeToFileTime

2.4.3 本地时间与UTC时间转换

FileTimeToLocalFileTime

LocalFileTimeToFileTime

如果Windows启用了夏令时,上面两个函数是无法正常工作的。如假定系统时区为-8:00,并启用了夏令时。则将UTC时刻转换为本地时刻将用到如下两个公式:

夏令时=UTC7:00

标准时=UTC8:00

正确的做法是:首先根据UTC时刻判断本地时刻是夏令时还是标准时,然后选择公式进行计算。但上面两个函数不是这么工作的,它们根据Windows当前处于夏令时还是标准时选择公式进行计算。

SystemTimeToTzSpecificLocalTime

TzSpecificLocalTimeToSystemTime

 

3 C运行时库函数

3.1 获取

3.1.1 时间间隔

3.1.1.1 clock

原型:clock_t clock( void )

功能:返回进程已经运行的时间,单位:1 / CLOCKS_PER_SEC 秒。

注意:clock_t其实就是long

3.1.2 时刻

3.1.2.1 time, _time32, _time64

原型:time_t time( time_t *timer );

功能:返回当前UTC时刻。

说明:

1、返回值表示自 1970 1 1 日到当前时刻的秒数;

2、在VC++6.0中,没有_time32, _time64time_t相当于long。因此,time_t最多只能表示到 2038-01-19 03:14:07

3、在VC++2005中,_time32的返回值为long_time64的返回值为__int64。至于time的返回值则要取决于是否定义了宏_USE_32BIT_TIME_T,定义了就是long,未定义就是__int64

3.1.2.2 _ftime

原型:void _ftime( struct _timeb *timeptr );

功能:获得当前UTC时刻、时差、是否为夏令时等信息。

说明:

1、与time函数相比,_ftime获得的时间精度更高(包含毫秒),信息更加丰富,如:包含时差信息。具体的请参考_timeb结构:

struct _timeb

{

time_t time;            //UTC时刻

unsigned short millitm;    //毫秒

short timezone;         //时差= UTC时刻 -本地时刻,单位:分钟

short dstflag;            //非零表示目前正处于夏令时

};

3.1.2.3 _stat_fstat

用于获取文件时间

3.1.2.4 _strdate

获取当前UTC日期至一个字符串内

3.1.2.5 _strtime

获取当前UTC时间至一个字符串内

3.2 设置

3.2.1 时刻

_utime_futime用于修改文件的访问、修改时刻,它们的不同之处在于指定文件的方式不同:前者通过路径名指定文件,后者通过文件句柄指定文件。

3.2.2 时区

请使用 _tzset 函数

3.3 比较

请使用 difftime 函数

3.4 转换

3.4.1 time_tstruct tm

struct tm 结构如下:

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,11]

int tm_year;    //年减去1900

int tm_wday;    //星期[0,6]0表示周日

int tm_yday;    //年积日[0,365]

int tm_isdst;    //正数表示为夏令时,0表示标准时,小于零表示未知

};

它既可以表示UTC时刻,也可以表示本地时刻。表示本地时刻时,通过tm_isdst可以明确指定该时刻为标准时刻还是夏令时刻。

3.4.1.1 time_tUTC时刻)转换为 struct tmUTC时刻)

请使用 gmtime 函数

3.4.1.2 struct tmUTC时刻)转换为 time_tUTC时刻)

请使用 _mkgmtime 函数

3.4.1.3 time_tUTC时刻)转换为 struct tm(本地时刻)

请使用 localtime 函数

3.4.1.4 struct tm(本地时刻)转换为 time_tUTC时刻)

请使用 mktime 函数

原型:time_t mktime( struct tm *timeptr );

说明:

1timeptr-> tm_isdst为正数(一般为1)时,表示将夏令时转换为UTC时刻;

2timeptr-> tm_isdst为零时,表示将标准时转换为UTC时刻;

3timeptr-> tm_isdst为负数(一般为-1)时,函数将自动判断本地时刻是夏令时还是标准时,然后再转换为UTC时刻。注意:夏令时、标准时的判断并不能完全正确;

3.5 格式化

3.5.1 asctime

struct tm转换为字符串格式的时间

3.5.2 ctime

time_t转换为字符串格式的时间

3.5.3 strftime

struct tm格式化输出为字符串

 

4 MFC

MFC中,CTimeCOleDateTime可用于处理时间。它们的异同:

1CTime封装的是C函数,COleDateTime封装的是Win32 API

2CTime可以处理夏令时,COleDateTime没有此功能;

3CTime以一个整数表示时刻,COleDateTime以一个double表示时刻。它们都只能精确到秒。

4VC++6.0CTime使用long表示时刻,时间范围为 197011日至2038118日。自VC++2002以后,CTime使用__int64表示时刻,时间范围为197011 12:00:0030001231日。

COleDateTime 表示的时间范围:10011日至99991231日。

posted @ 2016-11-03 19:54  hanford  阅读(9926)  评论(0编辑  收藏  举报