c++ 是否有任何日期/时间函数可以处理明天的日期,包括结转到下个月?

pwuypxnk  于 2023-04-01  发布在  其他
关注(0)|答案(4)|浏览(117)

我有一个函数,需要计算昨天的,今天的和明天的日期,我用localtime来得到今天的日期,为了得到明天的日期,我给tm_mday加1,问题是如果当前日期是3/31如果我在tm_mday上加1,它将变成3/32. C++中有日期包吗处理结转到下个月,还是我需要编写逻辑来完成?

string get_local_date(const string &s) {
    time_t rawtime;
    struct tm * timeinfo;
    time (&rawtime);
    timeinfo = localtime(&rawtime);

    if (s == "tomorrow") {
        timeinfo->tm_mday += 3; // day becomes 3/32
    }
    if (s == "yesterday") {
        timeinfo->tm_mday -= 1;
    }

    char buffer[80];
    strftime(buffer,80,"%04Y-%m-%d",timeinfo);
    string str(buffer);

    return str; 
}
lyr7nygr

lyr7nygr1#

在 * 大多数 * 系统上,(std::)time_t表示为自POSIX纪元(1970年1月1日00:00 UTC)以来经过的整数秒。由于1天中有86400秒(不包括闰秒),您可以简单地将明天的86400加上,并将昨天的86400减去,例如:

#include <string>
#include <ctime>

std::string get_local_date(const std::string &s) {

    std::time_t rawtime = std::time(nullptr);

    if (s == "tomorrow") {
        rawtime += 86400;
    }
    else if (s == "yesterday") {
        rawtime -= 86400;
    }

    char buffer[80] = {};
    std::strftime(buffer, 80, "%04Y-%m-%d", std::localtime(&rawtime));

    return buffer;
}

然而,你真的应该使用原生的<chrono>库,它是在C++11中引入的,来处理这类东西,例如:

#include <string>
#include <chrono>
#include <ctime>

std::string get_local_date(const std::string &s) {

    using namespace std::literals::chrono_literals;

    auto clock = std::chrono::system_clock::now();

    if (s == "tomorrow") {
        clock += 24h; // clock += std::chrono::hours(24);
        /* alternatively, in C++20 and later:
        clock += std::chrono::days(1);
        */
    }
    else if (s == "yesterday") {
        clock -= 24h; // clock -= std::chrono::hours(24);
        /* alternatively, in C++20 and later:
        clock -= std::chrono::days(1);
        */
    }

    auto rawtime = std::chrono::system_clock::to_time_t(clock);

    char buffer[80] = {};
    std::strftime(buffer, 80, "%04Y-%m-%d", std::localtime(&rawtime));

    /* alternatively, in C++20 and later:
    return std::format("{:%F}", clock);
    */
}
of1yzvn4

of1yzvn42#

C++中有一个日期包叫做chrono,你可以用它来处理日期和时间的计算。

#include <iostream>
#include <chrono>
#include <ctime>

using namespace std;

string get_local_date(const string& s) {
    auto now = chrono::system_clock::now();
    time_t rawtime = chrono::system_clock::to_time_t(now);
    struct tm* timeinfo = localtime(&rawtime);

    if (s == "tomorrow") {
        timeinfo->tm_mday += 1;
    } else if (s == "yesterday") {
        timeinfo->tm_mday -= 1;
    }

    auto modified_time = chrono::system_clock::from_time_t(mktime(timeinfo));
    auto modified_time_t = chrono::system_clock::to_time_t(modified_time);

    char buffer[80];
    strftime(buffer, 80, "%F", localtime(&modified_time_t));
    string str(buffer);

    return str;
}

int main() {
    cout << "Today: " << get_local_date("") << endl;
    cout << "Yesterday: " << get_local_date("yesterday") << endl;
    cout << "Tomorrow: " << get_local_date("tomorrow") << endl;

    return 0;
}
dddzy1tm

dddzy1tm3#

下面是一个C++20版本,它获取今天的本地日期,而不是UTC日期,根据您的本地时区和程序运行的时间,UTC日期可以相差1天:

#include <chrono>
#include <format>
#include <iostream>
#include <string>

std::string
get_local_date(std::string const& s)
{
    using namespace std;
    using namespace chrono;

    zoned_time zt_now{current_zone(), system_clock::now()};
    auto date = floor<days>(zt_now.get_local_time());
    if (s == "tomorrow")
        ++date;
    else if (s == "yesterday")
        --date;
    else if (s != "today")
        throw "oops";
    return format("{:%F}", date);
}

int
main()
{
    std::cout << get_local_date("yesterday") << '\n';
    std::cout << get_local_date("today") << '\n';
    std::cout << get_local_date("tomorrow") << '\n';
}

这可以很容易地自定义到另一个时区,通过更改一行,可能会输出稍微不同的结果。例如:

zoned_time zt_now{"Asia/Tokyo", system_clock::now()};

演示。

f2uvfpb9

f2uvfpb94#

即使使用普通的老C,这实际上也是一件非常容易管理的事情,因为mktime规范化了struct tm中包含的日期。例如:

#include <time.h>
#include <iostream>
#include <iomanip>

int main() { 
    time_t tnow = time(nullptr);    
    tm now = *localtime(&tnow);

    std::cout << std::put_time(&now, "%F\n"); // today
    now.tm_mday += 3;   // currently 30 March, so this will be next month
    mktime(&now);
    std::cout << std::put_time(&now, "%F\n");

    now.tm_mday -= 7;   // as I write this, tm_mday is now negative
    mktime(&now);
    std::cout << std::put_time(&now, "%F\n");

    now.tm_mday += 30;  // let's try a month ahead
    mktime(&now);
    std::cout << std::put_time(&now, "%F\n");

    now.tm_mday += 300; // How about nearly a year ahead?
    mktime(&now);
    std::cout << std::put_time(&now, "%F\n");
}

结果:

2023-03-30
2023-04-02
2023-03-26
2023-04-25
2024-02-19

所以,是的,所有这些工作都很好。
不要误会我的意思,我当然推荐使用C++ 20日期库或霍华德Hinnant的日期库(这几乎是标准化到C++20中的东西)如果你可以的话--这是一个很棒的库,工作得很好。(不管是什么原因)这是不容易得到的,你不需要自己写所有的东西。你需要的日期操作几乎一样简单,即使只使用C库。

相关问题