基于c++11的时间戳工具类, (TimestampUtil) 支持10位时间戳, 13位时间戳, 16位时间戳, 和19位时间戳的获取与转为格式化时间字符串

C++ 时间戳工具类 timestampUtil 基于c++11

  • 前言/工具类说明
  • 头文件(TimestampUtil.h)
  • 源文件(TimestampUtil.cpp文件)
  • 测试代码/使用示例
  • 测试结果

前言/工具类说明


       最近学习c++, 发现网络上几乎没有用c++编写的时间戳工具类(TimestampUtil). 今天在CSDN上参考了一些大佬的代码, 了解了c++11中获取和使用时间戳的步骤和方式, 总结后自己写了一个时间戳工具类. 基本覆盖日常编程中, 获取时间戳, 和将时间戳转化为格式化日期时间(字符串)的功能.
        - 考虑到跨平台的需求, 工具类中只使用了c++的时间库, 主要是chrono 和iomanip这两个库, 已避免使用任何C库函数. 以确保工具类可以在windows, linux等操作系统上正常编译和运行, 确保代码复制即用, 无需考虑系统差异(已测试无问题)
        - 接口函数注释较为详细, 根据头文件中的函数说明和测试代码中的示例使用
        - 由于是工具类, 已禁止继承和实例化. 所有函数均为static, 只能通过类名调用
        - 由于std:localtime函数是线程不安全的. 所以通过条件编译的方法, 在windows下使用std::localtime_s函数, linux以及类unix系统中使用localtime_r函数. 来规避localtime. 因此本类是线程安全的, 可以在多线程程序中使用.
        - 工具类基于c++11标准, 确保你的编译器最低支持c++11

头文件(TimestampUtil.h)


       头文件中主要包含TimestampUtil类的声明, 你可以根据注释, 通过类名调用public权限中的函数来使用本工具类

#pragma once

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace chrono;

// 临时存储数据用的结构体, 
// 如果你不准备给该工具类添加新功能, 你就不需要关心这个结构体
struct __timeData
{
    time_t timestamp = -1;
    string formatDatatime = "";
    int ms = -1;
    int cs = -1;
    int ns = -1;
};

/* ======================= 工具类声明, 接口声明, 函数说明 =================== */
class TimestampUtil final   // final禁止继承
{
/* 
    public中的函数均为工具类接口函数, 可根据需求使用类名调用
*/
public:

    /**
    * 获取当前时间戳
    * @param time_level 时间戳精度, 范围[0, 3]
    *   time_level = 0, 返回10位时间戳, 精确到秒
    *   time_level = 1, 返回13位时间戳, 精确到毫秒, 参数默认值
    *   time_level = 2, 返回16位时间戳, 精确到微秒
    *   time_level = 3, 返回19位时间戳, 精确到纳秒
    * @return time_t 时间戳
     */
    static time_t getCurrentTimestamp(int time_level = 1);


    /**
     * 获取当前的日期字符串, 如 2023-04-06
    */
    static string getCurrentFormatDate();


    /**
     * 获取当前的时间字符串, 如 22:01:26
    */
    static string getCurrentFormatTime();


    /**
     * 获取当前时间节点的格式化字符串, 可设置精度
     * @param time_level 格式字符串的精度
     *   time_level = 0, 返回精度为秒级的格式化字符串,      如: 2023-04-06 22:21:51     默认值
     *   time_level = 1, 返回精度为毫秒级的格式化字符串,    如: 2023-04-06 22:21:51 266
     *   time_level = 2, 返回精度为微妙级时的格式化字符串,  如: 2023-04-06 22:21:51 266.527
     *   time_level = 3, 返回精度为纳妙级的时格式化字符串,  如: 2023-04-06 22:21:51 266.527.300
     * @return 当前时间的格式化字符串
    */
    static string getCurrentFormatDatetime(int time_level = 0);


