当前位置: 首页 > news >正文

C/C++时间函数详解及使用场景

一、基本概念

C/C++中处理时间主要有两种方式:

  1. C-style时间函数(定义在<time.h><ctime>中)
  2. C++11引入的<chrono>库(更现代的时间处理方式)

二、C-style时间函数

1. 核心数据类型

  • time_t:通常为long类型,表示从1970年1月1日00:00:00(UNIX纪元)到当前时刻的秒数
  • struct tm:包含年月日时分秒等字段的结构体
  • clock_t:用于测量处理器时间的类型

2. 常用函数及示例

(1) 获取当前时间
#include <time.h>
#include <stdio.h>int main() {time_t now;time(&now);  // 获取当前时间printf("当前时间戳: %ld\n", now);return 0;
}
(2) 时间转换
struct tm *local_time = localtime(&now);  // 转换为本地时间
printf("%d年%d月%d日 %d:%d:%d\n", local_time->tm_year + 1900,local_time->tm_mon + 1,local_time->tm_mday,local_time->tm_hour,local_time->tm_min,local_time->tm_sec);
(3) 时间格式化
#include <time.h>
#include<stdio.h>
#include<string.h>
#include <pthread.h>
#include <stdbool.h>
#include<sys/time.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
bool getTimStrS(char* data,const int iLen)
{    char buffer[64];memset(buffer, 0, sizeof(buffer));struct timeval tv;struct tm      tm;size_t         len = 28;memset(&tv, 0, sizeof(tv));memset(&tm, 0, sizeof(tm));gettimeofday(&tv, NULL);localtime_r(&tv.tv_sec, &tm);strftime(buffer, 64, "%Y-%m-%d %H:%M:%S", &tm);if(data&&iLen>sizeof(buffer)){    strcpy(data,buffer);return true;    }return false;
}//带毫秒
bool getTimStrMs(char* data,const int iLen)
{char buf[32] = {0};struct timeval tv;struct tm      tm;size_t         len = 28;memset(&tv, 0, sizeof(tv));memset(&tm, 0, sizeof(tm));gettimeofday(&tv, NULL);localtime_r(&tv.tv_sec, &tm);strftime(buf, len, "%Y-%m-%d %H:%M:%S", &tm);len = strlen(buf);snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ".%03ld", tv.tv_usec / 1000);if (data && iLen > strlen(buf)) {strncpy(data, buf, iLen - 1);data[iLen - 1] = '\0';return true;}return false;
}
(4) 计算时间差秒
time_t start, end;
time(&start);
// 执行一些操作...
time(&end);
double diff = difftime(end, start);  // 计算时间差(秒)
printf("耗时: %.2f秒\n", diff);

(5)计算时间差(毫秒)

#include <sys/time.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
// 使用更明确的类型定义
typedef uint64_t DDWORD;
DDWORD getMsClick();
DDWORD getMsClickEnd(DDWORD timeRecord);
// 获取当前毫秒时间戳
inline DDWORD getMsClick() {struct timeval tv;if (gettimeofday(&tv, NULL) == -1) {fprintf(stderr,"gettimeofday failed\n");return -1;}return (DDWORD)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}// 计算耗时
inline DDWORD getMsClickEnd(DDWORD timeRecord) {return getMsClick() - timeRecord;
}int main()
{DDWORD start = getMsClick();sleep(2);start = getMsClickEnd(start);fprintf(stdout,"spend MS =%ld\n",start);return 0;
}

 

(6)计算时间差微秒

inline DDWORD getUsClick() {struct timeval tv;if (gettimeofday(&tv, NULL) == -1) {fprintf(stderr,"gettimeofday failed\n");return -1;}return (DDWORD)tv.tv_sec * 1000000 + tv.tv_usec;
}

3. 适用场景

 linxu c

三、C++11 chrono库

1. 核心组件

  • std::chrono::duration:表示时间间隔
  • std::chrono::time_point:表示时间点
  • std::chrono::system_clock:系统范围的实时时钟
  • std::chrono::steady_clock:单调时钟,适合测量时间间隔
1. std::chrono::duration(时间间隔)

模板类std::chrono::duration<Rep, Period>表示两个时间点之间的时间间隔,由计数值(Rep类型)和单位周期(Period,编译期有理数常量)组成。

std::chrono::duration<int> sec(3);          // 3秒
std::chrono::duration<long, std::milli> ms(500); // 500毫秒

特性‌

