How appropriate, you fight like a cow !

Unix timestamp seconds and nanoseconds string conversion in C++

2024-11-29 – 23:25

I have recently worked with the PcapPlusPlus library to analyze timestamps from PCAP ethernet captures. And I have fucked up majorly the Unix timestamp to string conversion. This post is meant to
1. remind me of my failure…
2. remember how to do it right the next time

Unix timestamps represent time elapsed since 00:00:00 UTC on Thursday, 1 January 1970, mostly in seconds, in case of .pcap(ng) files with an additional fractional nanoseconds part.
The following timestamp represents Mon Jul 15 2024 17:48:40 GMT+0000 and almost a second full of nanoseconds (the fractional part):

1721065720.968918119

In my C++ program I wanted to export stuff as CSV including a row of Unix timestamps. PcapPlusPlus allows getting the timestamp from a parsed packet read from a pcap(ng) file like this:

uint32 seconds = parsedPacket.getRawPacket()->getPacketTimeStamp().tv_sec;
uint32 nanosececonds = parsedPacket.getRawPacket()->getPacketTimeStamp().tv_nsec;

Converting this to string seems to be straight forward using a std::stringstream. The crucial part is that the nanoseconds part can start with one or more zeros such as this:

1721065721.008918119

The fractional part represents 0.008918119 seconds. This must be 9 digits long!
Parsing the fractional part of this with a std::stringstream will strip the leading zeros which reduces the length of the nanoseconds fractional part: The fractional part must preserve the 9 digits because 0.8918119 s is much bigger than 0.008918119 s.
To properly parse the fractional part (e.g. to plot it) it must be ensured that the leading zeros also go into the string written into the CSV:

#include <sstream>
#include <iomanip>
const std::string pcapTimestampToString(const uint32 seconds_, 
                                        const uint32 nanoseconds_) {
  std::stringstream ss;
  ss<<seconds_<<".";
  ss<<std::setfill('0')<<std::setw(9)<<nanoseconds_;
  return ss.str();
}
 
const std::string pcapTimestampString = pcapTimestampToString(
                 parsedPacket.getRawPacket()->getPacketTimeStamp().tv_sec, 
                 parsedPacket.getRawPacket()->getPacketTimeStamp().tv_nsec);

This was partially answered by Stackoverflow but not specifically enough to not deserve a dedicated post.

Post a Comment

Insert a smiley:


To prevent spam and comments of people who don't
know about mathematics you have to enter the result
into the field on the right side.
Hint: Possible answers are '-3', '-2', '0', '1' and '6x'.
Some challenges have more than one correct answer!

Please note: Comments will be approved manually!
It may take a few hours to check if yours
is legitimate even after solving the captcha..
Spam protection

Captcha