c++重载localtime函数

本文原创,转载请注明:https://www.cnblogs.com/tkblack/p/11274022.html

最近在写一个EOS的合约,我想将时间戳转换成日期,并将日期以整型存储,本来想采用localtime()或者gmtime()函数来直接转换,但是很遗憾,eosio.cdt好像并不支持该函数,虽然库当中具有该函数,但是实际编译还是会报错。然后我去github上面查看了eosio.cdt项目的相关issue,有人提出了这个问题,确实是编译的时候会报错;有开发者建议定义time_point或者time_point_sec类型,并将其存储在多索引表(multi_index)中,这样在展示的时候会以日期的格式打印。以上方法其实不是很契合我的需求,于是决定重载该函数,去网上看了看,发现有不少实现,但是很多人对于“百年不闰,四百年再闰”这点没有注意,他们的代码在2100年之前也是没有问题的(因为2100年是平年)。

好了,我们直接贴上代码:

/***
 *重载localtime()
 *时间戳转换成日期(北京时间,东八区)
***/
int localtime(const time_t stamp, struct tm &ret_tm, int time_zone = 8) {
    static const int days_every_month[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };    //平年各月份天数
    static const bool four_year[4] = { false, false, true, false };        //1970开始,判断是否为闰年,4年为周期
    static const bool four_hundred_year[4] = { true, false, false, false };    //百年不闰,四百年再闰

    //int time_zone = 8;        //多8小时
    time_t timestamp = stamp + time_zone * 3600;

    ret_tm.tm_isdst = 0;        //夏时令,这个东西没用过,默认是0,不过以防万一,还是重置下

    //计算秒
    ret_tm.tm_sec = (int)(timestamp % 60);
    int tmp = (int)(timestamp / 60);

    //计算分
    ret_tm.tm_min = tmp % 60;
    tmp = tmp / 60;

    //计算时
    ret_tm.tm_hour = tmp % 24;
    tmp = tmp / 24;

    /***
    //1970.1.1到2000.1.1,一共历时10957天
    //4年1461天,1461*24 = 35064小时
    //100年36524或36525天
    //400年146097天
    ***/
    int four_year_count = 0;            //四年计数
    int four_hundred_year_count = 0;    //四百年计数
    int left_days = 0;                    //剩余天数
    int leave_years = 0;                //过去年数

    if (tmp > 10957) {
        four_hundred_year_count = (tmp - 10957) / 146097;        //过去多少个400年,相对于2000.1.1而言
        left_days = (tmp - 10957) % 146097;
        int i = 0;            //此处i表示过了多少个百年,例如2100年1月1日,正好过100年,i == 1
        for (; i < 4; ++i) {
            int hundred_year_days = four_hundred_year[i] ? 36525 : 36524;
            if (left_days < hundred_year_days)        break;
            left_days -= hundred_year_days;
        }
        if (i >= 1 && left_days <= 58)    i--;            //当日期小于等于2月28日时,意味着这个百年并未多算一天,i--
        tmp += (four_hundred_year_count * 3 + i);        //将多算的天数补上
    }

    four_year_count = tmp / 1461;        //过去多少个4年
    left_days = tmp % 1461;
    int i = 0;                //i表示以4年为周期计数完之后,还过了几年
    for (; i < 4; ++i) {
        int year_days = four_year[i] ? 366 : 365;
        if (left_days < year_days)        break;
        left_days -= year_days;
    }
    //
    leave_years = (four_year_count << 2) + 1970 + i;
    ret_tm.tm_year = leave_years;

    int j = 0;
    for (; j < 12; ++j) {
        int month_days = days_every_month[j];
        if (i == 2 && j == 1) {
            month_days++;
        }

        if (left_days < month_days) {
            break;
        }
        left_days -= month_days;
    }
    //
    ret_tm.tm_mon = j + 1;
    //
    ret_tm.tm_mday = left_days + 1;

    cout << ret_tm.tm_year << "."
        << ret_tm.tm_mon << "."
        << ret_tm.tm_mday << " "
        << ret_tm.tm_hour << ":"
        << ret_tm.tm_min << ":"
        << ret_tm.tm_sec << endl;

    return 0;
}

 

以上代码,我仅进行简单测试,贴出来仅想和大家一起学习讨论,如果大家有什么更好的实现,或者代码逻辑有错误的地方,欢迎大家指正!

 

posted @ 2019-07-31 09:07  tkblack  阅读(470)  评论(0编辑  收藏  举报