C code for date time format validation. specified format is "YYYYMMDDHHMMSSmmmmmm" - c

I need to validate a date-time value for "YYYYMMDDHHMMSSmmmmmm" format. Actually what I am hoping is I need to find out a already tested working C code to validate a date time value for above format.
Further, I have a date-time value like 201304011031000000. I need a function to verify whether this is a valid date or not.[isdatetime()]
Below are the each parts of formats.
YYYY : Year
MM : Month
DD : Day
HH : hour
MM : Minutes
SS : seconds
mmmmmm: micro-seconds

If you're on a POSIX system, this looks like something that should be handled with strptime(), but the 'milliseconds' (or microseconds) part is not handled by strptime() or any other standard conversion function I know of.
Assuming the question is asking for microseconds, you could use a variation on the theme provided by:
#include <stdio.h>
#include <string.h>
#include <time.h>
int main(void)
{
const char datetime[] = "20130417221633012345"; // YYYYMMDDHHMMSSFFFFFF
struct tm time_val;
unsigned microsecs;
const char *end = strptime(datetime, "%Y%m%d%H%M%S", &time_val);
if (end != 0)
{
int nbytes;
if (strlen(end) == 6 && sscanf(end, "%6u%n", &microsecs, &nbytes) == 1 &&
nbytes == 6)
{
char buffer[32];
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &time_val);
printf("%s = %s.%.6u\n", datetime, buffer, microsecs);
}
}
return 0;
}
Revised requirement
#include <stdio.h>
#include <string.h>
#include <time.h>
int isdatetime(const char *datetime)
{
// datetime format is YYYYMMDDHHMMSSFFFFFF
struct tm time_val;
unsigned microsecs;
int nbytes;
const char *end = strptime(datetime, "%Y%m%d%H%M%S", &time_val);
if (end != 0 && strlen(end) == 6 &&
sscanf(end, "%6u%n", &microsecs, &nbytes) == 1 && nbytes == 6)
return 1; // Valid
return 0; // Invalid
}

You can use regex.h for windows or for linux.
"YYYYMMDDHHMMSSMSSSSS" is something like: (\d{4}[0,1][0,9]\d{})... you can find your specific format here, it depends wether you enable 24 or 12 clock etc.

Related

How to use the date and time that i get from time.h function

Let's say the user is prompted for the date - e.g. Friday.
How can that string be used to correctly compare with another sting?
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t current_time;
struct tm * time_info;
char timeString[9];
time(&current_time);
time_info = localtime(&current_time);
strftime(timeString, sizeof(timeString), "%A", time_info);
printf("%s\n",timeString);
if (timeString == "Friday")
{printf("Weekday");
}
else
{printf("not weekday");
}
return 0;
}
The program keeps printing out not weekday.
Use strncmp() instead of comparing the string with ==:
if (strncmp(timeString,"Friday",7) == 0)
{printf("Weekday");
}
See this in action at tutorialspoint.com:
Friday
Currently, it is Thursday (for ~50% of the world) - so try this one:
Thursday

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;
}

Order of elements in strptime

I am trying to use strptime(buf, &pattern,&result) to convert char[] containing date into tm structure.
I am using function like this:
if(strptime(buf, &pattern,&result) == NULL)
{
printf("\nstrptime failed\n");
...
and everything works if my variables are defined like this:
char buf[] = "26/10/2011";
char pattern[] = "%d/%m/%y";
struct tm result;
but if I change them into:
char buf[] = "2011/26/10";
char pattern[] = "%y/%d/%m";
struct tm result;
I get "strptime failed". Notice, that I have only put year in the beginning (both in buf and pattern).
Help appreciated. My final target is to convert string in this format: 2011-10-26T08:39:21
It's because the lower case %y is for the two-digit year within the century. Try changing it to uppercase %Y and it will work okay. You can see this from the following program:
#include <stdio.h>
#include <time.h>
int main (void) {
char buf[] = "26/10/2011";
char pattern[] = "%d/%m/%y";
struct tm result;
if (strptime (buf, pattern, &result) == NULL) {
printf("strptime failed\n");
return -1;
}
printf ("%d\n", 1900 + result.tm_year);
return 0;
}
This outputs 2020, meaning that the year is being read as just the 20 portion of 2011, with the remainder being ignored. If you use upper-case %Y, it outputs the correct 2011 instead.
Code that generates the conversion error using the reversed format:
#include <stdio.h>
#include <time.h>
int main (void) {
char buf[] = "2011/10/26";
char pattern[] = "%y/%m/%d";
struct tm result;
if (strptime (buf, pattern, &result) == NULL) {
printf("strptime failed\n");
return -1;
}
printf ("%d\n", 1900 + result.tm_year);
return 0;
}
will work fine (ie, output 2011) when you change the pattern value to "%Y/%m/%d".
Using my own 'strptime' and 'timestamp' commands, I get:
$ strptime -T '%y/%d/%m' 2011/26/11
strptime: failed to convert <2011/26/11> using format <%y/%d/%m>
$ strptime -T '%Y/%d/%m' 2011/26/11
1322294400 = 2011/26/11
$ strptime -T '%d/%m/%y' 26/11/2011
1606377600 = 26/11/2011
$ timestamp 1322294400 1606377600
1322294400 = Sat Nov 26 00:00:00 2011
1606377600 = Thu Nov 26 00:00:00 2020
$
(Time zone here is US/Pacific, currently UTC-7.)
Note that the '%d/%m/%y' format generates a date in 2020, not in 2011.

Need Help Programming in C comparing times together

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;
}

Resources