4

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

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

有人知道怎么做吗?

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

4

3 回答 3

3

准备带有日期的 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 特定的,它不适用于其他系统,这适用于 DST。

阅读 man mktime 了解更多信息。并填写struct tm正确的值

PS:从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);
于 2010-11-12T16:38:33.340 回答
2

我认为您可能会从使用 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 似乎有具有这种历史ICU TimeZone Classes的时区:

时区数据经常随着世界各地政府改变当地规则及其适用地区而发生变化。每个版本都会更新 ICU 时区数据,保持最新的最简单方法可能是升级到最新的 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_timelocal_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;
于 2010-11-12T16:58:38.043 回答
0

确保所有时间都转换为 UTC(参见mktime()示例)。然后,您可以使用同一链接中的difftime()或 timeval_subtract 示例函数,具体取决于时间存储在什么结构中。

于 2010-11-12T16:26:33.257 回答