    /**
     * 将任意精度的时间戳, 转化为格式化日期的字符串. 如: 2023-04-06
     * @param timestamp 10位/13位/16位/19位时间戳
     * @return 时间戳中日期部分的格式化字符串. 
     *      如果返回nullptr, 说明传入的时间戳长度有误(传入的时间戳必须是10位, 13位, 16位, 19位的任意一种)
    */
    static string getFormatData(const time_t timestamp);


    /**
     * 将任意精度的时间戳, 转化为格式化时间的字符串(只获取时间部分, 精度秒). 如: 22:21:51
     * @param timestamp 10位/13位/16位/19位时间戳
     * @return 时间戳中的时间部分的格式化字符串
     *      如果返回nullptr, 说明传入的时间戳长度有误(传入的时间戳必须是10位, 13位, 16位, 19位的任意一种)
    */
    static string getFormatTime(const time_t timestamp);


    /**
     * 将任意精度的时间戳, 转化为格式化日期时间的字符串, 可设置精度
     * @param timestamp 10位/13位/16位/19位时间戳
     * @param time_level 精度水平
     *   time_level = 0, 返回精度为秒级的格式化字符串,      如: 2023-04-06 22:21:51     默认值
     *   time_level = 1, 返回精度为毫秒级的格式化字符串,    如: 2023-04-06 22:21:51 266
     *   time_level = 2, 返回精度为微妙级时的格式化字符串,  如: 2023-04-06 22:21:51 266.527
     *   time_level = 3, 返回精度为纳妙级的时格式化字符串,  如: 2023-04-06 22:21:51 266.527.300
     * @return 时间戳中的时间信息字符串
     *      如果返回nullptr, 说明传入的时间戳长度有误(传入的时间戳必须是10位, 13位, 16位, 19位的任意一种)
    */
    static string getFormatDataTime(time_t timestamp, int time_level = 0);



/*  
    private和protected权限的函数:
        如果你不准备为工具类添加新功能, 你就不需要关心下面的所有函数, 因为你无法调用到它们
        protected中主要是工具类内部计算时用到的函数 
*/
private:
    // 禁止实例化
    TimestampUtil() = delete;

// 无法在类外调用
protected:
    /** 检查/获取时间戳长度, 10位时间戳返回10, 13位返回13, 16位返回16, 19位会返回19 */
    static int checkBitLength(const time_t timestamp);

    /** 用于从操作系统中获取当前时间节点的数据(c++11标准) */ 
    static system_clock::time_point _getNow();

    /** 根据时间戳的长度返回精度水平, 10位时间戳精度为0. 13位精度为1, 16位精度为2, 19位精度为9,*/ 
    static int getTimeLevel(const time_t &timestamp);

    /** 根据时间戳计算毫秒, 微妙和纳秒的函数 */ 
    static void setFormatData(int time_level, const string &formatType, struct __timeData &timedata);

    /** 格式化日期计算函数 */
    static string buildFormatString(struct __timeData &timedata);

    /** 精度拟合函数, 用于解决外部的时间戳在转为格式化字符串时, 期望的精度和时间戳实际精度不符的问题 */
    static int timestampGabFix(int input_level, __timeData &timedata);
};

源文件(TimestampUtil.cpp文件)


       TimestampUtil.cpp文件为TimestampUtil.h的代码实现, 你可以删除TimestampUtil.cpp文件中的第一行(删掉include行), 并将其余所有的代码复制到TimestampUtil.h的最后面, 实现header-only, 以方便在你的程序中更加快速的使用这个工具类

#include "TimestampUtil.h"  // 你可以将该行删除, 然后把本文其余的所有代码全部复制到TimestampUtil.h(头文件)的最后面. 之后就可以直接声明TimestampUtil.h来使用这个工具类

int
TimestampUtil::checkBitLength(time_t timestamp)
{
    int bit=0;
	if(timestamp == 0) return 1;

	while(timestamp)
	{
		bit++;
		timestamp/=10;
	}
	return bit;
}

system_clock::time_point
TimestampUtil::_getNow()
{
    return system_clock::now();
}

