Formatting struct timespec - c

How to format struct timespec to string? This structure is returned e.g. by clock_gettime() on Linux gcc:
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};

One way to format it is:
printf("%lld.%.9ld", (long long)ts.tv_sec, ts.tv_nsec);

I wanted to ask the same question. Here is my current solution to obtain a string like this: 2013-02-07 09:24:40.749355372
I am not sure if there is a more straight forward solution than this, but at least the string format is freely configurable with this approach.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define NANO 1000000000L
// buf needs to store 30 characters
int timespec2str(char *buf, uint len, struct timespec *ts) {
int ret;
struct tm t;
tzset();
if (localtime_r(&(ts->tv_sec), &t) == NULL)
return 1;
ret = strftime(buf, len, "%F %T", &t);
if (ret == 0)
return 2;
len -= ret - 1;
ret = snprintf(&buf[strlen(buf)], len, ".%09ld", ts->tv_nsec);
if (ret >= len)
return 3;
return 0;
}
int main(int argc, char **argv) {
clockid_t clk_id = CLOCK_REALTIME;
const uint TIME_FMT = strlen("2012-12-31 12:59:59.123456789") + 1;
char timestr[TIME_FMT];
struct timespec ts, res;
clock_getres(clk_id, &res);
clock_gettime(clk_id, &ts);
if (timespec2str(timestr, sizeof(timestr), &ts) != 0) {
printf("timespec2str failed!\n");
return EXIT_FAILURE;
} else {
unsigned long resol = res.tv_sec * NANO + res.tv_nsec;
printf("CLOCK_REALTIME: res=%ld ns, time=%s\n", resol, timestr);
return EXIT_SUCCESS;
}
}
output:
gcc mwe.c -lrt
$ ./a.out
CLOCK_REALTIME: res=1 ns, time=2013-02-07 13:41:17.994326501

The following will return an ISO8601 and RFC3339-compliant UTC timestamp, including nanoseconds.
It uses strftime(), which works with struct timespec just as well as with struct timeval because all it cares about is the number of seconds, which both provide. Nanoseconds are then appended (careful to pad with zeros!) as well as the UTC suffix 'Z'.
Example output: 2021-01-19T04:50:01.435561072Z
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
int utc_system_timestamp(char[]);
int main(void) {
char buf[31];
utc_system_timestamp(buf);
printf("%s\n", buf);
}
// Allocate exactly 31 bytes for buf
int utc_system_timestamp(char buf[]) {
const int bufsize = 31;
const int tmpsize = 21;
struct timespec now;
struct tm tm;
int retval = clock_gettime(CLOCK_REALTIME, &now);
gmtime_r(&now.tv_sec, &tm);
strftime(buf, tmpsize, "%Y-%m-%dT%H:%M:%S.", &tm);
sprintf(buf + tmpsize -1, "%09luZ", now.tv_nsec);
return retval;
}
GCC command line example (note the -lrt):
gcc foo.c -o foo -lrt

You can pass the tv_sec parameter to some of the formatting function. Have a look at gmtime, localtime(). Then look at snprintf.

You could use a std::stringstream. You can stream anything into it:
std::stringstream stream;
stream << 5.7;
stream << foo.bar;
std::string s = stream.str();
That should be a quite general approach. (Works only for C++, but you asked the question for this language too.)

Related

linux timeval gettimeofday printf error

The function displayTimeDifference is not working properly; the issue is that the printf statement is failing. After Googling the format of the printf statement when using a timeval is correct. Not sure why I can't print out the value of the timeval. I'm not getting any system errors from gettimeofday().
#include <sys/time.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
struct timeval *timeBefore;
struct timeval *timeAfter;
char * Buffer;
double malloctest(const int, const int, const int);
double calloctest(const int, const int, const int);
double allocatest(const int, const int, const int);
void displayTimeDifference();
int main(int argc, char **argv)
{
malloctest(3072, 10, 10);
return 0;
}
double malloctest(const int objectsize, const int numobjects, const int numtests)
{
int i;
int retVal;
for (i = 1; i < numtests; i++) {
if ((retVal = gettimeofday(timeBefore, NULL)) != 0) {
printf("ERROR: gettimeofday failed with code: %d\n", retVal);
}
Buffer = (char*)malloc(objectsize * sizeof(char));
if ((retVal = gettimeofday(timeAfter, NULL)) != 0) {
printf("ERROR: gettimeofday failed with code: %d\n", retVal);
}
displayTimeDifference();
}
return 0.0;
}
void displayTimeDifference()
{
printf("Time in microseconds: %ld microseconds\n", (timeAfter->tv_sec - timeBefore->tv_sec));
}
gettimeofday needs a valid pointer to struct timeval, where it can save the informations, you call it with a NULL pointer.
you should change
struct timeval *timeBefore;
struct timeval *timeAfter;
to
struct timeval timeBefore;
struct timeval timeAfter;
and the calls to gettimeofday(&timeBefore, NULL) and gettimeofday(&timeAfter, NULL). You check the return value of this function and print something, but your program continues as it was successfully.
Also
printf("Time in microseconds: %ld microseconds\n", (timeAfter->tv_sec - timeBefore->tv_sec));
to
printf("Time in seconds: %ld microseconds\n", (timeAfter.tv_sec - timeBefore.tv_sec));.
You are only calculating the seconds, not the microseconds.
Another possibility is to malloc the memory for the pointer, but that is not really necessary.
As already said in another answer you have wrongly declared the struct timeval as pointers.
I share my timing macros:
#define START_TIMER(begin) gettimeofday(&begin, NULL) // ;
#define END_TIMER(end) gettimeofday(&end, NULL) // ;
//get the total number of sec:
#define ELAPSED_TIME(elapsed, begin, end) \
elapsed = (end.tv_sec - begin.tv_sec) \
+ ((end.tv_usec - begin.tv_usec)/1000000.0) // ;
Where you have to define the variables:
struct timeval begin, end;
double elapsed;

