Skip to content
Advertisement

How to format unix time (sec+usec+nsec) string?

I have this function which works just fine. It gives me current system time the way I need:

struct Timer
{
    struct timespec ts;
    char buff[16];
    char res[64];

public:
    char* GetTimestampNow()
    {
        timespec_get(&ts, TIME_UTC);
        strftime(buff, sizeof buff, "%T", gmtime(&ts.tv_sec));
        snprintf(res, 64, "%s.%09ld", buff, ts.tv_nsec);

        return res;
    }
    char* GetTimestamp(int sec, int usec) {
        // ??? how do I convert raw readings into timespec or anything else I can use in strftime?
        strftime(buff, sizeof buff, "%T", gmtime(&ts.tv_sec));
        snprintf(res, 64, "%s.%09ld", buff, ts.tv_nsec);

        return res;
    }
    char* GetTimestamp(int sec, int usec, int nsec) {
        // same question plus nanosecs
};

Now I need to also be able to print timestamps I receive from 3rd party lib in 2-3 variables – sec, usec, nsec (optional). Can I somehow construct timespec from these values and reuse the code I already have?

Advertisement

Answer

You don’t need a timespec structure.

Notice how all the gmtime calls only use the tv_sec field of the structure? You can use the sec argument directly in the gmtime call.

As for the nanoseconds, you could multiply usec with 1000 to get the corresponding nanoseconds.

So something like:

char buff[16];  // No need to make this a member variable, it can be local
strftime(buff, sizeof buff, "%T", gmtime(&sec));
snprintf(res, 64, "%s.%09ld", buff, usec * 1000);

In the third overload, just add nsec to the result of usec * 1000.


I would rather recommend you create a utility function for the creation of the string, which all the other functions are calling.

Like

class Timer
{
public:
    std::string GetTimestampNow()
    {
        timespec ts;
        timespec_get(&ts, TIME_UTC);
        return GetTimestampHelper(ts.tv_sec, ts.tv_nsec);
    }

    std::string GetTimestamp(time_t sec, long usec)
    {
        return GetTimestampHelper(sec, usec * 1000);
    }

    std::string GetTimestamp(time_t sec, long usec, long nsec)
    {
        return GetTimestampHelper(sec, usec * 1000 + nsec);
    }

private:
    std::string GetTimestampHelper(time_t sec, long nsec)
    {
        char buff[64];
        strftime(buff, sizeof buff, "%T", gmtime(&sec));

        char res[64];
        snprintf(res, sizeof res, "%s.%09ld", buff, nsec);

        return res;
    }
};

And unless there’s code and requirements not mentioned, there’s really no need for these member functions to be non-static.

And the Timer names implies something like stop-watch, so the class should probably be renamed as well.

Advertisement