代码之家  ›  专栏  ›  技术社区  ›  Gabriel Schreiber

距离UTC-Linux上的本地时间

  •  4
  • Gabriel Schreiber  · 技术社区  · 15 年前

    我在C++中编写了一个Linux(Ubuntu和Debian Lenny)应用程序。

    现在,我需要知道过去某一天的UTC和当前设置的系统时间之间的距离/偏移量。由于我需要转换记录的数据,我需要根据过去的某个日期(可能与当前日期的DST设置不同)计算距离。

    有人知道怎么做吗?

    编辑:阅读第一个答案我觉得我被误解了:我不想比较日期/时间。我有日期/时间值,希望将其从UTC转换为本地时间。

    3 回复  |  直到 9 年前
        1
  •  3
  •   Artyom    15 年前

    准备TM结构,日期:

    struct tm date;
    memset(&date,0,sizeof(date));
    date.tm_year = year - 1900;
    date.tm_mon = month - 1;
    date.tm_mday = day;
    date.tm_hour = hour;
    date.tm_min = minute;
    date.tm_sec = second;
    date.tm_isdst = -1; // VERY IMPORTANT
    
    mktime(&date); /// fill rest of fields
    

    然后看看 tm_gmtoff

    printf("%d\n",date.tm_gmtoff);
    

    这是与UTC的距离。

    现在这是Linux和BSD特有的,它不能在其他Stystym上工作,而且这可以工作 关于DST。

    阅读手册获取更多信息。灌装 struct tm 具有正确的值

    P.S.:从UTC转换为本地和本地?

    time_t posix_time = timegm(&UTC_Filled_struct_tm); // Linux specific line
    localtime_r(&posix_time,&local_Filled_struct_tm);
    

    本地到UTC

    time_t posix_time = mktime(&local_Filled_struct_tm);
    gmtime_r(&posix_time,&UTC_Filled_struct_tm);
    
        2
  •  2
  •   Sergey Kurenkov    15 年前

    我认为使用boost.datetime或 ICU .

    至于boost.datetime,tt可能如下所示:

    1)准备一个包含时区信息的数据库 Boost.Datetime 创建时区。时区很重要,因为它们包含有关DST的信息

    tz_database tz_db;
    tz_db.load_from_file("./date_time_zonespec.csv");
    time_zone_ptr nyc = tz_db.time_zone_from_region("America/New_York"); // or other timezone
    


    或者创建一个这样的时区。

    std::string kaliningrad_string = "EET+02:00:00EEST+01:00:00,M3.5.0/02:00:00,M10.5.0/03:00:00";
    boost::local_time::time_zone_ptr kaliningrad_tzone_posix(new boost::local_time::posix_time_zone(kaliningrad_string));
    std::string vladivostok_string = "VLAT+10:00:00VLAST+01:00:00,M3.5.0/02:00:00,M10.5.0/03:00:00";
    boost::local_time::time_zone_ptr vladivostok_tzone_posix(new boost::local_time::posix_time_zone(vladivostok_string));
    

    使用时区的字符串规范创建时区看起来更困难,但是如果在date_time_zonespec.csv中找不到特定时区,则可以使用它。 例如,Samara在2010年3月之前使用的是UTC+4,现在使用的是UTC+3。 date_time_zonespec.csv 没有更改的历史记录,因此在这种情况下,有必要根据字符串规范创建时区。不过,我记得重症监护室似乎有类似历史的时区 ICU TimeZone Classes :

    时区数据经常在 对周边政府的反应 世界改变了他们的地方规则 它们适用的区域。重症监护病房 每个时区的数据都会更新 释放,以及最简单的停留方式 最新版本可以升级到 最新的ICU版本,也包括 提供错误修复、代码改进 以及其他功能。


    3)例如,在本地安排您需要的时间

    local_date_time tmp(boost::gregorian::date(2010, 3, 28), boost::posix_time::time_duration(1,59,0),nyc, boost::local_time::local_date_time::EXCEPTION_ON_ERROR);
    

    4)然后用函数计算差异 utc_time local_time
    该页面上有一个示例:

    ptime pt(date(2004,Nov,5), 
             hours(10));
    time_zone_ptr zone(new posix_time_zone("MST-07"));
    local_date_time az(pt, zone);
    az.utc_time(); // 10am 2004-Nov-5
    az.local_time(); // 3am 2004-Nov-5
    


    5)另一个例子。当地时间相同,但UTC不同

    local_date_time tmp(boost::gregorian::date(2010, 3, 28), boost::posix_time::time_duration(1,59,0),kaliningrad_tzone_posix, boost::local_time::local_date_time::EXCEPTION_ON_ERROR);
    std::cout << "As is: " << tmp << ", UTC: "  << tmp.utc_time() << std::endl;
    
    local_date_time tmp(boost::gregorian::date(2010, 3, 28), boost::posix_time::time_duration(1,59,0),vladivostok_tzone_posix, boost::local_time::local_date_time::EXCEPTION_ON_ERROR);
    std::cout << "As is: " << tmp << ", UTC: "  << tmp.utc_time() << std::endl;
    
        3
  •  0
  •   Flexo - Save the data dump sunny moon    15 年前

    确保所有时间都转换为UTC(请参见 mktime() 例如)。然后你可以使用 difftime() 或者TimeVal_从同一链接中减去示例函数,这取决于存储时间的结构。