将time_t从当地时区转换为UTC [英] Convert time_t from localtime zone to UTC

查看:231
本文介绍了将time_t从当地时区转换为UTC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 time_t ,它表示自纪元以来的时间(以秒为单位).那几秒指的是当地时间.

I have a time_t that represents the time in seconds since epoch. Those seconds refer to the local time.

我想将它们转换为UTC.

I want to convert them to UTC.

有没有办法在C ++中做到这一点?

Is there a way to do this in C++?

推荐答案

我将展示两种方法:

  1. 使用C API.
  2. 使用基于< chrono> 之上的现代C ++ 11/14库.
  1. Using the C API.
  2. Using a modern C++11/14 library based on top of <chrono>.

就本演示而言,我假设本地时区中的当前秒数为1,470,003,841.我的当地时区是America/New_York,所以我得到的结果反映出我们当前的时间是-0400 UTC.

For the purposes of this demo, I'm assuming that the current number of seconds in the local time zone is 1,470,003,841. My local time zone is America/New_York, and so the results I get reflect that we are currently at -0400 UTC.

首先使用C API:

此API不是类型安全的,并且很容易出错.在编写此答案时,我犯了一些错误,但是由于我正在根据第二种技术检查答案,因此我能够快速发现这些错误.

This API is not type-safe and is very error prone. I made several mistakes just while coding up this answer, but I was able to quickly detect these mistakes because I was checking the answers against the 2nd technique.

#include <ctime>
#include <iostream>

int
main()
{
    std::time_t lt = 1470003841;
    auto local_field = *std::gmtime(&lt);
    local_field.tm_isdst = -1;
    auto utc = std::mktime(&local_field);
    std::cout << utc << '\n'; // 1470018241
    char buf[30];
    std::strftime(buf, sizeof(buf), "%F %T %Z\n", &local_field);
    std::cout << buf;
    auto utc_field = *std::gmtime(&utc);
    std::strftime(buf, sizeof(buf), "%F %T UTC\n", &utc_field);
    std::cout << buf;
}

首先,我初始化 time_t .现在没有C API可从本地 time_t 转换为UTC time_t .但是,您可以使用 gmtime 从UTC time_t 转换为UTC tm (从串行到字段类型,都在UTC中).因此,第一步是 lie gmtime ,告诉您您已经有了UTC time_t .然后,当您获得结果时,您就假装自己是本地的 tm 而不是UTC的 tm .到目前为止清楚吗?这是:

First I initialize the time_t. Now there is no C API to go from a local time_t to a UTC time_t. However you can use gmtime to go from a UTC time_t to a UTC tm (from serial to field type, all in UTC). So the first step is to lie to gmtime, telling it you've got a UTC time_t. And then when you get the result back you just pretend you've got a local tm instead of a UTC tm. Clear so far? This is:

auto local_field = *std::gmtime(&lt);

现在,在您开始之前(我个人第一次把这部分弄乱了),您必须扩充此字段类型以说您不知道当前是否是夏时制.这将导致后续步骤为您解决这一问题:

Now before you go (and I personally messed this part up the first time through) you have to augment this field type to say that you don't know if it is currently daylight saving or not. This causes subsequent steps to figure that out for you:

local_field.tm_isdst = -1;

接下来,您可以使用 make_time 将本地 tm 转换为UTC time_t :

Next you can use make_time to convert a local tm to a UTC time_t:

auto utc = std::mktime(&local_field);

您可以将其打印出来,对我来说是

You can print that out, and for me it is:

1470018241

,该值大于4h.该功能的其余部分是将这些时间以人类可读的格式打印出来,以便您可以调试这些东西.对我来说输出:

which is 4h greater. The rest of the function is to print out these times in human readable format so that you can debug this stuff. For me it output:

2016-07-31 22:24:01 EDT
2016-08-01 02:24:01 UTC

现代C ++ API:

std :: lib中没有设施可以执行此操作.但是,您可以为此使用免费的开放源代码(MIT许可证)库./p>

There exist no facilities in the std::lib to do this. However you can use this free, open source (MIT license) library for this.

#include "date/tz.h"
#include <iostream>

int
main()
{
    using namespace date;
    using namespace std::chrono_literals;
    auto zt = make_zoned(current_zone(), local_seconds{1470003841s});
    std::cout << zt.get_sys_time().time_since_epoch() << '\n'; // 1470018241s
    std::cout << zt << '\n';
    std::cout << zt.get_sys_time() << " UTC\n";
}

第一步是创建自该纪元以来的本地时间(以秒为单位):

The first step is to create the local time in terms of seconds since the epoch:

local_seconds{1470003841s}

接下来要做的是创建一个 zoned_time ,它是该本地时间和当前时区的配对:

The next thing to do is to create a zoned_time which is a pairing of this local time and the current time zone:

auto zt = make_zoned(current_zone(), local_seconds(1470003841s));

然后,您可以简单地打印出该配对的UTC秒数:

Then you can simply print out the UTC number of seconds of this pairing:

std::cout << zt.get_sys_time().time_since_epoch() << '\n';

此输出对我来说

1470018241s

(比输入晚4h).要像我在C API中一样打印出此结果:

(4h later than the input). To print out this result as I did in the C API:

std::cout << zt << '\n';
std::cout << zt.get_sys_time() << " UTC\n";

输出:

2016-07-31 22:24:01 EDT
2016-08-01 02:24:01 UTC

在这种现代C ++方法中,本地时间和UTC时间是不同的类型,这使我更有可能在编译时发现这两个概念的偶然混合(而不是产生运行时错误).

In this modern C++ approach, the local time and the UTC time are different types, making it much more likely that I catch accidental mixing of these two concepts at compile time (as opposed to creating run time errors).

第二种技术将在C ++ 20中以以下语法提供:

The second technique will be available in C++20 with the following syntax:

#include <chrono>
#include <iostream>

int
main()
{
    using namespace std::chrono;
    zoned_time zt{current_zone(), local_seconds{1470003841s}};
    std::cout << zt.get_sys_time().time_since_epoch() << '\n'; // 1470018241s
    std::cout << zt << '\n';
    std::cout << zt.get_sys_time() << " UTC\n";
}

这篇关于将time_t从当地时区转换为UTC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