How to format system time in C? - c

I'm working on an element of a program that fetches the system time in (24 hour time) hours and minutes, and formats it as HH:MM and stores it in an array. The minutes also have to be incremented by 1. This is my code:
strftime (timeh,10,"%H:",formtime);
strftime (timem,10,"%M",formtime);
timem1 = atoi(timem);
++timem1;
itoa(timem1, timem, 10);
strcpy(time, timeh);
strcat(time, timem);
I tested it by simply having it print out time, and this was the output of printf("%s", time):
5. (the time was 1:04 AM)
Individually, the hours print as nothing (at 1:08 AM), and the minutes print correctly.
What can I do to make the array time hold the properly formatted HH:MM time?
Thanks for all your suggestions

If I read you question right, you should be able to do it with:
formtime->tm_min++; /* Additional checks needed. */
strftime(time, 10, "%H:%M", formtime);

Rather than trying to adjust the minutes directly and having to worry about wrapping at the hour, you should adjust the time by 60 seconds before splitting it into a struct tm for formatting:
time_t now;
time(&now);
now += 60;
strftime(buffer, sizeof(buffer), "%H:%M", localtime(&now));
Note that calling your array time is not a good idea, as that will conflict with the standard function time used to get the current time.

Related

How to print a future time from system time in C. Such as if it is 10 am now, to print 12 am instead

I am currently learning C programming and i am trying to out put a time for the next scheduled flight of a mock airport. i though i could use the system time, then have that be modified so it out puts which ever time is 3 hours from that moment. However, i could only find solutions to out put the current time on the system. Any help would be appreciated.
I've tried a few different methods I've seen others do, but have had no luck in modifying them as of yet. I am still very new to C programming, so i cant read many of these functions, and due to that cannot find where in them to edit or change out in order to achieve the desired result.
#include<stdio.h>
#include<time.h>
int main(){
time_t t;
time(&t);
printf("\n right now the time is: %s",ctime(&t));
}
this outputs to "Mon Aug 12 10:00:17 2019"
my end goal is something similar to "12:00 pm" if the current time is 10 am
In t the seconds since the unix epoch (1970-01-01 00:00 UTC) is stored.
So you can simply add 3h = 3600*3 = 10800 to it:
time_t t;
time(&t);
t += 10800;
printf("\n In 3 hours the time is: %s",ctime(&t));
Since flights are every 3 hours, I take be modified so it out puts which ever time is 3 hours from that moment. to mean up to 3 hours from the current moment.
If so,
1) Avoid making the non-portable assumption the time_t is in seconds.
2) Convert to local time, do the math on the .tm_hour member.
time_t t;
if (time(&t) == -1) Handle_invalid_time();
printf("Right now the time is: %s",ctime(&t));
struct tm *tm = localtime(&t);
if (tm == NULL) Handle_invalid_conversion();
tm->tm_hour += 3;
tm->tm_min = 0;
tm->tm_sec = 0;
// re-adjust members to their usual range (Handle going into next, day, month, year)
mktime(tm);
printf("Flight time: %s", asctime(tm));

time(time_t *timer) gives wrong results without time drift in system

below code is for doing some stuff and sleep till next interval.
for calculation of sleep time, I am using below logic.
time_t start = time(0);
time_t end = time(0);
int timeLeft = 0;
int interval = 300;
while(1)
{
/* do something
* lets say takes 5 to 20 seconds to execute
*/
end = time(0);
timeLeft = interval -(end - start);
printf("timeLeft: %d, interval: %d, end: %u, start: %u",timeLeft,interval,end,start);
sleep(timeLeft)
start = time(0);
}
After an uptime of 34 hours of the system, timeLeft is coming as greater than 300, which should never happen.
I have checked, there is no time drift in the system.
for an instance, when the issue happened,
timeLeft: 11484, interval: 300, end: 1549402241, start: 1549413425
Don't know how can above happen?
need help.
This analysis of the issue doesn't actually give a single answer, but it was too long to fit in a comment so here goes.
After looking at your code, it appears that the problem is that end < start. But end = time(0) is always called after start = time(0).
Your example assumes that you can subtract time_t values and get the elapsed seconds between them, but the C standard does not guarantee that. Your code seems to be running on a recent version of Linux so I took a look at the GNU Libc manual, and apparently time returns the number of secs since 00:00:00 on January 1, 1970, and a time_t is a long int. I also checked the values of start and end, when the issue occurred, and their values are about 49 years worth of secs, and since it been 49 years since January 1, 1970, it appears that the assumption in your example is valid.
My best guess is that there is some significant difference between the actual code and your example. Perhaps a call to start = time(0) that takes place after the call to end=time(0), or maybe situations where a call to end=time(0) does not take place.
You can rule this out by converting your example into an actual program and see if that program has the same issue. If it does, you can post the code for the program. This site encourages people to create Minimal, Complete, and Verifiable examples.
In the meantime, I can make some other guesses:
Your program has more than one thread, and your threads are stepping on each other.
Some weird compiler optimization is causing the calls to time(0) to be moved around.