How to convert character string in microseconds to struct tm in C?

I have a string that contains microseconds since the epoch. How could I convert it to a time structure?
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main ()
{
struct tm tm;
char buffer [80];
char *str ="1435687921000000";
if(strptime (str, "%s", &tm) == NULL)
exit(EXIT_FAILURE);
if(strftime (buffer,80,"%Y-%m-%d",&tm) == 0)
exit(EXIT_FAILURE);
printf("%s\n", buffer);
return 0;
}
Portable solution (assuming 32+ bit int). The following does not assume anything about time_t.
Use mktime() which does not need to have fields limited to their primary range.
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char buffer[80];
char *str = "1435687921000000";
// Set the epoch: assume Jan 1, 0:00:00 UTC.
struct tm tm = { 0 };
tm.tm_year = 1970 - 1900;
tm.tm_mday = 1;
// Adjust the second's field.
tm.tm_sec = atoll(str) / 1000000;
tm.tm_isdst = -1;
if (mktime(&tm) == -1)
exit(EXIT_FAILURE);
if (strftime(buffer, 80, "%Y-%m-%d", &tm) == 0)
exit(EXIT_FAILURE);
printf("%s\n", buffer);
return 0;
}
Edit: You could simply truncate the string, since struct tm does not store less than 1 second accuracy.
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
struct tm now;
time_t secs;
char buffer [80];
char str[] ="1435687921000000";
int len = strlen(str);
if (len < 7)
return 1;
str[len-6] = 0; // divide by 1000000
secs = (time_t)atol(str);
now = *localtime(&secs);
strftime(buffer, 80, "%Y-%m-%d", &now);
printf("%s\n", buffer);
printf("%s\n", asctime(&now));
return 0;
}
Program output:
2015-06-30
Tue Jun 30 19:12:01 2015
You can convert the microseconds to seconds, and use localtime() like this
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main (void)
{
struct tm *tm;
char buffer[80];
char *str = "1435687921000000";
time_t ms = strtol(str, NULL, 10);
/* convert to seconds */
ms = (time_t) ms / 1E6;
tm = localtime(&ms);
if (strftime(buffer, 80, "%Y-%m-%d", tm) == 0)
return EXIT_FAILURE;
printf("%s\n", buffer);
return EXIT_SUCCESS;
}
Note that in the printed date, the microseconds are not present, so you can ignore that part.
Convert the string to a time_t, then use gmtime(3) or localtime(3).
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main () {
struct tm *tm;
char buffer [80];
char *str ="1435687921000000";
time_t t;
/* or strtoull */
t = (time_t)(atoll(str)/1000000);
tm = gmtime(&t);
strftime(buffer,80,"%Y-%m-%d",tm);
printf("%s\n", buffer);
return 0;
}

How to Find a current day in c language?