int
TimestampUtil::getTimeLevel(const time_t &timestamp)
{
    int timestampLen = checkBitLength(timestamp);

    int time_level = -1;
    switch (timestampLen)
    {
    case 10:
        time_level = 0;
        break;

    case 13:
        time_level = 1;
        break;

    case 16:
        time_level = 2;
        break;

    case 19:
        time_level = 3;
        break;

    default:
        break;
    }

    return time_level;
}


void TimestampUtil::setFormatData(int time_level, const string &formatType, struct __timeData &timedata)
{
    time_t timestamp = timedata.timestamp;

    int ms;
    int cs;
    int ns;

    time_t timestamp_sec;
    stringstream formatTime;
    switch (time_level)
    {

    case 0:
        timestamp_sec = timestamp;

        break;

    case 1:
        timestamp_sec = timestamp / 1000;

        timedata.ms = timestamp % 1000;

        break;

    case 2:
        timestamp_sec = timestamp / 1000 / 1000;

        timedata.cs = timestamp % 1000;
        timedata.ms = timestamp / 1000 % 1000;

        break;

    case 3:
        timestamp_sec = timestamp / 1000 / 1000 / 1000;    
        
        timedata.ns = timestamp % 1000;
        timedata.cs = timestamp / 1000 % 1000;
        timedata.ms = timestamp / 1000 / 1000 % 1000;

        break;

    default:

        return;
    }
    tm timeInfo;

    #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
        localtime_s(&timeInfo, &timestamp_sec);
    #elif defined(linux) || defined(__linux) || defined(__linux__)
        localtime_r(&timestamp_sec, &timeInfo);
    #elif defined(unix) || defined(__unix) || defined(__unix__)
        localtime_r(&timestamp_sec, &timeInfo);
    #endif

    formatTime << put_time(&timeInfo, formatType.c_str());
    timedata.formatDatatime = formatTime.str();

}

string
TimestampUtil::buildFormatString(struct __timeData &timedata)
{
    stringstream formatString;
    formatString << timedata.formatDatatime;

    if (timedata.ms == -1)
    {
        return formatString.str();
    }    
    formatString << " " << setw(3) << setfill('0') << timedata.ms;


    if (timedata.cs == -1)
    {
        return formatString.str();
    }
    formatString << "." << setw(3) << setfill('0') << timedata.cs;


    if (timedata.ns == -1)
    {
        return formatString.str();
    }
    formatString << "." << setw(3) << setfill('0') << timedata.ns;
    return formatString.str();
}

time_t
TimestampUtil::getCurrentTimestamp(int time_level)
{

    auto timeinfo = _getNow().time_since_epoch();
    time_t current_time_stamp;
    switch (time_level)
    {

    case 0:
        current_time_stamp = duration_cast<seconds>(timeinfo).count();
        break;
    case 1:
        current_time_stamp = duration_cast<milliseconds>(timeinfo).count();
        break;
    case 2:
        current_time_stamp = duration_cast<microseconds>(timeinfo).count();
        break;
    case 3:
        current_time_stamp = duration_cast<nanoseconds>(timeinfo).count();
        break;
    default:
        current_time_stamp = -1;
        break;
    }
    return current_time_stamp;
}

string
TimestampUtil::getCurrentFormatDatetime(int time_level)
{
    struct __timeData timedata;
    timedata.timestamp = getCurrentTimestamp(time_level);
    setFormatData(time_level, "%Y-%m-%d %H:%M:%S", timedata);
    return buildFormatString(timedata);
}

string
TimestampUtil::getCurrentFormatDate()
{
    struct __timeData timedata;
    timedata.timestamp = getCurrentTimestamp(0);
    setFormatData(0, "%Y-%m-%d", timedata);

    return buildFormatString(timedata);
}

string
TimestampUtil::getCurrentFormatTime()
{
    struct __timeData timedata;
    timedata.timestamp = getCurrentTimestamp(0);
    
    setFormatData(0, "%H:%M:%S", timedata);
    
    return buildFormatString(timedata);
}

