将时区的时间转换为Excel格式时间?

时间:2018-06-08 18:56:07

标签: c++ excel datetime epoch

我需要能够将Epoch时间转换为Excel时间。 为什么选择Excel,因为使用数字excel时间比在显示格式上进行任何解析更快。

2018-06-08 12:46:58 CDT与UTC 1528480019的当前时间应为 0.5326157 。 但转换为New_York时间或2018-06-08 13:46:58 EDT将给出 0.574282367 。 我只需要将时间字段转换为Excel样式。

这是我不完整的代码:

double GetTime(Datetime currtime, std::string tz = "TZ=America/New_York")
{
  std::time_t t = currtime;
  //tzset(tz);
  std::tm tm = *std::localtime(&t);
  return ((tm.tm_hour * 3600 + (tm.tm_min) * 60.0 + tm.tm_sec) / 86400.0);
}

代码有效,但仅适用于当地时间“美国/芝加哥”。 我无法将时区设置为我可能需要的时区。 此外,tm似乎仅限于秒,但我也需要处理毫秒和微秒。

此外,我需要快速,并且当前实现将时间解析为单独的字段,然后我将其组合到我需要的内容中,这似乎做了很多额外的工作。

1 个答案:

答案 0 :(得分:0)

使用Howard Hinnant's free, open-source date/time/timezone library可以轻松解决此问题,这非常有效。该库也在namespace std::chrono下的当前C ++ 20工作草案中。因此,在将来,将代码移植到仅使用std :: lib应该像更改一些名称空间一样简单。

double
GetTime(std::chrono::system_clock::time_point currtime,
        date::time_zone const* tz = date::current_zone())
{
    using namespace date;
    using namespace std::chrono;
    zoned_time<system_clock::duration> zt{tz, currtime};
    auto lt = zt.get_local_time();
    auto ld = floor<days>(lt);
    using ExcelTime = duration<double, days::period>;
    ExcelTime tod = lt - ld;
    return tod.count();
}

取代Datetime而不是std::chrono::system_clock::time_point,而不是std::stringdate::time_zone const*

在三大平台(llvm / gcc / MSVS)上,最粗糙的system_clock::time_point是微秒,符合您的精确目标。

第一步是创建一个zoned_time,它是time_pointtime_zone的配对。从这一个可以获得local_time

floor<days>会将time_point的精度截断为days。如果从精细度time_point中减去日精度time_point,则获得当地时间。

如果您将此本地时间存储在chrono::duration代表double且期限为1天的情况下,那么您将获得Excel时间格式

这可以像:

一样使用
int
main()
{
    using namespace date;
    using namespace std::chrono;
    std::cout << std::fixed << std::setprecision(9);
    std::cout << GetTime(sys_seconds{1528480019s}, locate_zone("America/Chicago")) << '\n';
    zoned_time<system_clock::duration> zt{"America/New_York",
                                          local_days{2018_y/6/8} + 13h + 46min + 58s};
    std::cout << GetTime(zt.get_sys_time(), zt.get_time_zone()) << '\n';
}

输出:

0.532627315
0.574282407

上面,我努力尽可能接近您现有的API。但是,如果您采用此库,则可以通过采用“更原生”的API使其更简单,更高效:

std::chrono::duration<double, date::days::period>
GetTime(const date::zoned_time<std::chrono::system_clock::duration>& zt)
{
    using namespace date;
    auto lt = zt.get_local_time();
    return lt - floor<days>(lt);
}

现在GetTime只接受zoned_time<system_clock::duration>类型的单个参数,并返回duration<double, days::period>GetTime要做的就是将本地时间截断为天精度,减去时间以获取时间。

main中的演示也得到了简化:

std::cout << GetTime({"America/Chicago", sys_seconds{1528480019s}}).count() << '\n';
std::cout << GetTime({"America/New_York",
                      local_days{2018_y/6/8} + 13h + 46min + 58s}).count() << '\n';

并提供与以前相同的输出。

相关问题