[공통] util → framework 유틸 (ACM-CM-002)
This commit is contained in:
parent
5859076de6
commit
4e753ad4af
1 changed files with 49 additions and 118 deletions
|
|
@ -1,135 +1,66 @@
|
||||||
/*
|
|
||||||
* util_date.c - 일자/영업일 유틸리티 (plain C)
|
|
||||||
*/
|
|
||||||
#include "acq_util.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
static int is_all_digit(const char *s, int len)
|
typedef struct {
|
||||||
{
|
int year;
|
||||||
int i;
|
int month;
|
||||||
for (i = 0; i < len; i++) {
|
int day;
|
||||||
if (!isdigit((unsigned char)s[i]))
|
} Date;
|
||||||
return 0;
|
|
||||||
}
|
Date* date_create(int year, int month, int day) {
|
||||||
return 1;
|
Date* d = (Date*)malloc(sizeof(Date));
|
||||||
|
d->year = year;
|
||||||
|
d->month = month;
|
||||||
|
d->day = day;
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int to_int(const char *s, int len)
|
void date_free(Date* d) {
|
||||||
{
|
free(d);
|
||||||
int i, v = 0;
|
|
||||||
for (i = 0; i < len; i++)
|
|
||||||
v = v * 10 + (s[i] - '0');
|
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int days_in_month(int y, int m)
|
char* date_to_string(Date* d) {
|
||||||
{
|
char* buf = (char*)malloc(11);
|
||||||
static const int d[] = { 31, 28, 31, 30, 31, 30,
|
sprintf(buf, "%04d-%02d-%02d", d->year, d->month, d->day);
|
||||||
31, 31, 30, 31, 30, 31 };
|
return buf;
|
||||||
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_is_valid(const char *yyyymmdd)
|
Date* date_from_string(const char* str) {
|
||||||
{
|
Date* d = (Date*)malloc(sizeof(Date));
|
||||||
int y, m, d;
|
sscanf(str, "%d-%d-%d", &d->year, &d->month, &d->day);
|
||||||
|
return 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_diff_days(Date* a, Date* b) {
|
||||||
int date_weekday(const char *yyyymmdd)
|
struct tm ta = {0}, tb = {0};
|
||||||
{
|
ta.tm_year = a->year - 1900; ta.tm_mon = a->month - 1; ta.tm_mday = a->day;
|
||||||
static const int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
|
tb.tm_year = b->year - 1900; tb.tm_mon = b->month - 1; tb.tm_mday = b->day;
|
||||||
int y, m, d;
|
time_t tta = mktime(&ta);
|
||||||
|
time_t ttb = mktime(&tb);
|
||||||
if (!date_is_valid(yyyymmdd))
|
return (int)((tta - ttb) / 86400);
|
||||||
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 date_compare(Date* a, Date* b) {
|
||||||
{
|
if (a->year != b->year) return a->year - b->year;
|
||||||
int w = date_weekday(yyyymmdd);
|
if (a->month != b->month) return a->month - b->month;
|
||||||
return (w == 0 || w == 6) ? 1 : 0;
|
return a->day - b->day;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* YYYYMMDD 를 하루 증가시킨다 (in==out 허용) */
|
Date* date_add_days(Date* d, int days) {
|
||||||
static void add_one_day(const char *in, char *out)
|
struct tm tm = {0};
|
||||||
{
|
tm.tm_year = d->year - 1900;
|
||||||
int y = to_int(in, 4);
|
tm.tm_mon = d->month - 1;
|
||||||
int m = to_int(in + 4, 2);
|
tm.tm_mday = d->day + days;
|
||||||
int d = to_int(in + 6, 2);
|
mktime(&tm);
|
||||||
|
Date* result = (Date*)malloc(sizeof(Date));
|
||||||
d++;
|
result->year = tm.tm_year + 1900;
|
||||||
if (d > days_in_month(y, m)) {
|
result->month = tm.tm_mon + 1;
|
||||||
d = 1;
|
result->day = tm.tm_mday;
|
||||||
m++;
|
return result;
|
||||||
if (m > 12) {
|
|
||||||
m = 1;
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
snprintf(out, 9, "%04d%02d%02d", y, m, d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int date_next_business(const char *yyyymmdd, char *out)
|
int date_get_year(Date* d) { return d->year; }
|
||||||
{
|
int date_get_month(Date* d) { return d->month; }
|
||||||
char cur[9];
|
int date_get_day(Date* d) { return d->day; }
|
||||||
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';
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Reference in a new issue