string 
TimestampUtil::getFormatData(const time_t timestamp)
{
    struct __timeData timedata;
    int time_level = getTimeLevel(timestamp);
    timedata.timestamp = timestamp;
    time_level = 0;
    time_level = timestampGabFix(time_level, timedata);
    setFormatData(time_level, "%Y-%m-%d", timedata);

    return buildFormatString(timedata);
}

string 
TimestampUtil::getFormatTime(const time_t timestamp)
{
    struct __timeData timedata;
    int time_level = getTimeLevel(timestamp);
    timedata.timestamp = timestamp;
    time_level = 0;
    time_level = timestampGabFix(time_level, timedata);
    setFormatData(time_level, "%H:%M:%S", timedata);
    
    return buildFormatString(timedata);
}

string 
TimestampUtil::getFormatDataTime(time_t timestamp, int time_level)
{

    if (time_level > 3 || time_level < 0)
    {
        return nullptr;
    }

    struct __timeData timedata;
    timedata.timestamp = timestamp;

    // timestamp和time_level的精度拟合修复函数
    time_level = timestampGabFix(time_level, timedata);

    setFormatData(time_level, "%Y-%m-%d %H:%M:%S", timedata);

    return buildFormatString(timedata);
}

int 
TimestampUtil::timestampGabFix(int input_level, __timeData &timedata)
{
    
    int time_level_gab;         // 拟合值
    
    time_t timestamp = timedata.timestamp;
    
    
    int timestamp_time_level = getTimeLevel(timestamp);


    if (timestamp_time_level < 0)
    {
        return -1;
    }
    int time_level = -1;

    // 时间戳精度大于输入精度, 时间戳根据拟合值删减
    if (timestamp_time_level > input_level)
    {
        time_level_gab = timestamp_time_level  - input_level;
        timestamp = timestamp / pow(1000, time_level_gab);      // 时间戳截取
        time_level = input_level;                               // 使用输入的精度
    } 
    // 时间戳精度小于输入精度, 以时间戳精度为准
    else 
    {
        time_level = timestamp_time_level;
    }

    timedata.timestamp = timestamp;

    return time_level;
}

测试代码/使用示例


        测试代码中调用了工具类中public权限所有的函数, 并已经通过注释和打印字符串的方式给出了详细的说明. 你可以根据测试代码中的函数调用方式, 来使用这个工具类.

#include "TimestampUtil.h"


