#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", ¤t_tm);
printf("%s\n", buffer);
// Convert current_tm to time_t to compare against end_time
time_t current_time = mktime(¤t_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(¤t_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
*/