如何在纯C语言中根据年份和ISO周数计算对应日期
Pure C Standard Library Implementation for ISO Week to Date Conversion
Got it, here's a robust, pure C solution that uses only the standard C library (<time.h> and <stdbool.h>) to convert an ISO year and week number to the corresponding calendar date—fully handling edge cases where the ISO week falls in the previous or next calendar year.
Key ISO Week Rules Recap
- ISO weeks start on Monday and end on Sunday.
- ISO Week 1 is the first week of the ISO year that contains at least 4 days of the calendar year (equivalent to the week containing January 4th of the ISO year).
- The ISO year may differ from the calendar year: e.g., ISO 2019 Week 1 starts on December 31, 2018 (calendar year 2018, but ISO year 2019).
Implementation Code
#include <time.h> #include <stdbool.h> /** * Converts an ISO year and week number to the corresponding calendar date (Monday of the target week). * @param iso_year The ISO year (e.g., 2019) * @param iso_week The ISO week number (1-53) * @param day Output: day of the month (1-31) * @param month Output: month (1-12) * @param year Output: actual calendar year (may differ from iso_year) * @return true on success, false on invalid input or conversion error */ bool iso_week_to_date(int iso_year, int iso_week, int *day, int *month, int *year) { // Validate input week range if (iso_week < 1 || iso_week > 53) { return false; } // Initialize tm structure for January 4th of the ISO year struct tm tm_date = {0}; tm_date.tm_year = iso_year - 1900; // tm_year counts years since 1900 tm_date.tm_mon = 0; // 0 corresponds to January tm_date.tm_mday = 4; tm_date.tm_isdst = -1; // Let system auto-detect daylight saving time // Convert to time_t to resolve the full date structure time_t time_val = mktime(&tm_date); if (time_val == (time_t)-1) { return false; } // Convert tm_wday (0=Sunday, 1=Monday, ...6=Saturday) to ISO weekday (1=Monday, ...7=Sunday) int iso_weekday = (tm_date.tm_wday == 0) ? 7 : tm_date.tm_wday; // Calculate days to subtract from Jan 4th to get to the Monday of ISO Week 1 int days_to_monday = 5 - iso_weekday; // Simplified from 4 - (iso_weekday - 1) tm_date.tm_mday += days_to_monday; // Re-resolve the date after adjusting to ISO Week 1 Monday (handles year/month rollover) time_val = mktime(&tm_date); if (time_val == (time_t)-1) { return false; } // Add (week_num -1) weeks to reach the target week's Monday tm_date.tm_mday += (iso_week - 1) * 7; time_val = mktime(&tm_date); if (time_val == (time_t)-1) { return false; } // Extract human-readable date values *day = tm_date.tm_mday; *month = tm_date.tm_mon + 1; // Convert from 0-based to 1-based month *year = tm_date.tm_year + 1900; return true; } // Example usage #include <stdio.h> int main() { int day, month, year; if (iso_week_to_date(2019, 1, &day, &month, &year)) { printf("ISO 2019 Week 1 starts on: %04d-%02d-%02d\n", year, month, day); // Output: 2018-12-31 } if (iso_week_to_date(2020, 53, &day, &month, &year)) { printf("ISO 2020 Week 53 starts on: %04d-%02d-%02d\n", year, month, day); // Output: 2020-12-28 } if (iso_week_to_date(2021, 1, &day, &month, &year)) { printf("ISO 2021 Week 1 starts on: %04d-%02d-%02d\n", year, month, day); // Output: 2021-01-04 } return 0; }
How It Works
- Input Validation: Checks if the ISO week number falls within the valid range (1-53).
- January 4th Anchor: Uses January 4th of the ISO year as a fixed point—this date is guaranteed to be part of ISO Week 1 per ISO standards.
- Adjust to ISO Week 1 Monday: Converts the anchor date's weekday to ISO format, then calculates how many days to subtract to reach the Monday of ISO Week 1. The
mktimefunction automatically handles month/year rollovers (e.g., shifting to December of the previous year). - Calculate Target Week: Adds
(iso_week -1) *7days to the ISO Week 1 Monday to get the Monday of the target week.mktimeagain handles any necessary date adjustments. - Extract Date Values: Converts the
struct tmfields (which use 0-based months and years since 1900) to human-readable 1-based months and full calendar years.
Notes
- The function returns the Monday of the target ISO week. To get other days in the week, simply add 0-6 days to the
tm_mdayfield before the finalmktimecall (e.g., add 3 for Thursday). tm_isdst = -1ensures the system correctly handles daylight saving time adjustments for your local timezone. For UTC-only calculations, you can modify the logic to usegmtimeinstead of relying onmktime's local timezone handling.
内容的提问来源于stack exchange,提问作者markt1964
相关产品推荐
相关产品推荐