支持算术运算(如+、-、*)和比较操作。
提供预定义类型:nanoseconds、microseconds、milliseconds、seconds等。
可通过count()获取内部计数值,duration_cast转换单位。

2. std::chrono::time_point(时间点)

模板类std::chrono::time_point<Clock, Duration>表示特定时钟下的时间点,由Clock类型和uration类型共同决定。

auto now = std::chrono::system_clock::now(); // 获取当前系统时间点

操作‌

支持与duration的加减运算(如time_point + duration = time_point)。
可计算两个时间点的差值(返回duration)。
提供time_since_epoch()获取从时钟纪元开始的时长。

3. std::chrono::system_clock(系统时钟)

表示系统范围的实时时钟,与日历时间相关。
时间可能因系统时间调整(如NTP同步)而回退或跳跃。
提供to_time_t()和from_time_t()与C风格时间转换。

用途‌
适合记录日志时间、文件修改时间等需要与实际时间对应的场景。

4. std::chrono::steady_clock(单调时钟)

保证单调递增,不受系统时间调整影响。
适用于测量时间间隔(如性能分析)。
时钟纪元(epoch)通常为程序启动时间。
 

auto start = std::chrono::steady_clock::now();
// 执行操作...
auto end = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

对比总结

组件关键特性典型应用场景
duration时间间隔,支持单位转换和运算超时控制、耗时统计
time_point特定时钟下的时间点事件时间戳记录
system_clock实时时钟,可能非单调日志记录、日历时间相关操作
steady_clock单调递增,稳定计时性能分析、基准测试

2. 常用操作及示例

(1) 获取当前时间
#include <chrono>
#include <iostream>auto now = std::chrono::system_clock::now();
auto now_time = std::chrono::system_clock::to_time_t(now);
std::cout << "当前时间: " << ctime(&now_time);
(2) 高精度计时
auto start = std::chrono::high_resolution_clock::now();
// 执行一些操作...
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::cout << "耗时: " << duration.count() << "毫秒\n";

(3)封装时间计时

