I'm writing a function that, among other things, must print out an elapsed time counter. It receives by reference a start time _start, and compares it to current, both typed as time_t. I want to use strftime() to print out the observed time delta in ISO 8601 format. Here's what I attempted to do:
// Negative start time implies program has not begun
if (*_start > 0) {
time_t elapsed = current - *_start;
strftime(time_str, sizeof(time_str) - 1, "%T", localtime(&elapsed));
printf("%s\n", time_str);
}
And here is the output I get immediately after running the program
01:00:00
01:00:00
01:00:01
01:00:01
01:00:01
The seconds work fine, if I let it run longer they get incremented as expected, so do the minutes, however the hour starts as 01 as opposed to 00. Why is this happening? How can I get the hours to start zeroed, like the minutes?
time_t typically (see edit) stores absolute timestamps (the number of seconds since midnight UTC, January 1, 1970). By calculating current - *_start, you're getting elapsed time in seconds (as desired), but by then passing that to localtime and strftime, you're telling the computer to take the time elapsed since the start of your program and treat it as the time elapsed since midnight UTC 1-1-1970.
I'm guessing that happens to be 01:00:00 in your system's local time zone.
I'm not aware of a C99 function to print elapsed time, but it's not hard to write one yourself.
void format_elapsed_time(char *time_str, int total_seconds_elapsed) {
int hours_elapsed = total_seconds_elapsed / 3600;
int minutes_elapsed = (total_seconds_elapsed % 3600) / 60;
int seconds_elapsed = total_seconds_elapsed % 60;
sprintf(time_str, "%02i:%02i:%02i", hours_elapsed, minutes_elapsed, seconds_elapsed);
}
Edit: As #chux points out, time_t doesn't have to store timestamps as seconds since 1-1-1970. See this answer for details.
To portably find the number of elapsed seconds between 2 time_t, use difftime() as subtracting 2 time_t values is not specified in C to be a difference in seconds.
double difftime(time_t time1, time_t time0); C11dr ยง7.26.2.2
The difftime function returns the difference expressed in seconds as a double.
double elapsed_seconds = difftime(current, *_start);
printf("elapsed_seconds: %f\n", elapsed_seconds);
If you want to use this method, you should be aware that time() returns UTC. If you then subtract that from your local time (as returned by localtime()), time zones will have an effect on the result (it's likely your particular time zone is removed from UTC by one hour).
Consider the following complete program, similar to your snippet:
#include <stdio.h>
#include <time.h>
#include <unistd.h>
int main(void) {
time_t start = time(0);
char time_str[100];
for (int i = 5; i > 0; i--) {
sleep (1);
time_t elapsed = time(0) - start;
strftime(time_str, sizeof(time_str) - 1, "%T", localtime(&elapsed));
printf("%s\n", time_str);
}
return 0;
}
Also consider that my particular time zone is removed from UTC by eight hours:
pax> date ; date -u
Thursday 30 March 10:25:57 AWST 2017
Thursday 30 March 02:25:57 UTC 2017
When I run it, I see:
08:00:01
08:00:02
08:00:03
08:00:04
08:00:05
You can see there that the eight-hour time difference from UTC affects the value. The fix for that is actually quite simple: don't use local time at all. If you replace the localtime() call with gmtime(), you get the output you expect:
00:00:01
00:00:02
00:00:03
00:00:04
00:00:05
I realize this question already has an answer, but I thought I might shift the focus a little and expand on the accepted answer. Since the OP specified that they are dealing with elapsed times, one can avoid dealing with absolute timestamps altogether using the clock() function.
clock_t start = clock();
.
.
clock_t end = clock();
double elapsed = (end - start) / (double)CLOCKS_PER_SEC;
then you can call the notionally revised format_elapsed_time() function, like so:
void format_elapsed_time(char *time_str, double elapsed) {
int h, m, s, ms;
h = m = s = ms = 0;
ms = elapsed * 1000; // promote the fractional part to milliseconds
h = ms / 3600000;
ms -= (h * 3600000);
m = ms / 60000;
ms -= (m * 60000);
s = ms / 1000;
ms -= (s * 1000);
sprintf(time_str, "%02i:%02i:%02i.%03i", h, m, s, ms);
}
Related
I need to be able to count the seconds between now and a specific time (like the next time it's 3pm). I saw some similar questions but I wasn't able to use any of these.
C standard library has two representation of time: time_t is a seconds since Unix Epoch and struct tm where you can individially set seconds, minutes, etc.
So to get next moment in time when wall clock will show 3 p.m. you'll need take current time in seconds time(NULL), convert it to struct tm, advance time to 3 p.m. by setting structure fields, convert it back to time_t and calculate the difference:
#include <time.h>
#include <string.h>
#include <stdio.h>
int main() {
time_t now, next3pm;
struct tm threepm;
// Get current time (now)
now = time(NULL);
// Copy current date to a `threepm`, and set time
memcpy(&threepm, gmtime(&now), sizeof(struct tm));
if(threepm.tm_hour > 15) {
// Advance to a next day
++threepm.tm_mday;
}
threepm.tm_hour = 15;
threepm.tm_min = threepm.tm_sec = 0;
printf("%.f seconds till 3:00 PM\n", difftime(mktime(&threepm), now));
return 0;
}
I used UTC conversion functions gmtime()/mktime(). Since there is no timezoned version of mktime() you may need to convert time on your own. Using UTC time may cause trouble with advancing to a next day when it shouldn't do that (because it is already 15:00 according to UTC, but not yet 15:00 according to a local time).
Or, a classic joke version:
int main() {
time_t t;
struct tm* tm;
do {
t = time(NULL);
tm = gmtime(&t);
usleep(1000000);
} while(tm->tm_hour != 15 && tm->tm_min != 0);
puts("0 seconds till 3:00 PM");
}
Is there any way of converting milliseconds to date in C?
What I am trying to do is write a small application in C that can return the financial year and the like(quarter, week) given the start month and isCurentYear bool, where the input might be milliseconds or a date!
In the first place, is there any way by which this can be achieved in C?
And if so, in the process of finding out a way of converting milliseconds to date
I have found out that the use of time_t takes the current millis of our system and by creating a structure pointing to it,it permits us to extract the year,month, date, sec etc!
Refer the below code:
#include <sys/time.h>
#include<stdio.h>
#include<time.h>
void main()
{
time_t t = time(000);
//time_t t = time(0);
struct tm tm = *localtime(&t);
printf("now: %d-%d-%d %d:%d:%d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
}
And also, can time_t be used to store millisecond values so that it can be converted to date using tm struct?
Function time_t time(time_t* timer) returns the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC. In addition, if the input argument timer != NULL, then the function also sets this argument to the same value (so you probably have no reason to call it with anything else but NULL).
Function struct tm* localtime(const time_t* timer) takes the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC, and returns a structure that represents the equivalent time & date. If you're working on a multi-threaded application, then please note that this function is not thread safe.
As to your question - is there any way for converting milliseconds to time & date - yes, but:
Take into consideration that the milliseconds will be considered as of 00:00 hours, Jan 1, 1970 UTC.
Since the time_t type is 32-bit long, you will not be able to convert 4G*1000 milliseconds or more.
Here is a function for converting milliseconds to time & date:
struct tm* GetTimeAndDate(unsigned long long milliseconds)
{
time_t seconds = (time_t)(milliseconds/1000);
if ((unsigned long long)seconds*1000 == milliseconds)
return localtime(&seconds);
return NULL; // milliseconds >= 4G*1000
}
For those of us who were searching the web for an answer to apply to embedded c applications, think pic 32 programming here is the mathematical calculation:
Date in Epoch_seconds = ( (epoch_seconds / 1000) / 86400 ) + 25569
Resulting in a 5 digit answer which is 10 bits long format dd/MM/yyyy
(Note: the slashes are encoded in the result here so when converting to human readable date please account for it)
Where one day = 86400 ms
and the date 1970/1/1 = 25569
example:=( (1510827144853/1000) / 86400 ) + 25569 = 43055
put 43055 in excel and format cell to date dd/MM/yyyy and it gives you 16/11/2017
Perhaps, you are looking for strftime function.
char text[100];
time_t now = time(NULL);
struct tm *t = localtime(&now);
strftime(text, sizeof(text)-1, "%d %m %Y %H:%M", t);
printf("Current Date: %s", text);
I'm relatively new to C programming and I'm working on a project which needs to be very time accurate; therefore I tried to write something to create a timestamp with milliseconds precision.
It seems to work but my question is whether this way is the right way, or is there a much easier way? Here is my code:
#include<stdio.h>
#include<time.h>
void wait(int milliseconds)
{
clock_t start = clock();
while(1) if(clock() - start >= milliseconds) break;
}
int main()
{
time_t now;
clock_t milli;
int waitMillSec = 2800, seconds, milliseconds = 0;
struct tm * ptm;
now = time(NULL);
ptm = gmtime ( &now );
printf("time before: %d:%d:%d:%d\n",ptm->tm_hour,ptm->tm_min,ptm->tm_sec, milliseconds );
/* wait until next full second */
while(now == time(NULL));
milli = clock();
/* DO SOMETHING HERE */
/* for testing wait a user define period */
wait(waitMillSec);
milli = clock() - milli;
/*create timestamp with milliseconds precision */
seconds = milli/CLOCKS_PER_SEC;
milliseconds = milli%CLOCKS_PER_SEC;
now = now + seconds;
ptm = gmtime( &now );
printf("time after: %d:%d:%d:%d\n",ptm->tm_hour,ptm->tm_min,ptm->tm_sec, milliseconds );
return 0;
}
The following code seems likely to provide millisecond granularity:
#include <windows.h>
#include <stdio.h>
int main(void) {
SYSTEMTIME t;
GetSystemTime(&t); // or GetLocalTime(&t)
printf("The system time is: %02d:%02d:%02d.%03d\n",
t.wHour, t.wMinute, t.wSecond, t.wMilliseconds);
return 0;
}
This is based on http://msdn.microsoft.com/en-us/library/windows/desktop/ms724950%28v=vs.85%29.aspx. The above code snippet was tested with CYGWIN on Windows 7.
For Windows 8, there is GetSystemTimePreciseAsFileTime, which "retrieves the current system date and time with the highest possible level of precision (<1us)."
Your original approach would probably be ok 99.99% of the time (ignoring one minor bug, described below). Your approach is:
Wait for the next second to start, by repeatedly calling time() until the value changes.
Save that value from time().
Save the value from clock().
Calculate all subsequent times using the current value of clock() and the two saved values.
Your minor bug was that you had the first two steps reversed.
But even with this fixed, this is not guaranteed to work 100%, because there is no atomicity. Two problems:
Your code loops time() until you are into the next second. But how far are you into it? It could be 1/2 a second, or even several seconds (e.g. if you are running a debugger with a breakpoint).
Then you call clock(). But this saved value has to 'match' the saved value of time(). If these two calls are almost instantaneous, as they usually are, then this is fine. But Windows (and Linux) time-slice, and so there is no guarantee.
Another issue is the granularity of clock. If CLOCKS_PER_SEC is 1000, as seems to be the case on your system, then of course the best you can do is 1 msec. But it can be worse than that: on Unix systems it is typically 15 msecs. You could improve this by replacing clock with QueryPerformanceCounter(), as in the answer to timespec equivalent for windows, but this may be otiose, given the first two problems.
Clock periods are not at all guaranteed to be in milliseconds. You need to explicitly convert the output of clock() to milliseconds.
t1 = clock();
// do something
t2 = clock();
long millis = (t2 - t1) * (1000.0 / CLOCKS_PER_SEC);
Since you are on Windows, why don't you just use Sleep()?
Using nothing but the C standard library (plain ISO C, no POSIX, and thus no assumption that time_t is represented in "seconds since the epoch"), what is the simplest way to get a time_t value corresponding to 01 Jan 1970 00:00:00 UTC?
The UTC part is the key; otherwise, just using mktime on a properly initialized struct tm would trivially solve the problem.
Alternatively (this is actually the "point" of the question), how does one portably determine the number of POSIX seconds between a given time_t value, e.g. the current time obtained via time(0), and the epoch? By "POSIX seconds" I mean the definition used in POSIX's "Seconds Since the Epoch" which does not use leap seconds. If this sounds too complicated, just go back to the question as originally stated in the first paragraph and assume the epoch is representable in time_t.
Here's an entry for a way to do it, "simplest" if nobody beats it:
call mktime on a struct tm for 02 Jan 1970 00:00:00
call mktime on a struct tm for 31 Dec 1969 00:00:00. This could reasonably return -1, in which case treat it as 0.
Binary search between the two for a value of time_t that, when passed to gmtime, results in 01 Jan 1970 00:00:00
Assumes that no local time is ever more than 24 hours different from UTC, which I'm pretty sure is a fact. We could widen the boundaries if necessary, in extremis we could search between 0 and time(0).
The binary search could be improved on, for example by interpolation. But who knows, maybe some crazy time zone (or broken tzinfo data) could cause a daylight savings change in December/January. I doubt that happened for any real time zone. But it's not forbidden by the C standard, only by common sense.
If it wasn't for that, I think we could calculate based on gmtime(mktime(01 Jan)) (to get the time zone) and a comparison of 01 Jan 1970 00:00:00 vs 01 Jan 1970 00:00:01 (to get the precision of time_t).
Your problem is rather fundamental: ISO C punts on time zones almost entirely, simply providing mktime() and the localtime() and gmtime() conversions, with a hook for daylight savings. (They implement, you decide.)
So there seems like only two things you can do:
assume that time_t is seconds-since-epoch UTC and use gmtime() to verify that, and panic or alert if it ever fails; or
rely on a more comprehensive standard than ISO C
Step 1: Choose any time_t (the current time will work just fine) as a reference point; call it t0.
Step 2: Call gmtime on t0 and compute the difference between the result and the epoch in a broken-down struct tm form.
Step 3: Call localtime on t0 and apply the broken-down difference from step 2 to the resulting struct tm. Then call mktime on it to get back a time_t.
The result should be a time_t representing the epoch.
My first attempt to implement this had problems when the local time offsets are not constant over time, for example in localities where daylight time has been added or abandoned or which switched from observing one zone to another. This seems to be because the data in the struct tm on which the time zone information is based gets changed. Here is the original implementation, with its problems:
time_t get_epoch(time_t t0)
{
struct tm gmt = *gmtime(&t0);
struct tm tmp = *localtime(&t0);
tmp.tm_sec -= gmt.tm_sec;
tmp.tm_min -= gmt.tm_min;
tmp.tm_hour -= gmt.tm_hour;
tmp.tm_mday -= gmt.tm_mday-1;
tmp.tm_mon -= gmt.tm_mon;
tmp.tm_year -= gmt.tm_year-70;
return mktime(&tmp);
}
and an improved version, where posix_time is a function to compute the seconds since the epoch for a given struct tm using the POSIX formulae (http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_15), with additional work to handle years before 1970, etc. if needed:
time_t get_epoch(time_t t0)
{
struct tm gmt = *gmtime(&t0);
struct tm tmp = *localtime(&t0);
long long offset = posix_time(&gmt);
while (offset > INT_MAX) {
offset -= INT_MAX;
tmp.tm_sec -= INT_MAX;
mktime(&tmp);
}
while (offset < -INT_MAX+61) {
offset -= -INT_MAX+61;
tmp.tm_sec -= -INT_MAX+61;
mktime(&tmp);
}
tmp.tm_sec -= offset;
return mktime(&tmp);
}
For C89 compatibility, long long would have to be dropped and the number of mktime calls needed increases dramatically; offset could not be computed as a single value, but a loop would be needed to call mktime multiple times per year.
Edit: Perhaps the following implementation of the non-standard timegm would meet the non-POSIX requirements of the question:
#include <stdio.h>
#include <string.h>
#include <time.h>
time_t my_timegm(struct tm *tm) {
time_t t, g;
double dt; // seconds
struct tm *gm;
t = mktime(tm);
gm = gmtime(&t);
gm->tm_isdst = 0;
g = mktime(gm);
dt = difftime(t, g);
if (dt >= 0) {
tm->tm_sec += fmod(dt, 60); // needed to handle 16-bit ints
tm->tm_min += dt / 60;
}
else {
tm->tm_sec -= fmod(-dt, 60);
tm->tm_min -= -dt / 60;
}
return mktime(tm);
}
int main(void) { // prints time_t for 01 Jan 1970 00:00:00 UTC
struct tm start;
memset(&start, 0, sizeof start);
start.tm_year = 70; // = 1970
start.tm_mday = 1; // = 1st
printf("%ld\n" my_timegm(&start)); // gives 0 on any POSIX system
return 0;
}
This assumes mktime will, as per the Linux man page, act so that structure members .. outside their valid interval ... will be normalized, or at least ensure something sensible is returned. I don't know whether plain ISO C guarantees this.
My initial version of my_timegm was from http://lists.samba.org/archive/samba-technical/2002-November/025571.html, and is credited there to Beeman, Baushke, Sabol, and Zawinski:
time_t my_timegm(struct tm *tm) {
time_t t, g;
struct tm *gm;
t = mktime(tm);
if (t == -1) { // perhaps needed for DST changeover?
tm->tm_hour--;
if ((t = mktime(tm)) != -1)
t += 3600;
}
gm = gmtime(&t);
gm->tm_isdst = 0;
g = mktime(gm);
if (g == -1) {
gm->tm_hour--;
if ((g = mktime(gm)) != -1)
g += 3600;
}
return (t == -1 || g == -1) ? -1 : t - (g - t); // or difftime
}
I'm still thinking about the need for the code: tm->tm_hour--, etc.
My previous approach had too many problems stemming from ambiguity about how mktime resolves denormalized time representations for me to be comfortable with it, so I'm going to try merging the idea with Steve Jessop's guessing/search idea for a better approach:
Initialize a struct tm object tm0 to the calendar time of the epoch.
Call mktime on tm0. This will result in its being interpreted as local time, however, so the result will not be the desired answer. Call this time_t value t0.
Apply gmtime to t0 to convert it to a broken-down universal time. It should differ from the desired epoch by less than 24 hours (actually, at most 12).
Adjust tm0 by the difference and return to step 2. If step 3 gives the right broken-down universal time epoch, we are finished. Otherwise, repeat steps 2-4 (should not be necessary).
In code,
time_t get_epoch()
{
struct tm tm0 = { .tm_year = 70, .tm_mday = 1 }, gmt;
time_t t0;
for (;;) {
t0 = mktime(&tm0);
gmt = *gmtime(&t0);
if (!gmt.tm_sec && !gmt.tm_min && !gmt.tm_hour &&
!gmt.tm_yday && gmt.tm_year==70) return t0;
tm0.tm_sec -= gmt.tm_sec;
tm0.tm_min -= gmt.tm_min;
tm0.tm_hour -= gmt.tm_hour;
tm0.tm_mday -= gmt.tm_mday-1;
tm0.tm_mon -= gmt.tm_mon;
tm0.tm_year -= gmt.tm_year-70;
}
}
I was wondering whether there is a function in C that takes time in the following format (current date and time in seconds are in Epoch format)
a.1343323725
b.1343326383
And returns me the result as difference between the two time as hrs:mins:secs
Sorry for any confusion, to clarify my point I wrote a code that gets that gets the user's current time execute some block of code and gets the time again. And I was wondering whether the difference could be converted into hrs:mins:sec as a string literal.
#include <sys/time.h>
#include <stdio.h>
int main(void)
{
struct timeval tv = {0};
gettimeofday(&tv, NULL);
printf("%ld \n", tv.tv_sec);
//Execte some code
gettimeofday(&tv, NULL);
return 0;
}
First you want to get the time difference in seconds out of the timeval structures that those functions return, using something like this:
int diff = a.tv_sec-b.tv_sec;
Where a and b were the values returned by gettimeofday.
Next you want to break that down into units of hours, minutes and seconds.
int hours=diff/3600;
int minutes=(diff/60)%60;
int seconds=diff%60;
Finally we want to get that data into a string, using the snprintf function from
#include <stdio.h>
char output[10];
snprintf(output, 10, "%d:%d:%d", hours, minutes, seconds);
sprintf words exactly like printf, except the output goes into a string, not onto stdout, and snprintf is the same except it won't write more than n characters into the string, to prevent buffer overflows.
Stitch those together and you've got the job done.
unsigned diff = b-a;
printf("%u:%u:%u", diff/3600, (diff % 3600)/60, diff % 60);
diff / 3600 is hours.
(diff % 3600) / 60 is remainder minutes
(diff % 3600) % 60 equal to diff % 60 is remainder seconds
Limitation: this code don't work for diffs greater than about 136 years.
Note: It is bad idea to use gettimeofday for the performance meter. The best function to use is clock_gettime with CLOCK_MONOTONIC clock id (It is not affected by wall-clock time change). But beware CLOCK_MONOTONIC don't work in Linux kernels before 2.6. Check clock availability before use.