Xiameng Li
Xiameng Li

Reputation: 13

How to add minutes in C

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

Answers (4)

chux
chux

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

lost_in_the_source
lost_in_the_source

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

Xiameng Li
Xiameng Li

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

Ryan Fleck
Ryan Fleck

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

Related Questions