笔记1:VC 获取系统时间的方法
- 推荐的获取方法
- 获取时间方法种类
- 各种获取时间方法详解
- 方法1:time_t变量 和 time(time_t*)方法
- 方法2:system(" time" ); 改变电脑的时间设定
- 方法3:SYSTEMTIME变量,GetLocalTime(SYSTEMTIME*)获取当地时间方法、GetSystemTime(SYSTEMTIME*)获得世界协调时间(UTC)时间方法 ;
- 方法4:GetTickCount()方法返回值DWORD类型
- 方法5:clock_t clock() 方法获得CPU时间
- 方法6:BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency)和BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount)
- 方法7:timeGetTime()
- 方法8:CTime类和COleDateTime类
推荐的获取方法
- 获取一般精度时间(精度:秒),首推COleDateTime类
- 获取高精度时间(精度:毫秒,可能不足1毫秒),推荐timeGetTime()
- 方法 获取最高精度时间,推荐 QueryPerformanceCounterQueryPerformanceFrequency函数用于分辨率要求更高的时间测量。
获取时间方法种类
- CRT函数,即:C标准库(Windows平台下 C语言函数 即:C Runtime library)
方法1:time_t变量 和 time(time_t*)方法;精度:秒
方法2:system(" time" ); 可以改变电脑的时间设定 - 系统API
方法2:SYSTEMTIME变量,GetLocalTime(SYSTEMTIME*)获取当地时间方法、GetSystemTime(SYSTEMTIME*)获得世界协调时间(UTC)时间方法 ; 精度:55毫秒
方法3:GetTickCount()方法返回值DWORD类型 精度:55ms(1个tick就是55ms)
方法4:clock_t clock() 方法获得CPU时间;精度:1/CLOCKS_PER_SEC秒
方法5: BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency)获得高精度时间——系统的计数器的频率;
BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount)获取计数器的值
然后用两次计数器的差除以Frequency就得到时间;精度毫秒
方法6:timeGetTime();精度:毫秒 - MFC类 ATL库
方法7:CTime类和COleDateTime类 ;精度:秒
CTimeSpan和COleDateTime 时间间隔类
各种获取时间方法详解
方法1:time_t变量 和 time(time_t*)方法
精度:秒
优点:仅使用C标准库
#include <time.h> // time()方法的头文件
#include <stdio.h>
time_t t=time(0);
char tmp[64];
strftime(tmp, sizeof(tmp), "%Y/%m/%d %X %A 本年第%j天%z", localtime(&t));
方法2:system(" time" ); 改变电脑的时间设定
精度:秒
优点:C语言 系统函数
函数原型:int system(const char * command)
说明:在windows系统中,system函数直接在控制台调用一个command命令。
在Linux/Unix系统中,system函数会调用fork函数产生子进程,由子进程来执行command命令,命令执行完后随即返回原调用的进程。
返回值:命令执行成功返回0,执行失败返回-1。
#include<stdlib.h> // system() 原型的头文件
#include<iostream>
using namespace std;
system("time"); // 显示或设置系统时间
//****修改操作系统时间 方法1****
system("time 12:23:20"); // 修改时间
system("date 2013-12-1"); // 修改日期
system()函数还能做很多事情
例如:
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
int main(void)
{
char input[100];
system("shutdown -s -t 60"); //这是Windows系统下的一个关机命令
flag:
printf("你的电脑将在一分钟后关机,如果输入“我是猪”,就会取消关机!\n请输入: ");
scanf("%s",input);
if(0==strcmp(input,"我是猪"))
{
system("shutdown -a"); //取消关机命令
}
else
{
goto flag;
}
return 0;
}
附录
一些system()函数的参数及实现的功能
表格里的内容可以通过 system(“HELP”);语句获取。
参数 | 功能 | 说明 |
---|---|---|
ASSOC | 显示或修改文件扩展名关联 | |
ATTRIB | 显示或更改文件属性 | |
BREAK | 设置或清除扩展式 CTRL+C 检查 | |
BCDEDIT | 设置启动数据库中的属性以控制启动加载 | |
CACLS | 显示或修改文件的访问控制列表(ACL) | |
CALL | 从另一个批处理程序调用这一个 | |
CD | 显示当前目录的名称或将其更改 | |
CHCP | 显示或设置活动代码页数 | |
CHDIR | 显示当前目录的名称或将其更改 | |
CHKDSK | 检查磁盘并显示状态报告 | |
CHKNTFS | 显示或修改启动时间磁盘检查 | |
CLS | 清除屏幕 | |
CMD | 打开另一个 Windows 命令解释程序窗口 | |
COLOR | 设置默认控制台前景和背景颜色 | |
COMP | 比较两个或两套文件的内容 | |
COMPACT | 显示或更改 NTFS 分区上文件的压缩 | |
CONVERT | 将 FAT 卷转换成 NTFS 但是你不能转换当前驱动器 | |
COPY | 将至少一个文件复制到另一个位置 | |
DATE | 显示或设置日期 | 后面加 /t 表示显示日期 |
DEL | 删除至少一个文件 | |
DIR | 显示一个目录中的文件和子目录 | |
DISKPART | 显示或配置磁盘分区属性 | |
DOSKEY | 编辑命令行、撤回 Windows 命令并创建宏 | |
DRIVERQUERY | 显示当前设备驱动程序状态和属性 | |
ECHO | 显示消息,或将命令回显打开或关闭 | |
ENDLOCAL | 结束批文件中环境更改的本地化 | |
ERASE | 删除一个或多个文件 | * |
EXIT | 退出 CMD.EXE 程序(命令解释程序) | * |
FC | 比较两个文件或两个文件集并显示它们之间的不同 | |
FIND | 在一个或多个文件中搜索一个文本字符串 | |
FINDSTR | 在多个文件中搜索字符串 | |
FOR | 为一组文件中的每个文件运行一个指定的命令 | |
FORMAT | 格式化磁盘,以便用于 Windows | |
FSUTIL | 显示或配置文件系统属性 | |
FTYPE | 显示或修改在文件扩展名关联中使用的文件类型 | |
GOTO | 将 Windows 命令解释程序定向到批处理程序中某个带标签的行 | |
GPRESULT | 显示计算机或用户的组策略信息 | |
GRAFTABL | 使 Windows 在图形模式下显示扩展字符集 * | |
HELP | 提供 Windows 命令的帮助信息 | |
ICACLS | 显示、修改、备份或还原文件和目录的 ACL | |
IF | 在批处理程序中执行有条件的处理操作 | |
LABEL | 创建、更改或删除磁盘的卷标 | |
MD | 创建一个目录 | |
MKDIR | 创建一个目录 | |
MKLINK | 创建符号链接和硬链接 | |
MODE | 配置系统设备 | |
MORE | 逐屏显示输出 | * |
MOVE | 将一个或多个文件从一个目录移动到另一个目录 | |
OPENFILES | 显示远程用户为了文件共享而打开的文件 | |
PATH | 为 可执行文件显示或设置搜索路径 | |
PAUSE | 暂停批处理文件的处理并显示消息 | |
POPD | 还原通过 PUSHD 保存的当前目录的上一个值 | |
打印一个文本文件 | ||
PROMPT | 更改 Windows 命令提示 | |
PUSHD | 保存当前目录,然后对其进行更改 | |
RD | 删除目录 | |
RECOVER | 从损坏的或有缺陷的磁盘中恢复可读信息 * | |
REM | 记录批处理文件或 CONFIG.SYS 中的注释(批注) | |
REN | 重命名文件 | |
RENAME | 重命名文件 | |
REPLACE | 替换文件 * | |
RMDIR | 删除目录 | |
ROBOCOPY | 复制文件和目录树的高级实用工具 | |
SET | 显示、设置或删除 Windows 环境变量 | |
SETLOCAL | 开始本地化批处理文件中的环境更改 | |
SC | 显示或配置服务(后台进程) | |
SCHTASKS | 安排在一台计算机上运行命令和程序 | |
SHIFT | 调整批处理文件中可替换参数的位置 | |
SHUTDOWN | 允许通过本地或远程方式正确关闭计算机 | |
SORT | 对输入排序 | |
START | 启动单独的窗口以运行指定的程序或命令 | |
SUBST | 将路径与驱动器号关联 | |
SYSTEMINFO | 显示计算机的特定属性和配置 | |
TASKLIST | 显示包括服务在内的所有当前运行的任务 | |
TASKKILL | 中止或停止正在运行的进程或应用程序 | |
TIME | 显示或设置系统时间 后面加 /t 表示显示时间 | |
TITLE | 设置 CMD.EXE 会话的窗口标题 “TITLE 你想改成啥” | |
TREE | 以图形方式显示驱动程序或路径的目录结构 “TREE D:” | |
TYPE | 显示文本文件的内容 “TYPE D:\文本.txt” | |
VER | 显示 Windows 的版本 | |
VERIFY | 告诉 Windows 是否进行验证,以确保文件正确写入磁盘 | |
VOL | 显示磁盘卷标和序列号 | |
XCOPY | 复制文件和目录树 | |
WMIC | 在交互式命令 shell 中显示 WMI 信息 |
方法3:SYSTEMTIME变量,GetLocalTime(SYSTEMTIME*)获取当地时间方法、GetSystemTime(SYSTEMTIME*)获得世界协调时间(UTC)时间方法 ;
精度:55毫秒
优点:能精确到毫秒
缺点:使用了Windows API,无法跨平台
#include <windows.h> // GetLocalTime()方法头文件
#include<stdio.h>
// 获得操作系统时间
SYSTEMTIME sys;
GetLocalTime(&sys);
printf("M/d/d d:d:d:d 星期\n",
sys.wYear,
sys.wMonth,
sys.wDay,
sys.wHour,
sys.wMinute,
sys.wSecond,
sys.wMilliseconds, // 毫秒
sys.wDayOfWeek);
//****修改操作系统时间 方法2 ****
sys.wYear=2015; //修改年,其他类似
SetLocalTime( &sys );
说明:这样,系统时间的年,就变成了2015年。但有的机器并不会改变,具体原因不太清楚。这种情况第1种方法system(“time 2015-10-10”)。
方法4:GetTickCount()方法返回值DWORD类型
精度:55毫秒
函数原型:DWORD GetTickCount(void);
在Release版本中,该函数从0开始计时,返回自设备启动后的毫秒数(不含系统暂停时间)。
在Debug版本中,设备启动后便从计时器中减去180秒。这样方便测试使用该函数的代码的正确溢出处理。
返回值:如正确,返回毫秒数。
#include <Winbase.h> //GetTickCount() 所需头函数
// ***用来计算某个操作所使用的时间***
DWORD Start=GetTickCount;
//执行耗时的操作
...
DWORD Stop=GetTickCount;
TimeUsed=(Stop-Start)/1000; //使用了xxx秒
// ***用来定时***
DWORD dwLast;
DWORD dwCurrent;
DWORD dwInterval = 1000;
dwLast = GetTickCount();
int i = 0;
while(true)
{
dwCurrent = GetTickCount();
if( dwCurrent - dwLast < dwInterval )
continue;
//your code to be executed when interval is elapsed
printf("dwLast,dwCurrent,diff:%d,%d,%d ",dwLast,dwCurrent,dwCurrent-dwLast);
//your code to determine when to break
if( i > 10 ) break;
i++;
dwLast = dwCurrent;
printf("Time is up!");
break;
}
getchar();
方法5:clock_t clock() 方法获得CPU时间
精度:精确到1/CLOCKS_PER_SEC秒
clock()是C/C++中的计时函数,而与其相关的数据类型是clock_t
在time.h文件中,还定义了一个常量CLOCKS_PER_SEC,它用来表示一秒钟会有多少个时钟计时单元,其定义如下:
#define CLOCKS_PER_SEC ((clock_t)1000)
函数原型:clock_t clock(void) ;
返回值:clock_t是一个长整形数
#include <stdio.h>
#include <stdlib.h>
#include <time.h> // clock() 所需头文件
int main(void)
{
long i = 10000000L;
clock_t start, finish;
double duration;
/* 测量一个事件持续的时间*/
printf( "Time to do %ld empty loops is ", i) ;
start = clock();
while( i-- );
finish = clock();
duration = (double)(finish - start) // CLOCKS_PER_SEC;
printf( "%f seconds\n", duration );
system("pause");
}
方法6:BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency)和BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount)
利用这两个函数可以创建跟硬件时钟的晶振一样精确的计时器。
在进行定时之前,先调用QueryPerformanceFrequency()函数获得机器内部定时器的时钟频率, 然后在需要严格定时的事件发生之前和发生之后分别调用QueryPerformanceCounter()函数,利用两次获得的计数之差及时钟频率,计算出事件经 历的精确时间。
1.如下函数查询cpu时钟频率,(如我的cpu是2.89GHz,得到2893460000)
BOOL QueryPerformanceFrequency( LARGE_INTEGER *lpFrequency // current frequency);
2.再获取高精确度性能计数器的值
BOOL QueryPerformanceCounter( LARGE_INTEGER *lpPerformanceCount // counter value);
计数器的值除以频率得到当前系统运行时间(秒):
LARGE_INTEGER startTime = (*lpPerformanceCount) /(*lpFrequency )
3.运行所需计时的代码段后再次获取性能计数器的值
BOOL QueryPerformanceCounter( LARGE_INTEGER *lpPerformanceCount2 // counter value);
计数器的值除以频率得到当前系统运行时间(秒):
LARGE_INTEGER endTime =(*lpPerformanceCount2) /(*lpFrequency )
4.endTime-startTime即为两次调用QueryPerformanceCounter期间的精度计时时间。
这结果是秒级的,如果要更精确的可以将时钟频率除以相应值再作后面计算。
如要获得毫秒级的:LARGE_INTEGER tick=*lpFrequency/1000
LARGE_INTEGER startTime = (*lpPerformanceCount) /tick
LARGE_INTEGER endTime =(*lpPerformanceCount2) /tick
endTime - startTime
方法7:timeGetTime()
- 精度:毫秒
- 函数以 毫秒 计的系统时间。该时间为从系统开启算起所经过的时间。
在SDK中,可以用 DWORD timeGetTime(VOID)函数获取系统时间,其返回值是毫秒单位的。可以用其实现延时功能的函数。
#include <Mmsystem.h> // timeGetTime()所需头文件
void Delay(DWORD delayTime)
{
DWORD delayTimeBegin;
DWORD delayTimeEnd;
delayTimeBegin = timeGetTime();
do{
delayTimeEnd = timeGetTime();
}while(delayTimeEnd - delayTimeBegin < delayTime)
}
注:在使用timeGetTime()函数之前应先包含头文件#include <Mmsystem.h> 或者
#include <Windows.h>并在project->settings->link->Object/library modules中添加winmm.lib (注意使用<Windows.h> 必须 加载 “winmm.lib” )
也可以在文件头部添加 #pragma comment( lib,“winmm.lib” )
命令行:#pragma comment( lib,“xxx.lib” )时预编译处理指令,让vc将winmm.lib添加到工程中去进行编译。
备注:该函数与timeGetSystemTime()函数的唯一不同是timeGetSystemTime()函数使用MMTIME结构返回系统时间。TimeGetSystemTime()比timeGetTime()需要更多的系统开销。 注意timeGetTime()函数是一个双字。这个值在0到2^32之间。大约49.71天。
注意:如果在代码中直接将该值用于计算,会导致一些问题,特别是用该值来控制代码的执行。一般利用两个timeGetTime()函数返回值的不同来用于计算。
QueryPerformanceCounter QueryPerformanceFrequency函数用于分辨率要求更高的时间测量。
Windows95 默认分辨率是1毫秒,无论是否调用timeBeginPeriod和timeEndPeriod函数。
方法8:CTime类和COleDateTime类
精度:秒
Ctime类与COleDateTime类功能类似,两者区别:功能上,于COleDateTime使用更广泛,该类允许用户获得一年中的某一天,还可以分析时间字符串;使用隐患上,COleDateTime使用DWORD变量,他表示从1900-12-30之后的天数(天是正数部分,小时、分、秒是小数部分)几千年内不会溢出。而CTime计算从1970-1-1后经过的秒数,所以2037年后他将达到4294967295后溢出。
基于如上理由:下面推荐使用COleDateTime类并只介绍该类和COleDateTimeSpan类。
下面展示一些 内联代码片
。
/*
创建方法
*/
// **方式1**
// 创建COleDateTime类
COleDateTime datetime;
// 获得本地时间
datetime = COleDateTime::GetCurrentTime();
// **方式2**
COleDateTime datetime1(1977,4,16,2,2,2);
/*
获得字符串
*/
// **方法1** COleDateTime类的Format()方法
CString strTime;
strTime = datetime.Format("%Y-%m-%d %H:%M:%S");
// **方法2** COleDateTime单独获取是的方法
strTime.Format("%.4d-%.2d-%.2d %d.2d:%.2d:%.2d",
datetime.GetYear(),
datetime.GetMonth(),
datetime.GetDay(),
datetime.GetHour(),
datetime.GetMinute(),
datatime.GetSecond());
// 获得一年中的某一天
int DayOfYear = datetime.GetDayOfYear();
/*
COleDateTime类的Format()参数说明:
Format的变量含义:
%a 周的缩写 英文
%A 周的全名 英文
%b 月的缩写 英文
%B 月的全名 英文
%c 完整的日期和时间 完整样式不明
%d 十进制形式的日期(01-31) 注意:不足2位自动补0
%H 24小时制的小时(00-24)
%I 12小时制的小时(01-12)
%j 十进制表示的一年的第几天(001-366)
%m 月的十进制表示(01-12) 小写m表示月
%M 十进制表示的分钟(00-59) 大写M表示分钟
%p 12小时制的上下午(AM/PM)标识
%S 十进制标识的秒
%U 一年中的第几个星期(00-51), 星期日是一周的第一天
%W 一年中的第几个星期(00-51), 星期一是一周的第一天
%w 十进制表示的星期几(0-6), 0表示星期天
%x 当前时区的日期
%X 当前时区的时间
%y 用两位数(后两位)表示的年(00-99),如1960年表示成60 小写y表示2位的年份
%Y 用四位数标示的年,如1960 大写Y表示4位年份
%z/Z 小写/大写的时区名,如果时区不知,则为空串
%% 百分比的标志
*/
/*
从字符串中解析时间
*/
// 需要测试字符串内时间的顺序
datetime.ParseDateTime("12:12:23 27 January 93");
//或者
date_time.ParseDateTime(CString("2008-04-18 09:00:00"));
/*
计算时间间隔
*/
// 初始化格式:年 月 日 时 分 秒
COleDateTime begin_date(1970, 1, 1, 0, 0, 0);
COleDateTime end_date(1990, 1, 1, 0, 0, 0);
COleDateTimeSpan timeSpan;
timeSpan = end_date - begin_date;
// 获得间隔多少天
long expi_date = timeSpan.GetDays();
// 知道间隔计算时间
// 时间间隔类 初始化格式:天 时 分 秒
COleDateTimeSpan timeSpan1(10, 0, 0, 0);
COleDateTime new_date = end_date - timeSpan1;
//或者
date_time += COleDateTimeSpan(Day, Hour, Minute, Second);
/*
说明:
COleDateTime重载了+,-,+=,-=等运算符,可以方便的让时间日期前进倒退;
*/
/*
与其他时间格式的转换
*/
// CString 转 COleDateTime
strTime = "2020-10-27 6:24:37";
COleVariant vtime(strTime); // COleVariant 变体类型
vtime.ChangeType(VT_DATE);
COleDateTime time2 = vtime;
// COleDateTime 转 SYSTEMTIME 转 CTime
COleDateTime time3(1970,4,18,2,2,2);
SYSTEMTIME systime;
VariantTimeToSystemTime(time3, &systime); // COleDateTime -> SYSTEMTIME
CTime tm(systime); // SYSTEMTIME -> CTime
// CTime 转 time_t 转 COleDateTime
time_t time4 = tm.GetTime(); // CTime -> time_t
COleDateTime time5(time4); // time_t -> COleDateTime