不用MFC类,直接使用C/C++ANSI标准库函数
日常编程中,常常需要获取系统的日期时间或对相关日期时间进行简单处理等。我常常使用MFC类库中的CMonthCalCtrl、 CDateTimeCtrl
CTime/CTimeSpan、COleDateTime/COleDateTimeSpan等类,它们提供了很强大的功能。但有时仅仅只需要获取当前的日期/时间,使用MFC类库感觉是大材小用啦(杀鸡焉用宰牛刀)。无意中发现,C/C++库或者系统API也为我们提供了相关的函数,简单搞定。能简单的就简单搞定,这也是一种境界哦(条条道路通罗马,只是看那条路好走/距离近)。查看MSDN,得到了关于日期时间的函数说明:
================================================================================================================================
Run-Time Library Reference |
Time Management |
Updated: November 2007
Use these functions to get the current time and convert, adjust, and storeit as necessary. The current time is the system time.
The _ftime and localtime routines use theTZenvironment variable. IfTZ is not set, the run-time library attempts touse the time-zone information specified by the operating system. If thisinformation is unavailable, these functions use the default value of PST8PDT.For more information onTZ, see_tzset; also see _daylight, timezone, and _tzname.
Time Routines
Function |
Use |
.NET Framework equivalent |
|
asctime, _wasctime, asctime_s, _wasctime_s |
Convert time from type struct tm to character string.The versions of these functions with the_s suffix are more secure. |
System::DateTime::ToLongDateString, System::DateTime::ToLongTimeString, System::DateTime::ToShortDateString, System::DateTime::ToShortTimeString, System::DateTime::ToString |
|
clock |
Return elapsed CPU time for process. |
Not applicable. To call the standard C function, use PInvoke. For more information, see Platform Invoke Examples. |
|
ctime, _ctime32, _ctime64, _wctime, _wctime32, _wctime64, _ctime_s, _ctime32_s, _ctime64_s, _wctime_s, _wctime32_s, _wctime64_s |
Convert time from type time_t, __time32_t or __time64_t to character string. The versions of these functions with the _s suffix are more secure. |
System::DateTime::GetDateTimeFormats, System::DateTime::ToString, System::DateTime::ToLongTimeString, System::DateTime::ToShortTimeString |
|
difftime, _difftime32, _difftime64 |
Compute difference between two times. |
System::DateTime::Subtract |
|
_ftime, _ftime32, _ftime64, _ftime_s, _ftime32_s, _ftime64_s |
Store current system time in variable of type struct _timeb or type struct __timeb64 The versions of these functions with the _s suffix are more secure. |
System::DateTime::Now |
|
_futime, _futime32, _futime64 |
Set modification time on open file |
System::IO::File::SetLastAccessTime, System::IO::File::SetLastWriteTime, System::IO::File::SetCreationTime |
|
gmtime, _gmtime32, _gmtime64, _gmtime_s, _gmtime32_s, _gmtime64_s |
Convert time from type time_t to struct tm or from type __time64_t to struct tm. The versions of these functions with the _s suffix are more secure. |
System::DateTime::UtcNow, System::DateTime::ToUniversalTime |
|
localtime, _localtime32, _localtime64, localtime_s, _localtime32_s, _localtime64_s |
Convert time from type time_t to struct tm or from type __time64_t to struct tm with local correction. The versions of these functions with the _s suffix are more secure. |
System::DateTime::ToLocalTime |
|
_mkgmtime, _mkgmtime32, _mkgmtime64 |
Convert time to calendar value in Greenwich Mean Time. |
System::DateTime::ToUniversalTime |
|
mktime, _mktime32, _mktime64 |
Convert time to calendar value. |
System::DateTime::DateTime |
|
_strdate, _wstrdate, _strdate_s, _wstrdate_s |
Return current system date as string. The versions of these functions with the _s suffix are more secure. |
System::DateTime::Parse |
|
strftime, wcsftime, _strftime_l, _wcsftime_l |
Format date-and-time string for international use. |
System::DateTime::ToLongDateString, System::DateTime::ToLongTimeString, System::DateTime::ToShortDateString, System::DateTime::ToShortTimeString, System::DateTime::ToString |
|
_strtime, _wstrtime, _strtime_s, _wstrtime_s |
Return current system time as string. The versions of these functions with the _s suffix are more secure. |
System::DateTime::ToLongDateString, System::DateTime::ToLongTimeString, System::DateTime::ToShortDateString, System::DateTime::ToShortTimeString, System::DateTime::ToString |
|
time, _time32, _time64 |
Get current system time as type time_t, __time32_t or as type __time64_t. |
Not applicable. To call the standard C function, use PInvoke. For more information, see Platform Invoke Examples. |
|
_tzset |
Set external time variables from environment time variable TZ. |
Not applicable. To call the standard C function,use PInvoke. For more information, see Platform Invoke Examples. |
|
_utime, _utime32, _utime64, _wutime, _wutime32, _wutime64 |
Set modification time for specified file using either current time or time value stored in structure. |
Not applicable. To call the standard C function, use PInvoke. For more information, see Platform Invoke Examples. |
以上函数都包含在time.h中,time.h是C标准函数库中获取时间与日期、对时间与日期数据操作及格式化的头文件。下面结合MSDN,用实例对它们的使用做一个大体的介绍和演示,具体请参考MSDN.
在使用上面的相关函数之前,先了解一些“时间”和“日期”的概念,主要有以下几个:
Coordinated Universal Time(UTC):协调世界时,又称为世界标准时间,也就是大家所熟知的格林威治标准时间(Greenwich Mean Time,GMT)。比如,中国内地的时间与UTC的时差为+8,也就是UTC+8。
Calendar Time:日历时间,是用“从一个标准时间点到此时的时间经过的秒数”来表示的时间。这个标准时间点对不同的编译器来说会有所不同,但对一个编译系统来说,这个标准时间点是不变的,该编译系统中的时间对应的日历时间都通过该标准时间点来衡量,所以可以说日历时间是“相对时间”,但是无论你在哪一个时区,在同一时刻对同一个标准时间点来说,日历时间都是一样的。
epoch:时间点。时间点在标准C/C++中是一个整数,它用此时的时间和标准时间点相差的秒数(即日历时间)来表示。
clock tick:时钟计时单元(而不把它叫做时钟滴答次数),一个时钟计时单元的时间长短是由CPU控制的。一个clock tick不是CPU的一个时钟周期,而是C/C++的一个基本计时单位。
我们可以使用ANSI标准库中的time.h头文件。这个头文件中定义的时间和日期所使用的方法,无论是在结构定义,还是命名,都具有明显的C语言风格。下面,我将说明在C/C++中怎样使用日期的时间功能。
time_tltime;
ltime = time(NULL);//或者time(&m_nEdit1)
注意:使用time(NULL)函数得到是距离1970-01-01 00:00:00经历的秒数。要想得到一般的日期时间格式还需要转换。
常用为:srand((unsigned)time(NULL));//产生随机数种子,想必大家都见过的。
这里说的日期和时间就是我们平时所说的年、月、日、时、分、秒等信息。这些信息都保存在一个名为tm的结构体中,tm的标准定义为:
#ifndef _TM_DEFINED
struct tm {
int tm_sec; /* seconds afterthe minute - [0,59] */
int tm_min; /* minutes afterthe hour - [0,59] */
int tm_hour; /* hours sincemidnight - [0,23] */
int tm_mday; /* day of themonth - [1,31] */
int tm_mon; /* months sinceJanuary - [0,11] */
int tm_year; /* years since1900 */
int tm_wday; /* days sinceSunday - [0,6] */
int tm_yday; /* days sinceJanuary 1 - [0,365] */
int tm_isdst; /* daylightsavings time flag */
};
#define _TM_DEFINED
#endif
那么如何将一个日历时间(time_t)保存为一个tm结构的对象呢?
我们可以使用的函数是gmtime()和localtime(),这两个函数的原型为:
struct tm *gmtime(consttime_t *timer);
struct tm *localtime(const time_t * timer);
其中gmtime()函数是将日历时间转化为世界标准时间(即格林尼治时间),并返回一个tm结构体来保存这个时间,而localtime()函数是将日历时间转化为本地时间。比如现在用gmtime()函数获得的世界标准时间是2005年7月30日7点18分20秒,那么我用localtime()函数在中国地区获得的本地时间会比世界标准时间晚8个小时,即2005年7月30日15点18分20秒。
(1)固定格式
我们可以通过asctime()函数和ctime()函数将时间以固定的格式显示出来,两者的返回值都是char*型的字符串。返回的时间格式为:
星期几 月份 日期 时:分:秒 年\n\0
例如:Wed Jan 02 02:03:55 1980\n\0
其中\n是一个换行符,\0是一个空字符,表示字符串结束。
下面是两个函数的原型:
char*asctime(const structtm* timeptr);
char *ctime(const time_t *timer);
其中asctime()函数是通过tm结构来生成具有固定格式的保存时间信息的字符串,而ctime()是通过日历时间来生成时间字符串。这样的话,asctime()函数只是把tm结构对象中的各个域填到时间字符串的相应位置就行了,而ctime()函数需要先参照本地的时间设置,把日历时间转化为本地时间,然后再生成格式化后的字符串。
也可以使用_strdate()和_strtime()函数直接输出固定格式的日期好时间,两个函数的原型:
char*_strdate(char *datestr );//返回固定格式的本地日期
char*_strtime(char *timestr );// 返回固定格式的本地时间
我一般使用这两个函数来获取当前的系统日期和时间,比使用CTime类快捷多了,也推荐大家使用。
(2)自定义格式
可以使用strftime()函数将时间格式化为我们想要的格式。它的原型如下:
size_tstrftime(
char *strDest,
size_t maxsize,
const char *format,
const struct tm *timeptr
);
我们可以根据format指向字符串中格式命令把timeptr中保存的时间信息放在strDest指向的字符串中,最多向strDest中存放maxsize个字符。该函数返回向strDest指向的字符串中放置的字符数。 具体格式请参看MSDN.
有时候在实际应用中要计算一个事件持续的时间长度,比如计算打字速度。可以使用clock()函数和difftime()函数,clock()可以精确到毫秒,difftime()只能精确到秒。函数的定义如下:
clock_t clock( void );
double difftime(time_t time1, time_ttime0);
clock()函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数,在MSDN中称之为挂钟时间(wal-clock)。其中clock_t是用来保存时间的数据类型,在time.h文件中,我们可以找到对它的定义:
#ifndef _CLOCK_T_DEFINED
typedef long clock_t;
#define _CLOCK_T_DEFINED
#endif
很明显,clock_t是一个长整形数。在time.h文件中,还定义了一个常量CLOCKS_PER_SEC,它用来表示一秒钟会有多少个时钟计时单元,其定义如下:
#define CLOCKS_PER_SEC((clock_t)1000)
可以看到每过千分之一秒(1毫秒),调用clock()函数返回的值就加1。下面举个例子,你可以使用公式clock()/CLOCKS_PER_SEC来计算一个进程自身的运行时间.
Difftime()函数虽然返回的以秒计算的时间间隔是double类型的,但这并不说明该时间具有同double一样的精确度,这是由它的参数觉得的(time_t是以秒为单位计算的)。
可以使用mktime()函数将用tm结构表示的时间转化为日历时间。其函数原型如下:
time_tmktime(struct tm * timeptr);
其返回值就是转化后的日历时间。这样我们就可以先制定一个分解时间,然后对这个时间进行操作了.
系统还提供标准的Windows API 函数供使用;来获取和设置系统日期时间,函数原型为:
void WINAPI GetLocalTime(LPSYSTEMTIME lpSystemTime);
BOOL WINAPI SetLocalTime(constSYSTEMTIME* lpSystemTime);
void WINAPI GetSystemTime(LPSYSTEMTIME lpSystemTime);
BOOL WINAPI SetSystemTime(constSYSTEMTIME* lpSystemTime);
GetLocalTime()返回的是本地系统的时间,在不同的机器中会有不同的结果,这和你在控制面板中的时区设置有关. 该函数是获取的系统当前所属时区的时间, 比如说, 在北京时区, 那么获取的该时间的时间。而GetSystemTime()返回的是格林尼治时间(UTC), 是全球标准时间。SYSTEMTIME结果和TM结构很像,详情请参考MSDN.
(1)time.h中提供的各类函数中,每类函数中有几种形式,支持不同的系统设置,如单字节字符集合\多字节字符集(_w)、32位的\64位的,还有就是_s结尾的,表示比较安全的函数,推荐使用哦。不要被他们吓到了哈。
(2)若仅仅是想得到当前的日期和时间,推荐使用_strdate()和_strtime()函数,快捷方便,并直接返回你要的结果,不如意的就是格式是固定的,但格式是比较的通用的,也可以接受。
BOOL CGetDateTimeDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX& 0xFFF0) ==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX< 0xF000);
CMenu* pSysMenu= GetSystemMenu(FALSE);
if (pSysMenu !=NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon,TRUE); //设置大图标
SetIcon(m_hIcon,FALSE); //设置小图标
// TODO: 在此添加额外的初始化代码
m_stMail.SetURL("[email protected]");
m_stWeb.SetURL("http://blog.csdn.net/cbnotes");
//先得到日历时间:此时距离-01-01 00:00:00经历的秒数
//time_t ltime;
m_nEdit1 = time(NULL);//或者time(&m_nEdit1)
//将日历时间转化为标准的日期和时间格式及tm结构体形式
tm *gm,*local;
gm = gmtime(&m_nEdit1); //得到UTC(世界标准时间或格林尼治时间)建议使用gmtime_s(&gm,&m_nEdit1);比较安全
m_szEdit2.Format("%d/%02d/%02d %02d:%02d:%02d第%d天星期%d (%d)",gm->tm_year+1900,gm->tm_mon+1,gm->tm_mday,gm->tm_hour,gm->tm_min,gm->tm_sec,gm->tm_yday,gm->tm_wday,gm->tm_isdst);
local = localtime(&m_nEdit1);//得到本地时间,中国时间比UTC时间晚小时
m_szEdit3.Format("%d/%02d/%02d %02d:%02d:%02d第%d天星期%d (%d)",local->tm_year+1900,local->tm_mon+1,local->tm_mday,local->tm_hour,local->tm_min,local->tm_sec,local->tm_yday,local->tm_wday,local->tm_isdst);
//返回固定的时间格式:
char *buf =NULL;
//buf = asctime(gm);//注意使用时结果将出错,原因大概就是没有使用安全函数gmtime_s吧,值被改变了
buf = asctime(gmtime(&m_nEdit1));//返回tm格式的固定格式:返回UTC时间
//buf = asctime(localtime(&m_nEdit1));//返回本地时间
//buf = ctime(&m_nEdit1); //返回日历时间的固定格式
m_szEdit4.Format("%s",buf);
//固定格式:_strdate()格式为:mm/dd/yy _strtime()格式为:hh:mm:ss
char tempBuf1[9], tempBuf2[9];
m_szEdit5.Format("%s %s",_strdate(tempBuf1),_strtime(tempBuf2));
//自定义时间格式:推荐使用:%x(日期) %X(时间) %c(本地日期时间)%#c(Tuesday, March 14, 1995, 12:41:29) %#x(Tuesday, March 14, 1995) %a(星期简写) %b(月份简写)
char tmpbuf[128];
strftime(tmpbuf,128,"%Y年%m月%d日第%W周星期%w 第%j天",localtime(&m_nEdit1));
m_szEdit6.Format("%s",tmpbuf);
strftime(tmpbuf,128,"%Y-%m-%d %a %I:%M:%S %p",localtime(&m_nEdit1));
m_szEdit7.Format("%s",tmpbuf);
strftime(tmpbuf,128,"%#c",localtime(&m_nEdit1));
m_szEdit8.Format("%s",tmpbuf);
//计算持续时间的长度
// clock();//精确到毫秒级:该函数返回值是硬件滴答数,要换算成秒或者毫秒,需要除以CLK_TCK或者CLK_TCK CLOCKS_PER_SEC
//difftime()//只能精确到秒
//分解时间转化为日历时间
//将时间tm转换为日历时间
//计算-04-12是星期几?
tm t;
t.tm_year =1989 - 1900;
t.tm_mon = 3;
t.tm_mday = 12;
t.tm_hour= 0;
t.tm_min = 0;
t.tm_sec = 1;
t.tm_isdst = 0;
time_t t_of_day= mktime(&t);
m_szEdit12.Format("%s",ctime(&t_of_day));
//mktime();//将本地时间转换为日历时间
//_mkgmtime();//将UTC时间转换为UTC的日历时间
//The Win32 API GetLocalTime and SetLocalTime should beused instead
SYSTEMTIME systm;
GetLocalTime(&systm);//能得到毫秒级
m_szEdit13.Format("%d年%02d月%02d日星期%d:%02d:%02d:%02d:%d",systm.wYear,systm.wMonth,systm.wDay,systm.wDayOfWeek,systm.wHour,systm.wMinute,systm.wSecond,systm.wMilliseconds);
GetSystemTime(&systm);//能得到毫秒级
m_szEdit11.Format("%d年%02d月%02d日星期%d:%02d:%02d:%02d:%d",systm.wYear,systm.wMonth,systm.wDay,systm.wDayOfWeek,systm.wHour,systm.wMinute,systm.wSecond,systm.wMilliseconds);
//SetLocalTime();//修改本地的时间就不演示了。就是先设置systm值,再调用该函数。
UpdateData(FALSE);
return TRUE; // 除非将焦点设置到控件,否则返回TRUE
}
//计时计算
void CGetDateTimeDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CString szText;
GetDlgItem(IDC_BUTTON1)->GetWindowText(szText);
if (szText =="开始计时")
{
GetDlgItem(IDC_BUTTON1)->SetWindowText("停止计时");
m_szEdit9 = "等待结束...";
m_szEdit10 = "等待结束...";
UpdateData(FALSE);
m_start1 = clock();
m_start2 = time(NULL);
}
else
{
m_end2 = time(NULL);
m_end1 = clock();
double result1 = (double)(m_end1 -m_start1)/CLOCKS_PER_SEC;
double result2 = difftime(m_end2,m_start2);
m_szEdit9.Format("%d个滴答= %f秒",m_end1 -m_start1,result1);
m_szEdit10.Format("%f秒",result2);
UpdateData(FALSE);
GetDlgItem(IDC_BUTTON1)->SetWindowText("开始计时");
}
}
http://download.csdn.net/detail/cbnotes/4976848
欢迎大家修改和指正。
转载标明出处,谢谢合作. http://blog.csdn.net/cbNotes