int main()
{
    /* 当前时间时间戳获取 */
    cout << "获取当前时间的10位时间戳(精度0, 秒级) : " << TimestampUtil::getCurrentTimestamp(0) << endl;
    cout << "获取当前时间的13位时间戳(精度1, 毫秒级): " << TimestampUtil::getCurrentTimestamp(1) << endl;     // 也可以写为 TimestampUtil::getCurrentTimestamp();
    cout << "获取当前时间的16位时间戳(精度2, 微秒级): " << TimestampUtil::getCurrentTimestamp(2) << endl;
    cout << "获取当前时间的19位时间戳(精度3, 纳秒级): " << TimestampUtil::getCurrentTimestamp(3) << endl << endl;




    /* 当前格式化获取 */
    cout << "获取当前时间的格式化字符串(精度0, 秒级) : " << TimestampUtil::getCurrentFormatDatetime(0) << endl;    // TimestampUtil::getCurrentFormatDatetime();
    cout << "获取当前时间的格式化字符串(精度1, 毫秒级): " << TimestampUtil::getCurrentFormatDatetime(1) << endl;
    cout << "获取当前时间的格式化字符串(精度2, 微秒级): " << TimestampUtil::getCurrentFormatDatetime(2) << endl;
    cout << "获取当前时间的格式化字符串(精度3, 纳秒级): " << TimestampUtil::getCurrentFormatDatetime(3) << endl << endl;
   


    time_t testTimestamp_10 = 1680798753;              // 测试用的10位时间戳, 精确到秒
    time_t testTimestamp_13 = 1680798753327;           // 测试用的13位时间戳, 精确到毫秒
    time_t testTimestamp_16 = 1680798753327366;        // 测试用的16位时间戳, 精确到微妙
    time_t testTimestamp_19 = 1680798753327366400;     // 测试用的19位时间戳, 精确到纳秒

    // 将10位时间戳转为格式化字符串
    cout << "10位时间戳转格式化字符串: " << TimestampUtil::getFormatDataTime(testTimestamp_10) << endl << endl;



    // 将13位时间戳转为格式化字符串
    cout << "13位时间戳转格式化字符串(精度0, 保留到秒级): " << TimestampUtil::getFormatDataTime(testTimestamp_13) << endl;
    cout << "13位时间戳转格式化字符串(精度1, 保留到毫秒): " << TimestampUtil::getFormatDataTime(testTimestamp_13, 1) << endl << endl;


    /* 
        时间戳转为格式化字符串时, 如果期望精度高于时间戳实际的精度,  结果以时间戳实际的精度为准. 如下面的示例: 
            给入的时间戳位数为13(对应精度1, 毫秒级), 期望的精度为3(纳秒级), 结果以时间戳实际的精度为准
    */
    cout << "时间戳转化时格式化字符串时, 如果期望精度高于时间戳实际的精度: 例如期望纳妙, 给入的时间戳为毫秒级, 结果以时间戳实际的精度为准): " << TimestampUtil::getFormatDataTime(testTimestamp_13, 3) << endl << endl;
    


    // 将16位时间戳转为格式化字符串
    cout << "16位时间戳转格式化字符串(精度0, 保留到秒级): " << TimestampUtil::getFormatDataTime(testTimestamp_16) << endl;
    cout << "16位时间戳转格式化字符串(精度1, 保留到毫秒): " << TimestampUtil::getFormatDataTime(testTimestamp_16, 1) << endl;
    cout << "16位时间戳转格式化字符串(精度2, 保留到微妙): " << TimestampUtil::getFormatDataTime(testTimestamp_16, 2) << endl << endl;


    // 将19位时间戳转为格式化字符串
    cout << "19位时间戳转格式化字符串(精度0, 保留到秒级): " << TimestampUtil::getFormatDataTime(testTimestamp_19) << endl;
    cout << "19位时间戳转格式化字符串(精度1, 保留到毫秒): " << TimestampUtil::getFormatDataTime(testTimestamp_19, 1) << endl;
    cout << "19位时间戳转格式化字符串(精度2, 保留到微妙): " << TimestampUtil::getFormatDataTime(testTimestamp_19, 2) << endl;
    cout << "19位时间戳转格式化字符串(精度3, 保留到纳秒): " << TimestampUtil::getFormatDataTime(testTimestamp_19, 3) << endl << endl;
    


    /* 当前格式化年月日获取(只获取年月日) */
    cout << "获取当前的格式化年月日(只获取年月日): " << TimestampUtil::getCurrentFormatDate() << endl;
    /* 当前格式化时分秒获取(只获取时分秒) */
    cout << "获取当前的格式化时分秒(只获取时分秒): " << TimestampUtil::getCurrentFormatTime() << endl << endl;

   
    cout << "将时间戳转化为格式化年月日(只保留年月日, 可以是10, 13, 16, 19位时间戳): " << TimestampUtil::getFormatData(testTimestamp_19) << endl;
    cout << "将时间戳转化为格式化时分秒(只保留时分秒, 可以是10, 13, 16, 19位时间戳): " << TimestampUtil::getFormatTime(testTimestamp_19) << endl;
	return 0;
}

测试结果


window和linux都跑了一下, 确认无问题, 下图为linux中的运行结果
基于c++11的时间戳工具类, (TimestampUtil) 支持10位时间戳, 13位时间戳, 16位时间戳, 和19位时间戳的获取与转为格式化时间字符串_第1张图片

你可能感兴趣的:(c++常用工具类,linux,windows,c++)