c++ - Java 到 C++ UTC 时间 - 以秒为单位查找 Utc 区域时间偏移
问题描述
我需要使用无符号字符的纯 ByteBuffer 的最小长度将 UTC 日期时间实例从 java 序列化为 c++。我需要能够支持最小纳秒精度的时间点。
从 java 方面,我查看了 ZonedDateTime 和 OffsetDateTime 类,并查看了它们用于存储时间的原语类型,总共等于 17 个字节,这有点多。
请注意,我在这里并没有转移区域本身,因为我还没有找到将这些区域字符串从 IANA 映射到整数的方法。因此,我想区域偏移量就足够了。由于买方必须在将其时间点发送到服务器之前将其时间点转换为特定的偏移量,因此可以说这将是 UTC 0。我正在寻找一种解决本地时间问题的解决方案,即不涉及 NTP 服务器!
java端看起来像这样:
// 4 byte
Integer year = offsetDateTime.getYear();
// 1 byte
Integer month = offsetDateTime.getMonthValue();
// 1 byte
Integer day = offsetDateTime.getDayOfMonth();
// 1 byte
Integer hour = offsetDateTime.getHour();
// 1 byte
Integer minutes = offsetDateTime.getMinute();
// 1 byte
Integer seconds = offsetDateTime.getSecond();
// 4 byte
Integer nanoSeconds = offsetDateTime.getNano();
// 4 byte
Integer utcZoneTimeTotalSecondsOffset = offsetDateTime.getOffset().getTotalSeconds();
在 c++ 方面,我需要做同样的事情,并且能够从上面的所有这些整数中构造一个时间点。除了 utcOffset 即最后一个整数之外,我已经找到了如何获取上述信息的方法。
我想使用 chrono 来消耗这个缓冲区并从中实例化一个时间点。但是我无法找到一种方法来获取 C++ 中的时间偏移量。如何使用 chrono 获取时间偏移,然后根据上述信息构造一个时间点?
auto now = std::chrono::system_clock::now();
time_t itt = std::chrono::system_clock::to_time_t(now);
tm utc_tm = *gmtime(&itt);
std::cout << utc_tm.tm_year + 1900 << '-';
std::cout << utc_tm.tm_mon + 1 << '-';
std::cout << utc_tm.tm_mday << ' ';
std::cout << utc_tm.tm_hour << ':';
std::cout << utc_tm.tm_min << ':';
std::cout << utc_tm.tm_sec << '\n';
? wher is the time zoneOffset here ?
如果我使用
utc_tm.tm_gmtoff
这给了我错误的信息。至少在我的情况下。所以我相信 gmtoff 不是要走的路,但如果 gmtoff 不是路,那又是什么呢?
解决方案
不是一个完整的答案,但这是使用Howard Hinnant 的免费开源时区库序列化 C++ 本地时间点的一种方法。
#include "date/tz.h"
#include <iostream>
#include <sstream>
std::string
to_string(date::zoned_time<std::chrono::nanoseconds> t)
{
using namespace std;
using namespace date;
ostringstream out;
out << t.get_sys_time().time_since_epoch().count()
<< ' ' << t.get_time_zone()->name();
return out.str();
}
date::zoned_time<std::chrono::nanoseconds>
from_string(const std::string& s)
{
using namespace std;
using namespace std::chrono;
using namespace date;
istringstream in{s};
long long ns;
std::string tz_name;
in >> ns >> tz_name;
return {tz_name, sys_time<nanoseconds>{nanoseconds{ns}}};
}
int
main()
{
using namespace std;
using namespace std::chrono;
using namespace date;
zoned_time<nanoseconds> zt{current_zone(), system_clock::now()};
cout << zt << '\n';
auto s = to_string(zt);
cout << s << '\n';
zt = from_string(s);
cout << zt << '\n';
}
我使用 astd::string
来表示可能通过网络发送的序列化。
此示例首先使用计算机的当前本地时区和当前 UTC 时间 main
创建存储在 中的纳秒精度本地时间点。首先简单地打印这个时间戳,对我来说只是输出:date::zoned_time<nanoseconds>
main
2019-09-11 12:37:04.846272000 EDT
这是我当前的本地日期/时间和时区缩写。
接下来,程序将其转换为包含少量(但不一定是最少)ASCII 字符的字符串,以完整描述本地时间点。我选择了格式:
<Number of nanoseconds since epoch> <IANA time zone name>
在此示例中,该字符串是:
1568219824846272000 America/New_York
这string
是在 中形成的to_string
,它简单地流出了系统时间的“自纪元以来的时间”,zoned_time
。然后添加一个空格,并流出时区的名称。
from_string
通过读取纳秒数,然后读取时区名称来反转此操作。然后,它zoned_time<nanoseconds>
通过将时区名称配对并sys_time<nanoseconds>
与解析的整数形成 a 来形成 a。
main
打印出解析zoned_time
以确保我们有一个无损的往返:
2019-09-11 12:37:04.846272000 EDT
为了获得包含本地时间的无损转换,确实需要传输 IANA 时区名称,而不仅仅是当前的 UTC 偏移量。仅使用 UTC 偏移量,就可以恢复准确的 UTC 时间点。但是不能执行任何本地时间算术,或与其他本地时间点进行比较,因为人们无法知道何时更改 UTC 偏移量的规则。只有使用完整的 IANA 时区名称,才能传递有关这些规则的信息。
推荐阅读
- r - 在R中的某个字符串模式之后删除前4个单词?
- javascript - 如何修复 React.Children.only 预计会在 react.js 中接收单个 React 元素子项?
- python - 为什么 spark 无法识别我的“数据框布尔表达式”?
- c# - InstallUtil 会自动为您注册 .dll 吗?
- javascript - 如何使用javascript比较数组对象中的元素
- javascript - 控制台日志在函数返回对象时打印承诺,但在不是对象时打印数据
- java - 有 Lombok 注释 @Slf4j 不起作用
- drake - 如何在 Python 中创建线性/仿射系统的多项式轨迹?即时变 A 和 B 矩阵
- python - 如何在 ffprobe 中省略 JSON 输出中的错误消息?
- vaadin - 如何在 LitElement 的 vaadin 网格中延迟加载项目