공휴일은 음력은 계산할 수 있어서 그려러니 하는데 대체공휴일이나 지방선거
같은 휴일은 계산이 안된다.. 그래서 적용하기가 힘들다.. 그래서 공공API에서
공휴일에 대한 서비스를 하고 있는데 (물론 무료고) 이렇게 가져온 데이터를 DB에
박는것도.. 그렇다고 매번 호출할때마다 인터넷자원을 사용하는것도 아닌것 같다.
그래서 프로그램 실행중에 처음1번은 가져오고 그다음부터는 마지막 갱신시간이
만료되기 전까지 유지하는 싱글톤 클래스를 만들었더랬다..
public class HolidayResolver
{
private HolidayResolver()
{
Holidays_Dic = new ConcurrentDictionary<string, HolidayIndex>();
}
private static HolidayResolver _instance;
public static HolidayResolver Instance
{
get
{
if (_instance == null) { _instance = new HolidayResolver(); }
return _instance;
}
}
private const string PUBLIC_APIKEY = @"당신의 PublicKey";
private const int refresh_days = 30;
private ConcurrentDictionary<string, HolidayIndex> Holidays_Dic;
public async Task<List<HolidayModel>> getTargetMonthHoliday(int ayear, int amonth)
{
string yearmonth = ayear.ToString("D4") + "-" + amonth.ToString("D2");
List<HolidayModel> retlist = new List<HolidayModel>();
if (Holidays_Dic.ContainsKey(yearmonth)) {
TimeSpan ts = DateTime.Now - Holidays_Dic[yearmonth].LastUpdateTime;
if (ts.TotalDays < refresh_days) {
return Holidays_Dic[yearmonth].HolidayModels;
}
}
List<HolidayModel> fromapi;
try {
fromapi = await getHolidaysFromPublicAPI(ayear, amonth);
} catch {
fromapi = null;
}
if (fromapi != null) {
HolidayIndex oneitm = new HolidayIndex();
oneitm.LastUpdateTime = DateTime.Now;
oneitm.HolidayModels = fromapi;
Holidays_Dic[yearmonth] = oneitm;
return fromapi;
} else {
return retlist;
}
}
private async Task<List<HolidayModel>> getHolidaysFromPublicAPI(int ayear, int amonth)
{
return await Task.Run(() => {
try
{
string dest_url = "http://apis.data.go.kr/B090041/openapi/service/SpcdeInfoService/getRestDeInfo?_type=json&solYear="
+ ayear.ToString("D4") + "&solMonth=" + amonth.ToString("D2") + "&ServiceKey=" + PUBLIC_APIKEY;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(dest_url);
request.Method = "GET";
request.Timeout = 4000;
WebResponse wresp = request.GetResponse();
Stream resstream = wresp.GetResponseStream();
StreamReader resreader = new StreamReader(resstream);
List<HolidayModel> ret_list = new List<HolidayModel>();
JObject res_json = JObject.Parse(resreader.ReadToEnd());
var ret_count = res_json["response"]["body"]["totalCount"];
int item_count = Convert.ToInt32(ret_count.ToString());
if (item_count > 0) {
var ret_items = res_json["response"]["body"]["items"]["item"];
if (item_count == 1) {
HolidayModel tmp = HolidayModel.ParseHoliday(ret_items["locdate"].ToString(), ret_items["dateName"].ToString());
ret_list.Add(tmp);
} else {
foreach (var one_itm in ret_items) {
HolidayModel tmp = HolidayModel.ParseHoliday(one_itm["locdate"].ToString(), one_itm["dateName"].ToString());
ret_list.Add(tmp);
}
}
}
wresp.Close();
return ret_list;
} catch (Exception ex) {
Console.WriteLine(ex.Message);
return null;
}
});
}
}
public class HolidayIndex
{
public HolidayIndex()
{
LastUpdateTime = DateTime.Now;
HolidayModels = new List<HolidayModel>();
}
public DateTime LastUpdateTime { get; set; }
public List<HolidayModel> HolidayModels { get; set; }
}
public class HolidayModel
{
public int Year { get; set; }
public int Month { get; set; }
public int Date { get; set; }
public string Name { get; set; }
public static HolidayModel ParseHoliday(string datetime_str, string hname)
{
HolidayModel retval = new HolidayModel();
retval.Name = hname;
retval.Year = Convert.ToInt32(datetime_str.Substring(0, 4));
retval.Month = Convert.ToInt32(datetime_str.Substring(4, 2));
retval.Date = Convert.ToInt32(datetime_str.Substring(6, 2));
return retval;
}
public override string ToString()
{
return "Year: " + Year + " Month: " + Month + " Date: " + Date + " Name: " + Name;
}
}
위코드를 .cs 파일에다가 짱박아 놓고 사용할때는
HolidayResolver.Instance.getTargetMonthHoliday(년, 월);
이렇게 호출해서 쓰면됨.. (달력에 공휴일을 표시한다던가..)
당연히 '당신의 PublicKey' 에 해당하는 부분은 신청하고 받은 토큰이고 -_-;
굿투유즈 (ps: 근데왜 성탄절은 기독탄신일이냐?? -_-)
댓글 없음:
댓글 쓰기