How to get all dates between 2 dates in C

1 Answer

0 votes
#include <stdio.h>
#include <time.h>

/**
 * Generates and prints all dates between start_date and end_date inclusive.
 * 
 * @param start_date_str Start date in "YYYY-MM-DD" format.
 * @param end_date_str   End date in "YYYY-MM-DD" format.
 */
void get_dates_between(const char *start_date_str, const char *end_date_str) {
    struct tm start_tm = {0};
    struct tm end_tm = {0};

    // 1. Parse input strings into struct tm components
    if (sscanf(start_date_str, "%d-%d-%d", &start_tm.tm_year, &start_tm.tm_mon, &start_tm.tm_mday) != 3) {
        fprintf(stderr, "Error: Invalid start date format. Use YYYY-MM-DD.\n");
        return;
    }
    if (sscanf(end_date_str, "%d-%d-%d", &end_tm.tm_year, &end_tm.tm_mon, &end_tm.tm_mday) != 3) {
        fprintf(stderr, "Error: Invalid end date format. Use YYYY-MM-DD.\n");
        return;
    }

    // 2. Adjust struct tm fields to standard C definitions:
    //    - tm_year: years since 1900
    //    - tm_mon: months since January (0-11)
    start_tm.tm_year -= 1900;
    start_tm.tm_mon -= 1;
    end_tm.tm_year -= 1900;
    end_tm.tm_mon -= 1;

    // Set time to noon (12:00:00) and reset DST flag. 
    // Setting to noon prevents midnight DST shift bugs where a day might appear 
    // to have 23 or 25 hours.
    start_tm.tm_hour = 12;
    start_tm.tm_isdst = -1;
    end_tm.tm_hour = 12;
    end_tm.tm_isdst = -1;

    // 3. Convert to time_t for range validation
    time_t start_time = mktime(&start_tm);
    time_t end_time = mktime(&end_tm);

    if (start_time == (time_t)-1 || end_time == (time_t)-1) {
        fprintf(stderr, "Error: Failed to normalize dates using mktime().\n");
        return;
    }

    if (start_time > end_time) {
        printf("Error: Start date cannot be after the end date.\n");
        return;
    }

    // 4. Iterate day-by-day safely
    struct tm current_tm = start_tm;
    char buffer[11]; // Buffer for "YYYY-MM-DD" + null terminator

    while (1) {
        // Format the current struct tm back into a string
        strftime(buffer, sizeof(buffer), "%Y-%m-%d", &current_tm);
        printf("%s\n", buffer);

        // Convert current_tm to time_t to compare against end_time
        time_t current_time = mktime(&current_tm);
        if (current_time >= end_time) {
            break;
        }

        // Increment the day. 
        // mktime() will automatically correct month boundaries, year rollovers, and leap years.
        current_tm.tm_mday++;
        current_tm.tm_hour = 12; // Maintain noon safeguard
        current_tm.tm_isdst = -1;
        mktime(&current_tm); 
    }
}

int main(void) {
    // Example usage spanning a leap year / month boundary
    const char *start = "2026-02-26";
    const char *end = "2026-03-02";

    printf("Dates between %s and %s:\n", start, end);
    get_dates_between(start, end);

    return 0;
}


/*
run:

Dates between 2026-02-26 and 2026-03-02:
2026-02-26
2026-02-27
2026-02-28
2026-03-01
2026-03-02

*/

 



answered 5 days ago by avibootz
...