I am able to get the current date but the output is like 9/1/2010,but my requirement is to get the current day like"Wednesday" not in form of integer value like 1.
My code is here.
#include <dos.h>
#include <stdio.h>
#include<conio.h>
int main(void)
{
struct date d;
getdate(&d);
printf("The current year is: %d\n", d.da_year);
printf("The current day is: %d\n", d.da_day);
printf("The current month is: %d\n", d.da_mon);
getch();
return 0;
}
Please help me to find the current day as Sunday,Monday.........
Thanks
Are you really writing for 16-bit DOS, or just using some weird outdated tutorial?
strftime is available in any modern C library:
#include <time.h>
#include <stdio.h>
int main(void) {
char buffer[32];
struct tm *ts;
size_t last;
time_t timestamp = time(NULL);
ts = localtime(&timestamp);
last = strftime(buffer, 32, "%A", ts);
buffer[last] = '\0';
printf("%s\n", buffer);
return 0;
}
http://ideone.com/DYSyT
The headers you are using are nonstandard. Use functions from the standard:
#include <time.h>
struct tm *localtime_r(const time_t *timep, struct tm *result);
After you call the function above, you can get the weekday from:
tm->tm_wday
Check out this tutorial/example.
There's more documentation with examples here.
As others have pointed out, you can use strftime to get the weekday name once you have a tm. There's a good example here:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
char outstr[200];
time_t t;
struct tm *tmp;
t = time(NULL);
tmp = localtime(&t);
if (tmp == NULL) {
perror("localtime");
exit(EXIT_FAILURE);
}
if (strftime(outstr, sizeof(outstr), "%A", tmp) == 0) {
fprintf(stderr, "strftime returned 0");
exit(EXIT_FAILURE);
}
printf("Result string is \"%s\"\n", outstr);
exit(EXIT_SUCCESS);
}
Alternatively, if you insist on using your outdated compiler, there's a dosdate_t struct in <dos.h>:
struct dosdate_t {
unsigned char day; /* 1-31 */
unsigned char month; /* 1-12 */
unsigned short year; /* 1980-2099 */
unsigned char dayofweek; /* 0-6, 0=Sunday */
};
You fill it with:
void _dos_getdate(struct dosdate_t *date);
Use struct tm Example
strftime is certainly the right way to go. Of course you could do
char * weekday[] = { "Sunday", "Monday",
"Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"};
char *day = weekday[d.da_day];
I'm of course assuming that the value getdate() puts in the date struct is 0-indexed, with Sunday as the first day of the week. (I don't have a DOS box to test on.)

How to print time in format: 2009‐08‐10 18:17:54.811

What's the best method to print out time in C in the format 2009‐08‐10 
18:17:54.811?
Use strftime().
#include <stdio.h>
#include <time.h>
int main()
{
time_t timer;
char buffer[26];
struct tm* tm_info;
timer = time(NULL);
tm_info = localtime(&timer);
strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
puts(buffer);
return 0;
}
For milliseconds part, have a look at this question. How to measure time in milliseconds using ANSI C?
The above answers do not fully answer the question (specifically the millisec part). My solution to this is to use gettimeofday before strftime. Note the care to avoid rounding millisec to "1000". This is based on Hamid Nazari's answer.
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <math.h>
int main() {
char buffer[26];
int millisec;
struct tm* tm_info;
struct timeval tv;
gettimeofday(&tv, NULL);
millisec = lrint(tv.tv_usec/1000.0); // Round to nearest millisec
if (millisec>=1000) { // Allow for rounding up to nearest second
millisec -=1000;
tv.tv_sec++;
}
tm_info = localtime(&tv.tv_sec);
strftime(buffer, 26, "%Y:%m:%d %H:%M:%S", tm_info);
printf("%s.%03d\n", buffer, millisec);
return 0;
}
time.h defines a strftime function which can give you a textual representation of a time_t using something like:
#include <stdio.h>
#include <time.h>
int main (void) {
char buff[100];
time_t now = time (0);
strftime (buff, 100, "%Y-%m-%d %H:%M:%S.000", localtime (&now));
printf ("%s\n", buff);
return 0;
}
but that won't give you sub-second resolution since that's not available from a time_t. It outputs:
2010-09-09 10:08:34.000
If you're really constrained by the specs and do not want the space between the day and hour, just remove it from the format string.
Following code prints with microsecond precision. All we have to do is use gettimeofday and strftime on tv_sec and append tv_usec to the constructed string.
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
int main(void) {
struct timeval tmnow;
struct tm *tm;
char buf[30], usec_buf[6];
gettimeofday(&tmnow, NULL);
tm = localtime(&tmnow.tv_sec);
strftime(buf,30,"%Y:%m:%dT%H:%M:%S", tm);
strcat(buf,".");
sprintf(usec_buf,"%dZ",(int)tmnow.tv_usec);
strcat(buf,usec_buf);
printf("%s",buf);
return 0;
}
trick:
int time_len = 0, n;
struct tm *tm_info;
struct timeval tv;
gettimeofday(&tv, NULL);
tm_info = localtime(&tv.tv_sec);
time_len+=strftime(log_buff, sizeof log_buff, "%y%m%d %H:%M:%S", tm_info);
time_len+=snprintf(log_buff+time_len,sizeof log_buff-time_len,".%03ld ",tv.tv_usec/1000);
You could use strftime, but struct tm doesn't have resolution for parts of seconds. I'm not sure if that's absolutely required for your purposes.
struct tm tm;
/* Set tm to the correct time */
char s[20]; /* strlen("2009-08-10 18:17:54") + 1 */
strftime(s, 20, "%F %H:%M:%S", &tm);
None of the solutions on this page worked for me, I mixed them up and made them working with Windows and Visual Studio 2019, Here's How :
#include <Windows.h>
#include <time.h>
#include <chrono>
static int gettimeofday(struct timeval* tp, struct timezone* tzp) {
namespace sc = std::chrono;
sc::system_clock::duration d = sc::system_clock::now().time_since_epoch();
sc::seconds s = sc::duration_cast<sc::seconds>(d);
tp->tv_sec = s.count();
tp->tv_usec = sc::duration_cast<sc::microseconds>(d - s).count();
return 0;
}
static char* getFormattedTime() {
static char buffer[26];
// For Miliseconds
int millisec;
struct tm* tm_info;
struct timeval tv;
// For Time
time_t rawtime;
struct tm* timeinfo;
gettimeofday(&tv, NULL);
millisec = lrint(tv.tv_usec / 1000.0);
if (millisec >= 1000)
{
millisec -= 1000;
tv.tv_sec++;
}
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(buffer, 26, "%Y:%m:%d %H:%M:%S", timeinfo);
sprintf_s(buffer, 26, "%s.%03d", buffer, millisec);
return buffer;
}
Result :
2020:08:02 06:41:59.107
2020:08:02 06:41:59.196

