How do I convert a string containing a 64 bit epoch time to human readable format?

StackOverflow https://stackoverflow.com/questions/21069389

  •  27-09-2022
  •  | 
  •  

Pergunta

So I realized that the string I'm getting from a server that represents the date is a 64 bit representation of the time since the epoch. For example, one of the values I'm getting is: 1380994682285. I've tried doing an atoi on the string but obviously that doesn't work as I lose precision and the resultant value that I pass on to localtime() results in an incorrect date. This is on iOS so some phones are 32 bit and some are 64 bit, and presently, I see that it has time_t defined as a long. How do I convert this large epoch value to something I can ultimately get a human readable date from?

Foi útil?

Solução

Since it seems you are asking for C++, I add this answer. Comments try to explain issues about the fact that your input value won't fit into a 32bit variable, and if you can't have a 64bit variable, you need to "divide" before, by removing last three chars as duskwuff answer suggests.

#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;
}

This answers does not handle errors, e.g. the case when streaming is not able to read an integer, e.g. when you have "a string" instead of "1234".

Outras dicas

As Kerrek SB put in a comment, have a look at the std::sto* set of functions. std::stol will convert a string to a long, and std::stoull will convert a string to an unsigned long long. If you store that in a time_t, you can pass it to localtime without any problems.

The string is a UNIX epoch time in milliseconds, so there's an easy fix: Chop off the last three characters, and the result will be a UNIX epoch time in seconds (which will fit into a 32-bit integer until 2038).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top