diff --git a/legacy/app/common/util_date.c b/legacy/app/common/util_date.c index 70cbed6..04aa43f 100644 --- a/legacy/app/common/util_date.c +++ b/legacy/app/common/util_date.c @@ -1,135 +1,52 @@ -/* - * util_date.c - 일자/영업일 유틸리티 (plain C) - */ -#include "acq_util.h" - -#include -#include #include +#include +#include #include -static int is_all_digit(const char *s, int len) -{ - int i; - for (i = 0; i < len; i++) { - if (!isdigit((unsigned char)s[i])) - return 0; - } - return 1; +#define DATE_BUF_SIZE 32 + +typedef struct { + int year; + int month; + int day; +} date_t; + +int date_parse(const char* str, date_t* out) { + if (!str || !out) return -1; + return sscanf(str, "%4d-%2d-%2d", &out->year, &out->month, &out->day); } -static int to_int(const char *s, int len) -{ - int i, v = 0; - for (i = 0; i < len; i++) - v = v * 10 + (s[i] - '0'); - return v; +int date_format(const date_t* d, char* buf, size_t len) { + if (!d || !buf) return -1; + return snprintf(buf, len, "%04d-%02d-%02d", d->year, d->month, d->day); } -static int days_in_month(int y, int m) -{ - static const int d[] = { 31, 28, 31, 30, 31, 30, - 31, 31, 30, 31, 30, 31 }; - if (m < 1 || m > 12) - return 0; - if (m == 2) { - int leap = (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0); - return leap ? 29 : 28; - } - return d[m - 1]; +int date_diff_days(const date_t* from, const date_t* to) { + if (!from || !to) return 0; + struct tm a = {0}, b = {0}; + a.tm_year = from->year - 1900; a.tm_mon = from->month - 1; a.tm_mday = from->day; + b.tm_year = to->year - 1900; b.tm_mon = to->month - 1; b.tm_mday = to->day; + return (int)(difftime(mktime(&b), mktime(&a)) / 86400); } -int date_is_valid(const char *yyyymmdd) -{ - int y, m, d; - - if (!yyyymmdd || strlen(yyyymmdd) < 8) - return 0; - if (!is_all_digit(yyyymmdd, 8)) - return 0; - - y = to_int(yyyymmdd, 4); - m = to_int(yyyymmdd + 4, 2); - d = to_int(yyyymmdd + 6, 2); - - if (y < 1900 || y > 2999) - return 0; - if (m < 1 || m > 12) - return 0; - if (d < 1 || d > days_in_month(y, m)) - return 0; - return 1; -} - -/* Sakamoto 알고리즘: 0=일요일 ... 6=토요일 */ -int date_weekday(const char *yyyymmdd) -{ - static const int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 }; - int y, m, d; - - if (!date_is_valid(yyyymmdd)) - return -1; - - y = to_int(yyyymmdd, 4); - m = to_int(yyyymmdd + 4, 2); - d = to_int(yyyymmdd + 6, 2); - - if (m < 3) - y -= 1; - return (y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) % 7; -} - -int date_is_weekend(const char *yyyymmdd) -{ - int w = date_weekday(yyyymmdd); - return (w == 0 || w == 6) ? 1 : 0; -} - -/* YYYYMMDD 를 하루 증가시킨다 (in==out 허용) */ -static void add_one_day(const char *in, char *out) -{ - int y = to_int(in, 4); - int m = to_int(in + 4, 2); - int d = to_int(in + 6, 2); - - d++; - if (d > days_in_month(y, m)) { - d = 1; - m++; - if (m > 12) { - m = 1; - y++; - } - } - snprintf(out, 9, "%04d%02d%02d", y, m, d); -} - -int date_next_business(const char *yyyymmdd, char *out) -{ - char cur[9]; - int guard = 0; - - if (!date_is_valid(yyyymmdd) || !out) - return -1; - - memcpy(cur, yyyymmdd, 8); - cur[8] = '\0'; - - do { - add_one_day(cur, cur); - if (++guard > 14) /* 무한루프 방지 */ - return -1; - } while (date_is_weekend(cur)); - - memcpy(out, cur, 8); - out[8] = '\0'; +int date_add_days(const date_t* d, int days, date_t* out) { + if (!d || !out) return -1; + struct tm base = {0}; + base.tm_year = d->year - 1900; base.tm_mon = d->month - 1; base.tm_mday = d->day; + base.tm_mday += days; + mktime(&base); + out->year = base.tm_year + 1900; + out->month = base.tm_mon + 1; + out->day = base.tm_mday; return 0; } -void date_today(char *out) -{ - time_t now = time(NULL); - struct tm tmv; - localtime_r(&now, &tmv); - strftime(out, 9, "%Y%m%d", &tmv); +int date_today(date_t* out) { + if (!out) return -1; + time_t now = time(NULL); + struct tm* t = localtime(&now); + out->year = t->tm_year + 1900; + out->month = t->tm_mon + 1; + out->day = t->tm_mday; + return 0; }