Struct timeval to printable format

Could you please help me how to format a struct timeval instance to human readable format like "2010-01-01 15:35:10.0001"?
You need to manually append the microseconds part, since it's not in the struct tm that strftime() deals with. Here's a snippet:
struct timeval tv;
time_t nowtime;
struct tm *nowtm;
char tmbuf[64], buf[64];
gettimeofday(&tv, NULL);
nowtime = tv.tv_sec;
nowtm = localtime(&nowtime);
strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S", nowtm);
snprintf(buf, sizeof buf, "%s.%06ld", tmbuf, tv.tv_usec);
Note how we use explicit precision of 06 to get a zero-filled microseconds field. Since the microseconds go from 0 to 999,999, it must always be padded to 6 digits. We don't want to misrepresent e.g. 57 microseconds as 570,000 (compare "1.57" vs "1.000057").
Convert the tv_sec using localtime, and strftime, then append tv_usec part.
Combining previous answers and comments, changing the format to be RFC3339-compliant, and checking all of the error conditions, you get this:
#include <stdio.h>
#include <sys/time.h>
ssize_t format_timeval(struct timeval *tv, char *buf, size_t sz)
{
ssize_t written = -1;
struct tm *gm = gmtime(&tv->tv_sec);
if (gm)
{
written = (ssize_t)strftime(buf, sz, "%Y-%m-%dT%H:%M:%S", gm);
if ((written > 0) && ((size_t)written < sz))
{
int w = snprintf(buf+written, sz-(size_t)written, ".%06dZ", tv->tv_usec);
written = (w > 0) ? written + w : -1;
}
}
return written;
}
int main() {
struct timeval tv;
char buf[28];
if (gettimeofday(&tv, NULL) != 0) {
perror("gettimeofday");
return 1;
}
if (format_timeval(&tv, buf, sizeof(buf)) > 0) {
printf("%s\n", buf);
// sample output:
// 2015-05-09T04:18:42.514551Z
}
return 0;
}
ctime((const time_t *) &timeval.ts.tv_sec)
I think you are looking for this code, just for your reference.
You can use the strftime function to convert a date and time to a string.
Convert the tv_sec using localtime_s instead of localtime, because if you are writing a global function it may cause some problems.
if your function may work in a multi-threaded solution then please consider using localtime_r
This is what I use:
#include <time.h>
#include <string.h>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#define gmtime_r(ptime,ptm) (gmtime_s((ptm),(ptime)), (ptm))
#else
#include <sys/time.h>
#endif
#define ISO8601_LEN (sizeof "1970-01-01T23:59:59.123456Z")
char *timeval_to_str(char iso8601[restrict static ISO8601_LEN], unsigned precision, const struct timeval * restrict tv) {
struct tm tm;
if (!gmtime_r(&tv->tv_sec, &tm))
return memcpy(iso8601, "Error: Year overflow", sizeof "Error: Year overflow");
tm.tm_year %= 10*1000;
char *frac = iso8601 + strftime(iso8601, sizeof "1970-01-01T23:59:59.", "%Y-%m-%dT%H:%M:%SZ", &tm);
if (precision) {
unsigned long usecs = tv->tv_usec;
for (int i = precision; i < 6; i++) usecs /= 10;
char *spaces = frac + sprintf(frac - 1, ".%-*luZ", precision, usecs) - 3;
if (spaces > frac) while (*spaces == ' ') *spaces-- = '0';
}
return iso8601;
}
precision specifies the width of the seconds fraction. Code is y10k- and yINT_MAX-proof.

Resources