【问题标题】:How do I convert a string containing a 64 bit epoch time to human readable format?如何将包含 64 位纪元时间的字符串转换为人类可读的格式?
【发布时间】:2014-01-30 21:44:52
【问题描述】:

所以我意识到我从服务器获取的表示日期的字符串是自纪元以来时间的 64 位表示。例如,我得到的值之一是:1380994682285。我尝试在字符串上执行 atoi,但显然这不起作用,因为我失去了精度并且我传递给 localtime() 的结果值导致日期不正确。这是在 iOS 上,所以有些手机是 32 位的,有些是 64 位的,目前,我看到它的 time_t 定义为 long。如何将这么大的 epoch 值转换为我最终可以从中获得人类可读日期的东西?

【问题讨论】:

  • 试试std::stoull。
  • 那我会把它传递给什么? localtime 需要一个 time_t,在我的平台上它被定义为 long。
  • localtime 也需要几秒钟,而您需要几秒钟。做除法。

标签: c++ ios epoch


【解决方案1】:

由于您似乎要求使用 C++,因此我添加了此答案。评论试图解释有关您的输入值不适合 32 位变量这一事实的问题,如果您不能拥有 64 位变量,您需要先“除”,通过删除最后三个字符,如黄昏回答建议的那样。

#include <sstream>
#include <iostream>
#include <cstring>
#include <ctime>

// uint64_t ... gcc complains it's a C++11 stuff
//#include <cinttypes>

int main()
{
    const char *d = "1380994682285";

    std::stringstream is(d);

    // ISO C++98 does not support long long
    // ... it should be uint64_t, but supported in C++11...
    // or rather, just long but be sure you compile for 64bit
    std::cout << sizeof (long) << "\n";       // very likely 4 on 32bit
    std::cout << sizeof (long long) << "\n";  // 8
    unsigned long long epoch64;
    // if you need strict ISO C++98 conformance, you must use unsigned long,
    // see below.

    is >> epoch64;

    std::cout << epoch64 << "\n";
    epoch64 /= 1000;
    // this goes ok (if epoch64 is big enough), since /1000 makes it
    // small enough to go into time_t
    time_t t = epoch64;

    std::cout << std::ctime(&t) << "\n";

    // if you use unsigned long for epoch, and it turns out to
    // be sizeof (unsigned long) == 4, then you get the wrong output.
    // Then, you must make it shorter before to convert it:
    std::string shorter(d, strlen(d)-3); // assert(strlen(d)>3)
    std::stringstream is2(shorter);

    unsigned long epoch32; // I am on a 32bit machine
    is2 >> epoch32;
    t = epoch32;
    std::cout << epoch32 << "\n";
    std::cout << std::ctime(&t) << "\n";

    return 0;
}

此答案不处理错误,例如流式传输无法读取整数的情况,例如当你有“a string”而不是“1234”时。

【讨论】:

  • 我爱你!这工作得很好,谢谢。是的,C++ 是我所追求的,因为我正在用它而不是 Objective-c 编写我的可移植代码。非常感谢!
  • 注意最后三个字符必须是数字的一部分:如果您有尾随空格、换行符或其他垃圾,strlen(d)-3 不会正确“截断”输入字符串.
【解决方案2】:

正如 Kerrek SB 在评论中所说,请查看 std::sto* 函数集。 std::stol 将字符串转换为 long,std::stoull 将字符串转换为 unsigned long long。如果您将其存储在 time_t 中,则可以毫无问题地将其传递给 localtime。

【讨论】:

  • 我不能这样做,因为 time_t 被定义为 long,所以我在执行 std::stoull 时会失去精度,所以我的日期最终不正确。
  • @Architekt 如果您的纪元时间字符串不适合 time_t,您只会失去 std::stoll 的精度。无论如何,它仍然会失去 std::stol 的精度。使用 std::stoull 意味着即使在 time_t 可能更大的其他平台上,您仍然会得到准确的答案(到 time_t 的精度)
【解决方案3】:

该字符串是以毫秒为单位的 UNIX 纪元时间,因此有一个简单的解决方法:去掉最后三个字符,结果将是一个以秒为单位的 UNIX 纪元时间(它将适合 32 位整数,直到 2038 年) .

【讨论】:

    猜你喜欢
    • 2019-12-03
    • 2021-06-21
    • 2012-08-16
    • 2018-10-06
    • 2013-01-13
    • 2018-12-13
    • 2013-03-17
    • 2014-09-06
    相关资源
    最近更新 更多