如何获取特定时区的日期

C++ - How to get date in specific time zone

本文关键字:定时区 日期 获取 何获取      更新时间:2023-10-16

在c++中获取当前日期/时间已经已知并得到了答案。

获取特定时区的日期/时间。意思是,不同时区的不同用户,在同一时间运行我的应用程序,将得到相同的结果。

注意

  1. 为简单起见,假设指定的时区为东部时区。
  2. 应用程序只能在windows环境下运行。
  3. 本机解决方案优先(非boost等)

我读过使用c++获取不同时区的当前时间。似乎没有一个答案能解决我的问题。也许我不完全理解SystemTimeToTzSpecificLocalTime的用法。如果我用一些参数调用GetTimeZoneInformation来指定所需的时区,这将使我更进一步。

如果您使用的是windows环境,您可以使用SystemTimeToTzSpecificLocalTime函数。它将UTC时间转换为指定时区的本地时间。

这是一个有趣的练习。我唯一不明白的部分是如何在std::tm*上设置时区。它是某种全局变量吗?

#include <ctime>
#include <iomanip>
#include <iostream>
inline const int EST_diff(const bool is_DST)
{
    if (is_DST < 0)
        std::cout << "Erorr! No DST Information available!" << std::endl;    
    if (is_DST)
        return 4;
    else
        return 5;
}
inline const bool try_rollback(int& time)
{
    if (time > 1)
    {
        time -= 1;
        return true;
    }
    else
        return false;
}
inline int leapyear(const std::tm *const time)
{
    return time->tm_year % 4 == 0 ? 1 : 0;
}
inline int back_one(int& time, const int increment)
{
    return time = time > 1 ? time - 1 : time + increment - 1;
}
inline int advance_hours(int& time, const int difference)
{
    return time += 24 - difference;
}
inline int days_in_month(const int month, const bool leapyear)
{
    switch(month)
    {
    case 0: //january
        return 31;
    case 1: //february
        return leapyear ? 29 : 28;
    case 2: //march
        return 31;
    case 3: //april
        return 30;
    case 4: //may
        return 31;
    case 5: //june
        return 30;
    case 6: //july
        return 31;
    case 7: //august
        return 31;
    case 8: //september
        return 30;
    case 9: //october
        return 31;
    case 10:    //november
        return 30;
    case 11:    //december
        return 31;
    default:
        std::cout << "Input error in days_in_month!" << std::endl;
        break;
    }
    return -1;
}
inline std::tm* rollback_week(std::tm *const time)
{
    back_one(time->tm_wday, 7);
    advance_hours(time->tm_hour, EST_diff(time->tm_isdst));
    return time;
}
inline std::tm* rollback_month(std::tm *const time)
{
    back_one(time->tm_mon, 12);
    back_one(time->tm_mday, days_in_month(time->tm_mon, leapyear(time)));
    return rollback_week(time);
}
inline std::tm* rollback_year(std::tm *const time)
{
    time->tm_year -= 1;
    time->tm_yday += 364 + leapyear(time);
    return rollback_month(time);
}
inline std::tm* UTC_to_EST(std::tm *const time)
{
    if (time->tm_hour > EST_diff(time->tm_isdst))
        time->tm_hour -= EST_diff(time->tm_isdst);
    else
    {
        if (!try_rollback(time->tm_yday))
            rollback_year(time);
        else if(!try_rollback(time->tm_mday))
            rollback_month(time);
        else if(!try_rollback(time->tm_wday))
            rollback_week(time);
    }
    return time;
}
int main()
{
    std::time_t t = std::time(NULL);
    std::tm* time(std::gmtime(&t));
    std::cout << "UTC: " << std::put_time(time, "%c %Z") << 'n';
    std::cout << "EST: " << std::put_time(UTC_to_EST(time), "%c %Z") << 'n';
    std::cout << "Daylight Savings Time is " << (std::gmtime(&t)->tm_isdst < 0 ? "invalid" : (std::gmtime(&t)->tm_isdst > 0 ? "active" : "inactive")) << std::endl;
}

生活在Coliru

假设您只谈论Windows,并且您只希望不同时区的用户在同时请求时间时获得相同的结果,而不关心具体的时区,答案很简单:GetSystemTime()

它给你UTC时间,不管时区。