Search code examples
ctimeformat-specifiers

Is it possible to treat a format specifier as a variable?


I would like for this function to be able to return data from the given time_t argument according to the specifier argument.

If specifier is 'd', it should return the Day of the month (01-31);
If specifier is 'W', it should return the Week of the year (00-53).

int get_number_atr_from_time(time_t raw_time, char specifier) {
    struct tm *info = localtime(&raw_time);

    char buffer[3];
    strftime(buffer, 3, "%specifier", info);

    return atoi(buffer);
}

Can this somehow be done?


Solution

  • Many (if not most) of the standard C functions that take a "format" argument, such as printf and – as in your code – strftime, take that argument as a const char*. However, that does not mean it has to be a string literal.

    Any char array that you have declared and written-to yourself (i.e. not const) can still be passed as a const char* argument. So, you can write the required format specifier to a pre-declared format array and then pass that to the strftime function.

    In the following code, I show how you can do this to get the current day-of-month and week-of-year, passing 'd' and 'W', respectively, to your function, which then writes that (together with the required % prefix) to the format string used for the strftime call.

    #include <time.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    int get_number_atr_from_time(time_t raw_time, char specifier)
    {
        struct tm* info = localtime(&raw_time);
        char buffer[3];
        char format[3] = { '%', specifier, 0 }; // Initialize as "%X", where X is
        strftime(buffer, 3, format, info);      // "specifier" - and add null char
        return atoi(buffer);
    }
    
    int main(void)
    {
        time_t tNow = time(NULL);
        int dy = get_number_atr_from_time(tNow, 'd');
        int wk = get_number_atr_from_time(tNow, 'W');
        printf("D = %d, W = %d\n", dy, wk);
        return 0;
    }
    

    Output as of the date of posting:

    D = 13, W = 45
    

    Note that there will be a number of more efficient ways to retrieve the day and week values from a time_t or struct tm value, but the above code shows how to solve your specific problem.