vendredi 28 avril 2017

Chrono precision parameterizable function?

I am writing a utility function that returns the current time in ISO format. However, I would like to be able to specify the precision:

2017-04-28T15:07:37Z        //s
2017-04-28T15:07:37.035Z    //ms
2017-04-28T15:07:37.035332Z //us

I have working code to do this, however, I can't seem to find a way to make it generic:

string getISOCurrentTimestamp_us()
{
    char iso_buf[30];

    auto now = chrono::high_resolution_clock::now();
    auto s = chrono::duration_cast<chrono::seconds>(now.time_since_epoch());
    time_t seconds = (time_t) s.count();
    strftime(iso_buf, sizeof(iso_buf), "%FT%T", gmtime(&seconds));

    string iso_timestamp(iso_buf);

    auto us = chrono::duration_cast<chrono::microseconds>(now.time_since_epoch());
    auto us_diff = us - chrono::duration_cast<chrono::microseconds>(s);
    char buffer[8];
    std::snprintf(buffer, sizeof(buffer), ".%06d", (int) us_diff.count());

    iso_timestamp += string(buffer);
    iso_timestamp += "Z";

    return iso_timestamp;
}

As you can see, this one only returns the microsecond version. I have a separate function using chrono:milliseconds for the millisecond version. Seems like a DRY violation to have so much similar code when the only difference is the duration template parameter and the zero-padding.

Yet being able to specify the duration is tricky. I think I'm not quite understanding function templates, because I tried something like getISOCurrentTimestamp<chrono::microseconds>(), to no avail:

template <class T>
string getISOCurrentTimestamp() {
    ...
    auto t = chrono::duration_cast<T>(now.time_since_epoch());
    auto t_diff = t - chrono::duration_cast<T>(s);
}

Another problem is deducing the amount of zero padding based on T which doesn't seem trivial either (i.e. microseconds should be zero-padded up to 6, milliseconds up to 3, etc.

How can I make this ISO String function generic? Am I approaching this the wrong way?

Aucun commentaire:

Enregistrer un commentaire