【问题标题】:Date and time from Siemens西门子日期和时间
【发布时间】:2021-06-02 10:39:27
【问题描述】:

背景: 我有一个旧的 Siemens cpu,它将以 date_and_time 格式向我发送总共 8 个字节。这种格式的构造使得前 4 个字节包含时间,最后 4 个字节包含自 1992 年 1 月 1 日以来的日期。

问题:我开始提取最后4个日期来计算日期,使用

    long long int dt = 0x60592102FC29000;
    char a, b, c, d;
    a = (dt & 0xFF);
    b = ((dt >> 8) & 0xFF);
    c = ((dt >> 16) & 0xFF);
    d = ((dt >> 24) & 0xFF);
    long int date = int((unsigned char)a << 24 |
        (unsigned char)b << 16 |
        (unsigned char)c << 8 |
        (unsigned char)d);

但是在这部分之后我被卡住了,因为我想不出任何好的方法来计算一天而不循环所有天。

示例:

0x60592102FC29000 等于 2021-06-04 09:55:40.000

0x7A0DC6021C07000 等于 1996-12-24 12:55:34.010

参考资料:

T#0d_0h_0m_0s_0ms 到 T#49d_17h_2m_47s_295ms 值日、小时、分钟、最多两位数 秒,最多三位毫秒 用 T#0d_0h_0m_0s_0ms 初始化

D#1992-01-01 到 D#2200-12-31 考虑闰年,年份有四位数, 月和日各为两位数 用 D#0001-01-01 初始化

Link to siemens way of calculating

Siemens manual, page 107

我的最终解决方案受以下帖子启发:

    //1996-12-24 12:55:34.010
    long long int dt = 0x7A0DC6021C070000;
    const int dateOffset = 8034;
    time_t date_t = 0;

    int date =
        ((dt & 0xFF) << 24) |
        (((dt >> 8) & 0xFF) << 16) |
        (((dt >> 16) & 0xFF) << 8) |
        (((dt >> 24) & 0xFF));
    int time =
        ((dt >> 32 & 0xFF) << 24) |
        (((dt >> 40) & 0xFF) << 16) |
        (((dt >> 48) & 0xFF) << 8) |
        (((dt >> 56) & 0xFF));

    tm _dt = *localtime(&date_t);

    _dt.tm_mday += dateOffset + date;
    _dt.tm_sec += time/1000;

    mktime(&_dt);

【问题讨论】:

  • 不,当然不需要“整天循环”。计算很简单:1)距离下月初的天数,2)明年同上,3)闰年同上。以这种方式,将天数添加到日期是有限数量的计算,仅涉及基本的日期数学。具体来说,这些计算的哪些部分不清楚?
  • 我正在考虑尝试将我的 8 个字节转换为标准 time_t 格式以更好地使用这些功能,但这可能是一个不好的方法?我还需要能够处理循环年
  • 这种方法听起来可能可行:将天数乘以 24 个日历日的秒数,并将其添加到纪元开始日中午的 time_t(以避免时区过渡问题),然后使用标准库例程来计算结果日期。对我来说,这似乎是一个已解决的问题。

标签: c++


【解决方案1】:

我认为您应该帮自己一个忙并使用 chrono 库。众所周知,日期问题很难处理并且容易出错。使用 chrono 库,您的问题可以归结为简单的事情

date_time dt=date_time(1992, 1, 1) + days(value);

value 是 Siemens CPU 返回的值。

boost::chrono 或 boost::date_time 应该可以在包括嵌入式系统在内的旧 CPU 上使用。 C++ 标准有 std::chrono,但你需要的功能只有 C++20 才有。

这里是一个使用 boost::date_time 的例子:

#include "boost/date_time/gregorian/gregorian.hpp"

date start(1992,Jan,1);

date yourdate=start + days(value);

【讨论】:

  • 找不到日期时间类型。包括计时码表。我错过了什么吗?
  • boost chrono 也很好,如果它可以让你定义天数并且有天数算术。我认为,首先是 boost::date_time,然后是 boost::chrono,它已经进入了 C++ 标准。如果您可以使用 std::chrono 并拥有 C++20 函数来增加天数,那可能是最好的选择。 :)
【解决方案2】:

使用Howard Hinnant's date libraryc++20 equivalent 会更容易:

#include "date.h"
#include <chrono>
#include <iostream>

using namespace date;
using namespace date::literals;

int main()
{
    date::sys_days epoch = 1992_y / 1 / 1;
    uint64_t date_time = 0x60592102'FC290000;
    date::days days(
        (( date_time & 0xFF ) << 24) |
        (( (date_time >> 8) & 0xFF) << 16) |
        (( (date_time >> 16) & 0xFF) << 8) |
        (( (date_time >> 24) & 0xFF)));
    std::chrono::milliseconds time(
        ((date_time >> 32 & 0xFF) << 24) |
        (((date_time >> 40) & 0xFF) << 16) |
        (((date_time >> 48) & 0xFF) << 8) |
        (((date_time >> 56) & 0xFF)));
    std::chrono::system_clock::time_point result = epoch + days + time;
    std::cout << result << "\n";
}

请注意,您的示例值似乎不正确(缺少尾随 0)。此代码打印:

2021-06-05 09:55:40.0000000

哪一天比您的样本值晚了一天,我不确定您的样本是错误的还是第 1 天是 1 月 1 日?您链接到的规范非常不清楚。如果样本是正确的,那么很容易通过添加来修复:

epoch -= date::days(1);

同样的代码使用c++20:

#include <chrono>
#include <iostream>
#include <format>

using namespace std::chrono;
using namespace std::literals;

int main()
{
    sys_days epoch = 1992y / 1 / 1;
    uint64_t date_time = 0x60592102'FC290000;
    days days(
        ((date_time & 0xFF) << 24) |
        (((date_time >> 8) & 0xFF) << 16) |
        (((date_time >> 16) & 0xFF) << 8) |
        (((date_time >> 24) & 0xFF)));
    milliseconds time(
        ((date_time >> 32 & 0xFF) << 24) |
        (((date_time >> 40) & 0xFF) << 16) |
        (((date_time >> 48) & 0xFF) << 8) |
        (((date_time >> 56) & 0xFF)));
    system_clock::time_point result = epoch + days + time;
    std::cout << std::format("{:%F %T %Z}", result) << "\n";
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-02
    • 2016-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-28
    • 1970-01-01
    • 2014-11-10
    相关资源
    最近更新 更多