Reputation: 13
I have a function to add any minutes to a date time in C using struct tm and maketime. the function takes in date time in string and minutes in integer then add the minutes to the date time then return a string.
char *addMinutes(char *dateTime, int mins)
{
/* Intput & Output: YYYYMMDDHHMM */
char year[5];
char month[3];
char day[3];
char HH[3];
char MM[3];
char newDateTime[13];
struct tm t;
STRMCPY(year, dateTime, 4);
STRMCPY(month, &dateTime[4], 2);
STRMCPY(day, &dateTime[6], 2);
STRMCPY(HH, &dateTime[8], 2);
STRMCPY(MM, &dateTime[10],2);
printf("input %s %s %s %s %s\n",year,month,day,HH,MM);
t.tm_year = atoi(year);
t.tm_mon = atoi(month)-1;
t.tm_mday = atoi(day);
t.tm_hour = atoi(HH);
t.tm_min = atoi(MM)+mins;
printf("input %d %d %d %d %d\n",t.tm_year,t.tm_mon,t.tm_mday,t.tm_hour,t.tm_min);
mktime(&t);
printf("input %d %d %d %d %d\n",t.tm_year,t.tm_mon,t.tm_mday,t.tm_hour,t.tm_min);
sprintf(newDateTime, "%04d%02d%02d%02d%02d", t.tm_year, t.tm_mon,
t.tm_mday,t.tm_hour,t.tm_min);
return newDateTime;
}
Below is my result if i call above function strcpy(atb30, addMinutes("201812120431",30));
input 2018 12 12 04 31
input 2018 11 12 4 61
input 2018 11 12 5 41
atb 201811120541
I don't understand why my program is not working. And what's the correct way to write a addMinutes function using C.
Upvotes: 1
Views: 2073
Reputation: 153338
Many issues
Wrong epoch
The .tm_year
member is from 1900. @paddy
// t.tm_year = atoi(year);
t.tm_year = atoi(year) - 1900;
Check for success
// mktime(&t);
if (mktime(&t) == -1) {
puts("Failed conversion");
exit(EXIT_FAILURE);
}
Incomplete assignment
OP's code does not assign the other members of t
, leading to questionable result. Instead, completely assign t
and use -1
for the .tm_isdst
if you do not know the daylight setting for the date.
// struct tm t;
struct tm t = { 0 };
t.tm_isdst = -1; // add
t.tm_year = atoi(year) - 1900;
t.tm_mon = atoi(month) - 1;
t.tm_mday = atoi(day);
t.tm_hour = atoi(HH);
t.tm_min = atoi(MM) + mins;
if (mktime(&t) == -1) {
puts("Failed conversion");
exit(EXIT_FAILURE);
}
Return of invalid pointer
return newDateTime;
attempts to return a pointer to a local array. This is undefined behavior. Code needs a new approach. Recommend passing into the function allocation to store the new newDateTime
.
Stingy buffer size
char newDateTime[13];
is borderline sufficient. What happens should the year exceed 4 characters?
// char newDateTime[13];
// sprintf(newDateTime, "%04d%02d%02d%02d%02d",
// t.tm_year, t.tm_mon, t.tm_mday,t.tm_hour,t.tm_min);
char newDateTime[13 * 2];
snprintf(newDateTime, sizeof newDateTime, "%04d%02d%02d%02d%02d",
t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min);
Also research strftime()
.
Upvotes: 1
Reputation: 11237
Don't reinvent the wheel and accept a string, which you have to parse. Instead take in a pointer to struct tm
. This way, "somebody else" can take care of handling string inputs.
struct tm *addMinutes(const struct tm *time, int nMin)
{
time_t equivalent = mktime(time);
equivalent += (nMin*60);
return localtime(&equivalent);
}
Upvotes: 3
Reputation: 13
After read all the replies i updated my code to below.
void addMinutes(char *dateTime, int mins,char *newDateTime)
{
/* Intput & Output: YYYYMMDDHHMM */
char year[5];
char month[3];
char day[3];
char HH[3];
char MM[3];
struct tm *info;
STRMCPY(year, dateTime, 4);
STRMCPY(month, &dateTime[4], 2);
STRMCPY(day, &dateTime[6], 2);
STRMCPY(HH, &dateTime[8], 2);
STRMCPY(MM, &dateTime[10],2);
struct tm t = { 0 };
t.tm_isdst = -1;
t.tm_year = atoi(year)-1900;
t.tm_mon = atoi(month)-1;
t.tm_mday = atoi(day);
t.tm_hour = atoi(HH);
t.tm_min = atoi(MM)+mins;
t.tm_sec = 0;
if (mktime(&t) == -1) {
printf("Failed conversion\n");
exit(-1);
}
time_t equivalent = mktime(&t);
strftime(newDateTime,80,"%Y%m%d%H%M", localtime(&equivalent));
}
Upvotes: 0
Reputation: 158
According to tp, the tm_min
parameter only takes integers from 0 to 59. Consider processing your input with some if/while statements to ensure the hour and minute are stored correctly before calling mktime(&t);
Upvotes: 0