Getting Duration

I'm trying to measure duration of something.
when it start I call start_time = time(NULL);
when it ends:
time_t a_time = time(NULL) - start_time;
struct tm * ts = localtime(&a_time);
char time_buff[32];
memset (time_buff,0,32);
sprintf (time_buff, "Duration: %02d:%02d:%02d", ts->tm_hour, ts->tm_min, ts->tm_sec);
The problem is that ts->tm_hour is always 2.
Please advise.
Thanks,
Nahum
The function localtime converts the time to a complete date and time. You better convert it to days, hours and minutes yourself though divisions and modulo operations.
do you eventualy live in a country where the time is 2 hours away from UTC time ?
replace your call to localtime() (which is in your current timezone) by a call to gmtime().
Why not use a function that returns the amount of milliseconds elapsed (clock or gettimeofday) and then convert to hour/min/sec?

a time function in C linux

hi i was wondering if it is possible to edit the time function.for my program to give a time for a user to retry again?
struct tm * abc()
{
char *time_string;
time_t curtime;
struct tm *loctime;
/* Get the current time. */
curtime = time (NULL);
/* Convert it to local time representation. */
loctime = localtime (&curtime);
return loctime;
}
this will return the current time but want i want to do is to edit this to add a value. The reason for me doing this is so i can tell a user to try again at a certain time using the current and adding 2minutes to it. Not sure if this is the correct way?
Thanks
time() returns a timestamp in seconds (number of seconds since the epoch), so you can just add the required delay.
curtime = time (NULL) + 2*60; // Adds two minutes,
Add the following lines just before the return.
localtime->tm_min += 2;
mktime(localtime);
The first line adds two minutes to localtime.
The second line renormalizes localtime to a "standard" format, in other words you it will roll the added minutes from values like (61) to values like (hours+1),(minutes = 1).

How to get current hour (time of day) in linux kernel space

I'm writing a kernel module that checks to see if the time is between two specified hours, and disables input if it is. This has to do with me wanting to make sure I go to bed early. (I know I could also use any number of different techniques including cron etc, but I wanted to learn kernel programming...)
As a first version, I therefore check if the current hour is between start and end, which are set via parameters to the module.
My question is therefore : How do I get the current hour? I have no access to the usual time functions in the standard library because I am in kernel space. I'm guessing that I should be using do_gettimeofday() for this, but that only gives me seconds and nanoseconds, and I need hours in the current day.
Thanks.
time_to_tm function can be of your help, which returns the structure tm. Timezone available in variable sys_tz, it can help you to set your offset properly to get local time.
To get the local time in kernel, add the below code snippet your kernel driver:
struct timeval time;
unsigned long local_time;
do_gettimeofday(&time);
local_time = (u32)(time.tv_sec - (sys_tz.tz_minuteswest * 60));
rtc_time_to_tm(local_time, &tm);
printk(" # (%04d-%02d-%02d %02d:%02d:%02d)\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
This works well for me:
#include <linux/time.h>
...
/* getnstimeofday - Returns the time of day in a timespec */
void getnstimeofday(struct timespec *ts)
For getting usual time format you can use:
printk("TIME: %.2lu:%.2lu:%.2lu:%.6lu \r\n",
(curr_tm.tv_sec / 3600) % (24),
(curr_tm.tv_sec / 60) % (60),
curr_tm.tv_sec % 60,
curr_tm.tv_nsec / 1000);
Converting the do_gettimeofday result to an hour is pretty simple, since it starts at midnight GMT.
time_t t = time(0);
time_t SecondsOfDay = t % (24*60*60);
time_t HourGMT = SecondsOfDay / (60*60);
Then adjust for your local timezone
We can use clock_gettime function with CLOCK_REALTIME as the type of clock.
Reference http://linux.die.net/man/3/clock_gettime
Just doing a strace on date executable gives us an idea to get the current date in the kernel mode.

Resources