class HighPrecisionTimer {
public:using Clock = std::chrono::high_resolution_clock;using TimePoint = std::chrono::time_point<Clock>;using Duration = std::chrono::nanoseconds;// 启动计时器void start()  {try {start_time = Clock::now();} catch (const std::exception& e) {std::cerr << "Timer start error: " << e.what() << std::endl;throw;}}// 获取经过的时间(返回指定单位的计数值)template<typename T = std::chrono::milliseconds>auto elapsed() const {if (!is_running()) {throw std::logic_error("Timer not started");}return std::chrono::duration_cast<T>(Clock::now() - start_time).count();}// 获取经过的时间(返回duration对象)template<typename T = std::chrono::milliseconds>T elapsed_duration() const {if (!is_running()) {throw std::logic_error("Timer not started");}return std::chrono::duration_cast<T>(Clock::now() - start_time);}// 获取当前时间戳(毫秒)static int64_t currentTimestamp() noexcept {return std::chrono::duration_cast<std::chrono::milliseconds>(Clock::now().time_since_epoch()).count();}// 检查计时器是否已启动bool is_running() const noexcept {return start_time != TimePoint{};}// 重置计时器void reset() noexcept {start_time = TimePoint{};}// 获取并重置计时器(返回之前的时间)template<typename T = std::chrono::milliseconds>auto lap() {auto duration = elapsed<T>();start();return duration;}private:TimePoint start_time{};
};// 支持RAII自动计时的作用域计时器
class ScopedTimer {
public:explicit ScopedTimer(std::string tag, bool auto_log = true) : tag(std::move(tag)), auto_log(auto_log) {timer.start();}~ScopedTimer() {if (auto_log) {auto us = timer.elapsed<std::chrono::microseconds>();std::cout << tag << " elapsed: " << formatDuration(us) << "\n";}}// 获取当前耗时template<typename T = std::chrono::milliseconds>auto elapsed() const {return timer.elapsed<T>();}// 手动记录时间点void log(const std::string& message = "") {auto us = timer.elapsed<std::chrono::microseconds>();std::cout << tag << " [" << message << "] elapsed: " << formatDuration(us) << "\n";}private:std::string tag;HighPrecisionTimer timer;bool auto_log;// 智能格式化时间显示static std::string formatDuration(int64_t microseconds) {static const char* units[] = {"μs", "ms", "s"};static const int64_t thresholds[] = {1000, 1000};double value = microseconds;int unit_index = 0;while (unit_index < 2 && value >= thresholds[unit_index]) {value /= thresholds[unit_index];unit_index++;}std::ostringstream oss;oss << std::fixed << std::setprecision(unit_index > 0 ? 3 : 0) << value << units[unit_index];return oss.str();}
};// 线程安全的时间戳生成器
class TimestampGenerator {
public:static std::string getTimestamp(bool with_milliseconds = true) {std::lock_guard<std::mutex> lock(mutex);auto now = std::chrono::system_clock::now();auto time = std::chrono::system_clock::to_time_t(now);std::tm tm;localtime_r(&time, &tm);std::ostringstream oss;oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");if (with_milliseconds) {auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() % 1000;oss << "." << std::setfill('0') << std::setw(3) << ms;}return oss.str();}private:static std::mutex mutex;
};std::mutex TimestampGenerator::mutex;
void exampleUsage() {// 基本计时器使用HighPrecisionTimer timer;timer.start();// 执行一些操作...auto elapsed_ms = timer.elapsed(); // 默认毫秒auto elapsed_ns = timer.elapsed<std::chrono::nanoseconds>();std::cout << "Operation took " << elapsed_ms << "ms (" << elapsed_ns << "ns)\n";// 作用域计时器{ScopedTimer timer("Database query");// 执行数据库查询...} // 自动输出耗时// 带手动记录的作用域计时器{ScopedTimer timer("Complex operation", false);// 第一步操作...timer.log("Step 1 completed");// 第二步操作...timer.log("Step 2 completed");}// 获取时间戳std::cout << "Current timestamp: " << TimestampGenerator::getTimestamp() << "\n";std::cout << "Current time (no ms): " << TimestampGenerator::getTimestamp(false) << "\n";
}

(4)时间打印

#include <chrono>
#include <format>
#include <stdexcept>
#include <string>namespace timestamp_utils {// 预定义格式constexpr auto kSecFormat = "{:%Y-%m-%d %H:%M:%S}";// 获取北京时间时区(UTC+8)inline const std::chrono::time_zone* get_beijing_timezone() {try {return std::chrono::locate_zone("Asia/Shanghai"); // 或 "Etc/GMT-8"} catch (...) {return std::chrono::locate_zone("UTC"); // 回退方案}}// 安全格式化模板(带时区转换)template<typename Duration>std::string format_safe(std::chrono::system_clock::time_point tp) {try {const auto* tz = get_beijing_timezone();auto local_time = std::chrono::zoned_time(tz, tp);if constexpr (std::is_same_v<Duration, std::chrono::milliseconds>) {auto sec = std::chrono::floor<std::chrono::seconds>(tp);auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(tp - sec);return std::format("{}.{:03d}", std::chrono::floor<std::chrono::seconds>(local_time.get_local_time()),ms.count());} else {return std::format(kSecFormat, std::chrono::floor<Duration>(local_time.get_local_time()));}} catch (...) {return std::format(kSecFormat, std::chrono::zoned_time(get_beijing_timezone(), std::chrono::system_clock::now()).get_local_time());}}// 获取当前北京时间(秒级)std::string get_timestamp() {return format_safe<std::chrono::seconds>(std::chrono::system_clock::now());}// 获取当前北京时间(毫秒级)std::string get_timestamp_with_millis() {return format_safe<std::chrono::milliseconds>(std::chrono::system_clock::now());}
}void test()
{std::cout << "Current time: " << timestamp_utils ::get_timestamp() << "\n";std::cout << "Current time with millis: " << timestamp_utils ::get_timestamp_with_millis() << "\n";
}

3. 适用场景

  • 需要高精度计时(毫秒、微秒、纳秒级)
  • 复杂的日期时间计算
  • C++11及以上环境

四、Windows平台特有函数

1. GetTickCount()

#include <windows.h>DWORD start = GetTickCount();
// 执行一些操作...
DWORD end = GetTickCount();
printf("耗时: %d毫秒\n", end - start);

2. 适用场景

  • Windows平台专用程序
  • 需要毫秒级精度但不需纳秒级的场景

五、MFC时间类(CTime和CTimeSpan)

CTime time = CTime::GetCurrentTime();
CString str = time.Format("%Y-%m-%d %H:%M:%S");
CTimeSpan span(0, 1, 30, 0);  // 1小时30分钟
CTime newTime = time + span;

适用场景:MFC应用程序开发6

六、异同对比

特性C-style时间函数C++ chronoWindows APIMFC类
精度秒级纳秒级毫秒级秒级
跨平台C++11及以上仅Windows仅Windows
复杂度简单中等简单简单
主要用途基本日期时间操作高精度计时Windows计时MFC应用

