从 struct tm 转换为 std::time_t 并转换回日期将被更改

wan*_*gzj 0 c++ time

我尝试使用以下示例代码从 struct tm 转换为 std::time_t:

void test_time_t() {
    tm time;
    time.tm_year = 2004-1900;
    time.tm_mon = 11;
    time.tm_mday = 5;
    time.tm_hour = 12;
    time.tm_min = 2;
    char buff[25];
    strftime(buff, 20, "%Y %b %d %H:%M",&time);
    printf("%s\n",buff);
    auto t = std::mktime(&time);
    struct tm *tmp = localtime(&t);
    strftime(buff, 20, "%Y %b %d %H:%M",tmp);
    printf("%s\n",buff);
}

Run Code Online (Sandbox Code Playgroud)

这将输出:

2004 Dec 05 12:02
2005 Jun 16 22:41
Run Code Online (Sandbox Code Playgroud)

日期已更改,有人能告诉我我在这里做错了什么吗?我认为时区不会造成如此不同的日期

Ted*_*gmo 5

您需要初始化您的time

tm time{}; // zero-initialized
Run Code Online (Sandbox Code Playgroud)

我只是忘了那tm是一个C结构体。

那很常见。但是std::tm,您可以在代码中继承并使用您自己的类型。

struct tm_ext : std::tm {
    tm_ext() : std::tm{} {}; // zero initialize on default construction
};
Run Code Online (Sandbox Code Playgroud)

您现在可以使用tm_ext而不会错过初始化:

tm_ext time; // now fine
Run Code Online (Sandbox Code Playgroud)

当您使用它时,您甚至可以为其添加一些其他便利功能。

struct tm_ext : std::tm {

    tm_ext() : std::tm{} {}; // zero initialize on default construction

    explicit tm_ext(int year, int mon = 1, int mday = 1, int hour = 0,
           int min = 0, int sec = 0, int isdst = 0) :
        tm_ext() // delegate to default constructor
    {
        tm_year = year - 1900;
        tm_mon = mon - 1;
        tm_mday = mday;
        tm_hour = hour;
        tm_min = min;
        tm_sec = sec;
        // A negative value of tm_isdst causes mktime to attempt to determine if
        // Daylight Saving Time was in effect.
        tm_isdst = isdst;

        errno = 0;
        if(std::mktime(this) == -1 && errno != 0) {
            throw std::runtime_error("mktime failed");
        }
    }

    tm_ext(const std::tm& t) : std::tm(t) {} // conversion ctor

    operator std::time_t () const { // implicit conversion to time_t
        tm_ext copy(*this);
        errno = 0;
        return std::mktime(&copy);
    }

    // implicit conversion to a pointer - perhaps an exaggeration
    operator const tm_ext* () const { return this; }

    bool set_localtime(const std::time_t& t) {
        std::tm* tmp = std::localtime(&t);
        if(not tmp) return false;
        *this = *tmp;
        return true;
    }

    bool set_utc(const std::time_t& t) {
        std::tm* tmp = std::gmtime(&t);
        if(not tmp) return false;
        *this = *tmp;
        return true;
    }
};
Run Code Online (Sandbox Code Playgroud)

并使用它:

void test_time_t() {
    tm_ext time(2004, 12, 5, 12, 2); // use real world values
    
    char buff[25];
    // implicit conversion to a   const tm_ext*  below:
    strftime(buff, 20, "%Y %b %d %H:%M", time);
    printf("%s\n",buff);
    
    std::time_t t = time; // implicit conversion from tm_ext to time_t

    tm_ext tmp;
    if(tmp.set_localtime(t)) std::cout << "successfully set localtime\n";

    // implicit conversion to a   const tm_ext*  below:
    strftime(buff, 20, "%Y %b %d %H:%M", tmp);

    printf("%s\n",buff);
}
Run Code Online (Sandbox Code Playgroud)

在对此进行过度之前,人们可能想看看 Howard Hinnant 的date.h