Need Help Programming in C comparing times together - c

i need some advice and help with a plugin i am writing for Nagios.
i am writing the plugin in C, but have no previous experience in the language except for minor amounts whilst trying to get this plugin to work.
basically what i am trying to-do is the following.
read a text file that is generated on a remote PC by an application i have written, this program writes nothing more than 5 characters into the file, the first 4 chars are the time in 24 hour format. e.g. 22:30 > 10:30pm
it then needs to take these 4 characters convert them into a time and compare it to the current system time (if there is a difference of 5 mins then it generates a reply to nagios to flag a warning).
I have tried many different ways of doing this, my first attempt was to convert the characters into an integer, then convert the time into an integer and compare the difference .. failed at doing this.
my second attempt is to generate two Time Structs one with the current time in and the other with my "homemade" time in and compare them but this is not working either.
heres my code, no matter what i try the date from the file is always the same as the current system time, i know its something to-do with having to set the time at the top.
t_of_file = time(NULL);
time_from_file = localtime(&t_of_file);
but if i do not do this i get a segmentation fault.
heres the code.
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define COPYMODE 0644
int main(int argc, char *argv[])
{
struct tm *time_from_file;
struct tm *the_system_time;
time_t t_of_file;
time_t t_of_sys;
t_of_sys = time(NULL);
the_system_time = localtime(&t_of_sys);
t_of_file = time(NULL);
time_from_file = localtime(&t_of_file);
time_from_file->tm_year = the_system_time->tm_year;
time_from_file->tm_mon = the_system_time->tm_mon;
time_from_file->tm_mday = the_system_time->tm_mday;
time_from_file->tm_hour = 10; //should be read in from file
time_from_file->tm_min = 30; //should be read in from file
time_from_file->tm_sec = the_system_time->tm_sec;
time_from_file->tm_isdst = the_system_time->tm_isdst;
t_of_file = mktime(time_from_file);
printf("%s\n",ctime(&t_of_file));
t_of_sys = mktime(the_system_time);
printf("%s\n",ctime(&t_of_sys));
double difference = difftime(t_of_file, t_of_sys );
printf("%lf\n",(double)t_of_file);
printf("%lf\n",(double)t_of_sys);
if (difference >= 0.0) { //this should be 5 mins, not quite sure what to put here yet
// second is later than first
printf("later\n");
}
else if (difference < 0.0) {
// second is earlier than first
printf("earlier\n");
}
printf("%lf\n", difference);
return 0;//STATE_OK;
}
any help you can offer would be appreciated on this.
Following the answers i got, PACE's answer was spot on for what i wanted to-do and now i have a simpler bit of code that works perfectly for what i am trying to-do and is easier to under stand. below is the code in its modified form (it compiles perfectly on Linux btw).
#include <stdio.h>
#include <time.h>
int main ()
{
time_t filetime;
time_t presenttime;
struct tm * timeinfo;
time ( &filetime );
time ( &presenttime);
timeinfo = localtime ( &filetime );
timeinfo->tm_hour = 14; //this should be entered from file
timeinfo->tm_min = 15; //this should be entered from file
filetime = mktime ( timeinfo );
printf("my time %s\n",ctime(&filetime));
printf("pc time %s\n",ctime(&presenttime));
double difference = difftime(filetime, presenttime );
printf("%lf\n",(double)filetime);
printf("%lf\n",(double)presenttime);
if (difference > 300.0) {
// second is later than first
printf("later\n");
}
else if (difference < 0.0) {
// second is earlier than first
printf("earlier\n");
}
printf("%lf\n", difference);
return 0;
cheers for the help guys.

There is an example of making a time here. You can then compare the times with the difftime method.

If it were me, I'd be tempted to just save the result of time() to the file. That would save a whole lot of string parsing work on the other side.

I modified your code as follows and it does now what you were expecting:
struct tm time_from_file;
struct tm the_system_time;
time_t t_of_file;
time_t t_of_sys;
t_of_sys = time(NULL);
memcpy(&the_system_time,localtime(&t_of_sys),sizeof(struct tm));
t_of_file = time(NULL);
memcpy(&time_from_file,localtime(&t_of_sys),sizeof(struct tm));
time_from_file.tm_hour = 10; //should be read in from file
time_from_file.tm_min = 30; //should be read in from file
t_of_file = mktime(&time_from_file);
printf("%s\n",ctime(&t_of_file));
printf("%s\n",ctime(&t_of_sys));
double difference = difftime(t_of_file, t_of_sys );
printf("%lf\n",(double)t_of_file);
printf("%lf\n",(double)t_of_sys);
printf("%lf\n", difference);
What was wrong with your code:
You were using and modifying the pointer returned by localtime which happens to be same in both cases.
Consequently your pointers time_from_file and the_system_time were infact pointing to the same location.Any modification of one modifies the other as well and finally you have a difference of zero.
(Thanks gdb for helping me figure out that!!:D)

Paring your format is easy in C. Use this to read the time components from the file:
int hr, min;
fscanf (file, "%d:%d", &hr, &min);
Here is a complete solution:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
struct HrMin_ {
int hr;
int min;
};
typedef struct HrMin_ HrMin;
static const double TIME_DIFFERENCE = (double) (5 * 1000);
static HrMin read_time (FILE* file);
int
main (int argc, char **argv)
{
time_t sys_time_t = 0;
struct tm *sys_time = NULL;
struct tm *file_time = NULL;
double d = 0.0f;
if (argc != 2)
{
printf ("Usage: time_cmp <time_file>\n");
return 1;
}
time (&sys_time_t);
sys_time = localtime (&sys_time_t);
file_time = malloc (sizeof (struct tm));
file_time->tm_sec = sys_time->tm_sec;
file_time->tm_min = sys_time->tm_min;
file_time->tm_hour = sys_time->tm_hour;
file_time->tm_mday = sys_time->tm_mday;
file_time->tm_mon = sys_time->tm_mon;
file_time->tm_year = sys_time->tm_year;
file_time->tm_wday = sys_time->tm_wday;
file_time->tm_yday = sys_time->tm_yday;
file_time->tm_isdst = sys_time->tm_isdst;
FILE *file = fopen (argv[1], "r");
if (file == NULL)
{
printf ("Failed to open file: %s\n", argv[1]);
return 1;
}
HrMin hr_min = read_time (file);
fclose (file);
file_time->tm_hour = hr_min.hr;
file_time->tm_min = hr_min.min;
d = difftime (sys_time_t, mktime (file_time));
free (file_time);
if (d < 0) d *= -1;
printf ("Diff: %f\n", d);
if (d >= TIME_DIFFERENCE)
printf ("WARN!\n");
return 0;
}
static HrMin
read_time (FILE *file)
{
HrMin hr_min;
hr_min.hr = 0;
hr_min.min = 0;
fscanf (file, "%d:%d", &hr_min.hr, &hr_min.min);
return hr_min;
}

Related

C Get Date Sometimes Wrong By 1 Day

So finally after a lot of time googling I've been able to create a function that gets current date and convert it to string then write to buffer in C. But I noticed sometimes the day is off by 1? So for example today is may 4, but it may return may 5
Here is my code
void getCurrentDateTime(char * buffer)
{
time_t t = time(NULL);
struct tm *tm = localtime(&t);
char bufForOut[64] = { 0 };
strftime(bufForOut, sizeof(bufForOut), "%c", tm);
strcpy(buffer,bufForOut);
}
I call it like
char hi[64] = { 0 }
getCurrentDateTime(hi);
print(hi);

PaStreamCallbackTimeInfo members are all 0

From the PortAudio docs:
Stream Timing Information
When using the callback I/O method your stream callback function
receives timing information via a pointer to a
PaStreamCallbackTimeInfo structure. This structure contains the
current time along with the estimated hardware capture and playback
time of the first sample of the input and output buffers. All times
are measured in seconds relative to a Stream-specific clock. The
current Stream clock time can be retrieved using Pa_GetStreamTime().
So PaStreamCallbackTimeInfo::currentTime somehow indicates the current time and PaStreamCallbackTimeInfo::outputBufferDacTime should indicate the output time of the first sample in the current buffer. I don't know why but, on Linux, these values are all zero for me. Maybe I'm doing something wrong. Here's the code and the output:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include "portaudio.h"
#define PI 3.14159265359
#define SRATE 44100
#define FREQ 440
#define DURATION 5000
int
audio_callback(
const void* inbuf,
void* outbuf,
unsigned long bufsize,
const PaStreamCallbackTimeInfo* time_info,
PaStreamCallbackFlags status_flags,
void* user_data)
{
(void)inbuf;
(void)status_flags;
double* phase = (double*)user_data;
float* out = (float*)outbuf;
printf(
"current time = %f; out time = %f\n",
time_info->currentTime,
time_info->outputBufferDacTime);
for (unsigned long i = 0; i < bufsize; i++)
{
*phase += 2 * PI * FREQ / SRATE;
out[i] = sin(*phase);
}
return 0;
}
int
main(int argc, char** argv)
{
(void)argc;
(void)argv;
PaError pa_error;
PaStream* stream = NULL;
int error = 0;
double phase = 0;
pa_error = Pa_Initialize();
if (pa_error != paNoError)
{
return 1;
}
pa_error = Pa_OpenDefaultStream(
&stream,
0,
1,
paFloat32,
SRATE,
paFramesPerBufferUnspecified,
&audio_callback,
&phase);
if (pa_error != paNoError)
{
error = 1;
goto exit;
}
pa_error = Pa_StartStream(stream);
if (pa_error != paNoError)
{
error = 1;
goto exit;
}
Pa_Sleep(DURATION);
pa_error = Pa_CloseStream(stream);
if (pa_error != paNoError)
{
error = 1;
goto exit;
}
printf("Done.\n");
exit:
Pa_Terminate();
if (pa_error != paNoError)
{
printf("PortAudio error: %s\n", Pa_GetErrorText(pa_error));
}
return error;
}
Output:
current time = 0.000000; out time = 0.000000
current time = 0.000000; out time = 0.000000
current time = 0.000000; out time = 0.000000
current time = 0.000000; out time = 0.000000
...
Addendum: This same piece of code seems to work fine with Visual Studio in Windows 10.
Your example compiles fine on my Mac and returns meaningful time information so the issue is not in your code.
You haven't said which audio backend you're using on Linux, but if you're using ALSA and PulseAudio, there've been problems getting time info with those (see there for instance). In this specific case of ALSA/PulseAudio, Pulse is the one to blame and PortAudio has nothing to do with that.
If you're using a different audio backend, you might want to check the implementation of the GetStreamTime() function in the corresponding src/hostapi/<your_backend> PortAudio source folder.
As a side note, never make I/O operations in an audio callback in a real product. printf is a huge function which takes quite a lot of time to execute (from an audio callback point-of-view).

using gettimeofday() equivalents on windows

I'm trying to use 2 different equivalents for UNIX's gettimeofday() function on Windows, using Visual Studio 2013.
I took the first one from here. As the second one, I'm using the _ftime64_s function, as explained here.
They work, but not as I expected. I want to get different values when printing the seconds, or at least the milliseconds, but I get the same value for the printings with gettimeofday() (mytime1 & mytime2) and with _ftime64_s (mytime3 & mytime4).
However, it worth mentioning that the value of the milliseconds is indeed different between these two functions (that is, the milliseconds value of mytime1/mytime2 is different from mytime3/mytime4).
Here's my code:
#include <stdio.h>
#include <Windows.h>
#include <stdint.h>
#include <sys/timeb.h>
#include <time.h>
#define WIN32_LEAN_AND_MEAN
int gettimeofday(struct timeval * tp, struct timezone * tzp)
{
// Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
SYSTEMTIME system_time;
FILETIME file_time;
uint64_t time;
GetSystemTime(&system_time);
SystemTimeToFileTime(&system_time, &file_time);
time = ((uint64_t)file_time.dwLowDateTime);
time += ((uint64_t)file_time.dwHighDateTime) << 32;
tp->tv_sec = (long)((time - EPOCH) / 10000000L);
tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
return 0;
}
int main()
{
/* working with struct timeval and gettimeofday equivalent */
struct timeval mytime1;
struct timeval mytime2;
gettimeofday(&(mytime1), NULL);
gettimeofday(&(mytime2), NULL);
printf("Seconds: %d\n", (int)(mytime1.tv_sec));
printf("Milliseconds: %d\n", (int)(mytime1.tv_usec));
printf("Seconds: %d\n", (int)(mytime2.tv_sec));
printf("Milliseconds: %d\n", (int)(mytime2.tv_usec));
/* working with _ftime64_s */
struct _timeb mytime3;
struct _timeb mytime4;
_ftime64_s(&mytime3);
_ftime64_s(&mytime4);
printf("Seconds: %d\n", mytime3.time);
printf("Milliseconds: %d\n", mytime3.millitm);
printf("Seconds: %d\n", mytime4.time);
printf("Milliseconds: %d\n", mytime4.millitm);
return (0);
}
I tried other format specifiers (%f, %lu) and castings ((float), (double), (long), (size_t)), but it didn't matter. Suggestions will be welcomed.
QueryPerformanceCounter is used for accurate timing on windows. Usage can be as follows:
uint64_t microseconds()
{
LARGE_INTEGER fq, t;
QueryPerformanceFrequency(&fq);
QueryPerformanceCounter(&t);
return (1000000 * t.QuadPart) / fq.QuadPart;
}
This does not work with any EPOCH as far as I know. For that you need GetSystemTimePreciseAsFileTime which is only available on Windows 8 and higher.
uint64_t MyGetSystemTimePreciseAsFileTime()
{
HMODULE lib = LoadLibraryW(L"kernel32.dll");
if (!lib) return 0;
FARPROC fp = GetProcAddress(lib, "GetSystemTimePreciseAsFileTime");
ULARGE_INTEGER largeInt;
largeInt.QuadPart = 0;
if (fp)
{
T_GetSystemTimePreciseAsFileTime* pfn = (T_GetSystemTimePreciseAsFileTime*)fp;
FILETIME fileTime = { 0 };
pfn(&fileTime);
largeInt.HighPart = fileTime.dwHighDateTime;
largeInt.LowPart = fileTime.dwLowDateTime;
}
FreeLibrary(lib);
return largeInt.QuadPart;
}
int main()
{
uint64_t t1 = microseconds();
uint64_t t2 = microseconds();
printf("t1: %llu\n", t1);
printf("t2: %llu\n", t2);
return (0);
}

Time convert from a file and compare to the current time

I've asked something close to this before, but as it seems, the time I get from the file does not convert to the same type of time you get from localtime() and time().
Exactly what I want is:
I have a txt file with the following information
order.txt
file1.txt;5;15:40
file2.txt;7;15:41
file1.txt;10;16:00
My objective is to get the time in hour:min (15:40) and then, if it's the same as the currentTime, then I show the file1.txt content. Otherwise, if the currentTime is lower than the hour:min time (15:40), it waits untill it's 15:40 and shows the file1.txt content. If the currentTime is higher, then it ignores the first one and goes to the next one.
So for example, if the current time is 15:39, it will wait 1 minute and then show the file1.txt content.
If the current Time is 15:40, it shows the file1.txt content without waiting.
If the current Time is 15:41, it just goes to the next one (file2.txt) and checks again.
Used variables
FILE* orderFile;
FILE* contentFile;
FILE* defaultFile; (This will be used when this code works)
char fileName[50];
char textContent[5000];
int seconds;
int hour, min;
int diff_time;
char timeValue[50];
time_t current;
Includes
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
So for that I've tried the following code:
orderFile = fopen("order.txt","r");
defaultFile = fopen("default.txt","r");
while(fscanf(orderFile," %49[^;];%d; %49[^\n]",fileName,&seconds,timeValue)
{
sscanf(timeValue,"%d:%d",&hour,&min);
contentFile = fopen(fileName,"r");
if(contentFile != NULL)
{
fseek (contentFile, 0, SEEK_END);
size = ftell(contentFile);
rewind(contentFile);
if(size == 0)
{
printf("\nEmpty file. (Scanned file: %s)\n", fileName);
fclose(contentFile);
}
else
{
time_t now;
time(&now);
struct tm file_time_tm;
file_time_tm = *localtime(&now);
file_time_tm.tm_hour = hour;
file_time_tm.tm_min = min;
file_time_tm.tm_sec = 0;
file_time_tm.tm_isdst = -1;
time_t fileTime = mktime(&file_time_tm);
double diff_time = difftime(fileTime, now);
if(diff_time == 0)
{
while(fscanf(contentFile,"%[^\t]",textContent) == 1)
{
printf("%s\n", textContent);
}
sleep(seconds);
}
else
{
if(diff_time > 0)
{
while(fscanf(defaultFile,"%[^\t]",defaultContent) == 1)
{
printf("%s\n", defaultContent);
}
sleep(diff_time);
while(fscanf(contentFile,"%[^\t]",textContent) == 1)
{
printf("%s\n", textContent);
}
sleep(seconds);
}
}
fclose(defaultFile);
fclose(contentFile);
}
}
else
{
if(contentFile == NULL)
{
printf("\nFile does not exist. (Scanned file: %s)\n", fileName);
fclose(contentFile);
}
}
}
fclose(orderFile);
printf("\n");
So thanks to chux it is quite working now, yet not fully working.
If I have the following:
Current Time: 15:00
order.txt
file1.txt;5;15:01
file2.txt;6;15:02
file3.txt;3;15:03
When I run the program, the following will occur:
DEFAULT MESSAGE (text inside default.txt)
WAITS DIFF_TIME (CORRECTLY DONE)
SHOWS CONTENT FROM THE file1.txt
WAITS 5 SECONDS
X - SHOWS CONTENT FROM THE file2.txt (This is wrong, it should check again and if the time is 15:02 it will show, not 15:01. Which I assume it's because it is still reading as 15:01 on the timeValue and not 15:02, any idea why?)
WAITS UNTILL IT'S 15:02 (wrong)
SHOWS file3.txt (wrong)
WAITS UNTILL IT'S 15:03
ENDS (wrong as it should not end after waiting, it should end when file3.txt shows and waits for 3 seconds)
Output I need:
DEFAULT MESSAGE
waits diff_time
file1.txt content
waits 5 seconds
DEFAULT MESSAGE
waits diff_time
file2.txt content
waits 7 seconds
DEFAULT MESSAGE
waits diff_time
file3.txt content
waits 3 seconds
ENDS
It also does not work well if I have two files with the same time, such as this:
order.txt
file1.txt;5;15:01
file2.txt;6;15:01
file3.txt;3;15:02
It breaks it aswell.
Any idea of how to do this correctly?
As commented above by #M Oehm, it is apparent the compiler warnings are not fully enabled. Suggest enabling them - it will save you time.
A problem lies in the time compare and subtraction.
// Troublesome code
if(currentTime->tm_hour < hour && currentTime->tm_min < min) {
diff_time = difftime(currentTime,timeValue);
printf("%d - Or this?\n", diff_time);
sleep(diff_time);
}
The comparison is curious. Usually with such a comparison would be in the form
if (h1 < h2 || (h1 == h2 && m1 < m2))
difftime takes 2 time_t paramters, not char timeValue[50] and a struct tm.
The values passed to double difftime(time_t time1, time_t time0) appear backwards. The result it time1 - time0.
Recommend instead
int current_hm = currentTime->tm_hour * 60 + currentTime->tm_min;
int file_hm = hour * 60 + min;
if (current_hm < file_hm) {
unsigned diff_time = (file_hm - current_hm)*60u;
printf("%u - Or this?\n", diff_time);
sleep(diff_time);
}
[Edit]
Simplified approach.
time_t now;
time(&now);
struct tm file_time_tm;
file_time_tm = *localtime(&now);
file_time_tm.tm_hour = hour; // from file
file_time_tm.tm_min = min; // from file
file_time_tm.tm_sec = 0;
file_time_tm.tm_isdst = -1;
time_t filetime = mktime(&file_time_tm);
double diff = difftime(filetime, now); // filetime - now
if (diff > 0) {
sleep((unsigned) diff);
}
Chux's suggestion to do your comparisons with your own integer that represents the minutes after midnight is probably easier in your case, but if you want to use the standard time mechanisms, you can do it.
But first, keep in mind that there are two time representations, time_t, which is a "numerical" time that stores the seconds after the epoch and struct tm, which is the human-readable time that breaks a time down to years, months, days and so on.
With strptime, you can scan a string accoding to a format specification. It is the scanf for struct tm. This function does not initialise fields that are not specified, so that you can assign the current time with localtime and then overwrite only the hour and minute fields.
mktime converts a struct tm to a time_t, which you can pass to difftime.
The following code snipped shows how such a comparison might work:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main()
{
char stamp[] = "12:53";
char *p;
struct tm now;
time_t t = time(NULL);
now = *localtime(&t);
p = strptime(stamp, "%H:%M", &now);
if (p == NULL || *p != '\0') {
printf("Illegal date.\n");
} else {
char buf[20];
double dsec;
int dmin;
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M\n", &now);
puts(buf);
dsec = difftime(t, mktime(&now));
printf("Diff: %g sec\n", dsec);
dmin = (int) dsec / 60;
printf("Diff: %d min\n", dmin);
}
return 0;
}

Printing out current date

Implement a function that determines and prints out the current year, month and day. For example:
Today is 03/04/2014.
Code so far that I have:
#include <stdio.h>
#include <time.h>
int main ()
{
int days, weeks, months, years, option, rmd, currentyear, currentmonth;
int daysinjan, daysinfeb, daysinmarch;
time_t seconds;
seconds = time(NULL);
days = seconds/(60*60*24);
weeks = seconds/((60*60*24)*7);
rmd=seconds%31557600;
months = ((seconds/31557600) * 12)+(((float)rmd/31557600)*12);
years = days/(365.25);
currentyear = 1970 + years;
currentmonth = (((float)rmd/31557600)*12)+1;
printf("%ld/%ld", currentmonth,currentyear);
return 0;
}
Please do not mind all the useless stuff in the code, this question is part of a project and i simply used the code from my previous question to try and work with that code in order to solve this question. The problem i have is that i cannot print the current day of the month that it is, because of this i feel that i have gone about this question wrongly.
This uses standard library calls to do all the math for you.
From Here:
#include <time.h>
#include <stdio.h>
#define SIZE 256
int main (void)
{
char buffer[SIZE];
time_t curtime;
struct tm *loctime;
/* Get the current time. */
curtime = time (NULL);
/* Convert it to local time representation. */
loctime = localtime (&curtime);
/* Print out the date and time in the standard format. */
fputs (asctime (loctime), stdout);
/* Print it out in a nice format. */
strftime (buffer, SIZE, "Today is %A, %B %d.\n", loctime);
fputs (buffer, stdout);
strftime (buffer, SIZE, "The time is %I:%M %p.\n", loctime);
fputs (buffer, stdout);
return 0;
}
If you wanted to create this as a function to return a string, you could do it like this:
char * getTimeString (char *str)
{
//replace this comment with relevant code from above with (at least) two additional lines:
strcpy(str, buffer);
return str;
}
Call it like this:
int main(void)
{
char *timeStr;
timeStr = malloc(30);//sufficient length to accept values assigned in getTimeString()
printf("%s\n", getTimeString(timeStr);
free(timeStr);
return 0;
}
#include <time.h> // for time_t
#include <stdio.h> // for printf
int main () {
int days, weeks, months, years, option, rmd, currentyear, currentmonth;
int daysinjan, daysinfeb, daysinmarch;
time_t seconds;
seconds = time(NULL);
days = seconds/(60*60*24);
weeks = seconds/((60*60*24)*7);
rmd=seconds%31557600;
months = ((seconds/31557600) * 12)+(((float)rmd/31557600)*12);
years = days/(365.25);
currentyear = 1970 + years;
currentmonth = (((float)rmd/31557600)*12)+1;
printf("%ld/%ld", currentmonth,currentyear);
return 0;
}

Resources