七、使用建议

  1. 简单日期时间操作‌:优先使用C-style函数,兼容性好
  2. 高精度计时‌:使用C++ chrono库
  3. Windows平台‌:考虑GetTickCount()等API
  4. MFC开发‌:使用CTime和CTimeSpan类
  5. 跨平台高精度‌:C++ chrono是最佳选择

八、延时函数

1. 标准库方法(推荐,跨平台)

  • std::this_thread::sleep_for
    需包含 <chrono><thread> 头文件,支持纳秒级精度:
    #include <chrono> 
    #include <thread> 
    void delay(int ms) 
    { std::this_thread::sleep_for(std::chrono::milliseconds(ms)); 
    } 
    // 使用示例:delay(3000); // 延时3秒 

2. 传统 C 库方法

  • sleep / usleep
    • sleep(秒级)和 usleep(微秒级)需包含 <unistd.h>(Linux)或 <windows.h>(Windows):
      #include <ctime>
      void delay_sec(int sec) {time_t start = time(nullptr);while (time(nullptr) - start < sec);
      }
      
    • Windows 下等效函数为 Sleep(毫秒级,首字母大写):
      #include <windows.h> 
      Sleep(3000); // 延时3秒 

3. 手动实现延时(不依赖库)

  • 基于 clock()
    使用 <ctime> 头文件,适合简单场景但精度有限:
    #include <ctime>
    void delay_ms(int ms) {clock_t end = clock() + (ms * CLOCKS_PER_SEC / 1000);while (clock() < end);
    }
    
  • 基于 time()
    秒级延时,适用于对精度要求不高的场景:
    #include <ctime>
    void delay_sec(int sec) {time_t start = time(nullptr);while (time(nullptr) - start < sec);
    }
    

4. 注意事项

  • 跨平台兼容性
    std::this_thread::sleep_for 是 C++11 标准,兼容性最佳;sleep/usleep 需区分系统。
  • 精度差异
    clock() 依赖 CPU 时钟频率,time() 精度通常为秒级,而 std::chrono 支持更高精度。
  • 阻塞线程
    所有延时函数均会阻塞当前线程,若需非阻塞延时需结合异步编程。

总结建议

场景推荐方法头文件
高精度跨平台std::this_thread::sleep_for<chrono>, <thread>
Linux 系统sleep / usleep<unistd.h>
Windows 系统Sleep<windows.h>
无库依赖简单实现clock()time() 循环<ctime>

相关文章:

  • ArrayUtils:数组操作的“变形金刚“——让你的数组七十二变
  • [Unity]-[UI]-[Prefab] 关于Unity UGUI 的布局及组件讲解
  • C# 综合示例 库存管理系统7 主界面(FormMain)
  • 《AI大模型趣味实战》基于RAG向量数据库的知识库AI问答助手设计与实现
  • (CAS:130100-20-8)Mag-Fura-2 AM Cell Permeant,配制方法步骤
  • 国产32位单片机PY32F003,ADC使用注意事项
  • Ubuntu中的防火墙工具
  • 网络安全概述:定义、重要性与发展历程
  • 从零开始用Turtle绘制分形树,数学与编程的完美结合!
  • matplotlib2-统计分布图
  • 【TS入门笔记2---基础语法】
  • 多模态大语言模型arxiv论文略读(四十一)
  • 03实战篇Redis02(优惠卷秒杀、分布式锁)
  • 精益数据分析(23/126):把握创业阶段与第一关键指标
  • 隐形革命:环境智能如何重构“人-机-境“共生新秩序
  • MySql 数据 结构 转为SqlServer (简单)
  • 百度文心4.5 Turbo与DeepSeek、豆包、元宝对比:技术路径与市场格局分析​​
  • python基础-requests结合AI实现自动化数据抓取
  • iphonex uniapp textarea标签兼容性处理过程梳理
  • 秒级到毫秒:BFD的速度革命
  • 建投读书会·东西汇流|全球物品:跨文化交流视域下的明清外销瓷
  • 政治局会议:积极维护多边主义,反对单边霸凌行径
  • 特朗普签署行政命令推动深海采矿,被指无视国际规则,引发环境担忧
  • “住手!”特朗普罕见公开谴责普京,俄称愿恢复对话但要看美方行动
  • 安徽铁塔再通报“会议室不雅行为”事件:涉事员工停职检查
  • 帕力旦·吐尔逊已任喀什大学党委副书记、校长