【问题标题】:How to convert unsigned int 64 into time in C++?如何在 C++ 中将 unsigned int 64 转换为时间?
【发布时间】:2017-10-05 14:14:21
【问题描述】:

我正在将 CLI C++ 代码转换为标准 C++,并且我有一段代码可以获取 UINT64 数字(来自远程服务器 - 所以我无法更改为我得到的时间的格式/精度)并将其转换进入 DateTime 对象,然后输出以下值:myDatetime.ToString("dd/MM/yyyy hh:mm:ss.fffffff tt")。 我还没有找到在 C++ 中将 unsigned int 64 转换为时间的方法。 下面的代码对这么大的数字没有任何作用(这是我从服务器获得的 64 位数字)。

time_t rawtime=131274907755873979
localtime_s(&timeinfo, &rawtime);

我需要一些帮助:)

我的问题没有在线程Convert Epoch Time string to Time 中得到回答,因为它不适用于我需要的大数字。例如数字 131274907755873979 这是我从服务器得到的。该值的函数 ctime 只返回 NULL。 我需要一种方法来将我作为 unsigned int64 获得的时间转换为标准 C++ 时间对象。

【问题讨论】:

  • 您不会认为将该数字转换为 DateTime 对象可能与该问题有丝毫关联,对吗?
  • 关于“标准 C++ 时间对象”。 C++11 或更高版本是可接受的标准吗?
  • 最好是 C++11,因为我不确定我们的生产服务器上会有什么编译器版本。但我希望 C++14 也可以接受
  • 时髦。 Howard Hinnant's time libraries may be helpful to you. 可能需要进行一些 Epoch 转换(请参阅下面 @MikeNakis 的回答)。

标签: c++ datetime time c++-cli


【解决方案1】:

您尚未告诉我们现有代码如何将该数字转换为DateTime。让我们假设它是通过调用这个构造函数来实现的:DateTime( long long ticks )

根据the documentation of that constructor of DateTime

long long ticks 日期和时间,以自公历 0001 年 1 月 1 日 00:00:00.000 以来经过的 100 纳秒间隔数表示。

另一方面,根据the documentation of localtime_sthe documentation of time_tlocaltime_s()需要

自 1970 年 1 月 1 日 00:00 UTC 以来的秒数(不包括闰秒)。

因此,您首先需要将 100 纳秒的间隔转换为秒,然后将 0001 年 1 月 1 日转换为 1970 年 1 月 1 日。

【讨论】:

  • 目前的工作方式是使用 DateTime::FromFileTime 函数将 unsigned int64 转换为 DateTime 对象。
  • 同样的事情,根据 [FromFileTime 的文档] (msdn.microsoft.com/en-us/library/…)
  • 你是什么意思:“所以,你首先需要将 100 纳秒的间隔转换为秒,然后从 0001 年 1 月 1 日转换为 1970 年 1 月 1 日” - 我该如何进行这种转换?
  • 呃,这不是编程问题。把它带到math.stackexchange.com 怎么样?
【解决方案2】:

使用Howard Hinnant's datetime library 这个计算可以很容易地完成。它适用于 VS 2013 及更高版本。

#include "tz.h"
#include <cstdint>
#include <string>
#include <iostream>

std::string
FILETIME_to_string(std::uint64_t i)
{
    using namespace std;
    using namespace std::chrono;
    using namespace date;
    using FileTime = duration<int64_t, ratio<1, 10000000>>;
    auto const offset = sys_days{jan/1/1970} - sys_days{jan/1/1601};
    auto tp = sys_days{jan/1/1970} + (FileTime{static_cast<int64_t>(i)} - offset);
    return format("%d/%m/%Y %I:%M:%S %p", make_zoned("Etc/GMT-2", tp));
}

int
main()
{
    std::cout << FILETIME_to_string(131274907755873979) << '\n';
}

这会跳过DateTime 并直接转到string。我不确定您对 tt 格式的要求是什么。但不管是什么,都可以处理。

此库基于 C++11 &lt;chrono&gt; 库构建。所以首先要做的是创建一个持续时间来表示窗口刻度大小(100 ns)。然后只需计算两个时期之间的偏移量并将其从输入中减去,并形成std::chrono::time_point。现在你可以随意格式化time_point

上面的程序输出:

29/12/2016 03:12:55.5873979 PM

如果你使用VS 2017,你将能够使offsetconstexpr,使转换更有效率。

【讨论】:

  • 非常感谢。但我的工作不允许使用第三方库。是否可以通过构建 chrono 库来做到这一点?
  • @primeQuestion:是的,我的整个库可移植地构建在 &lt;chrono&gt; 之上。您需要计算两个纪元日期之间的0.1 microseconds 的数量,将其从输入中减去,然后将其转换为{year, month, day, hour, minute, second, fractional second} 数据结构,然后对其进行格式化。这是一篇包含日历公式的论文,可以帮助您:howardhinnant.github.io/date_algorithms.html
  • 谢谢。为什么您使用 jan/1/1601 作为 Windows 的 epoh 日期?不是 0001 年 1 月 1 日 00:00:00.000 吗?
  • 另外——“tt”应该输出 PM 或 AM。原始代码中 131274907755873979 的正确输出是 9/12/2016 03:12:55.5873979 PM。所以它与你的略有不同。也许是因为“tt”?
  • 我使用了 jan/1/1601,因为我猜您使用的是基于 Windows Filetime 纪元(即 1601-01-01 00:00:00 UTC)的东西。当我使用那个时代时,您的示例输入给出了合理的输出,因此我认为我的猜测是正确的。
【解决方案3】:
std::string LongToString(int64_t longDate) {        
    char buff[128];

    std::chrono::duration<int64_t, std::milli> dur(longDate);
    auto tp = std::chrono::system_clock::time_point(
        std::chrono::duration_cast<std::chrono::system_clock::duration>(dur));
    std::time_t in_time_t = std::chrono::system_clock::to_time_t(tp);
    strftime(buff, 128, "%Y-%m-%d %H:%M:%S", localtime(&in_time_t));
    std::string resDate(buff);
    
    return resDate;

}

这是 bsoncxx::types::b_date get_date().to_int64() MongoDB 的情况。

使用 int64_t 保存的 DateTime。

【讨论】:

  • 虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。
猜你喜欢
  • 2022-01-04
  • 1970-01-01
  • 2013-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多