曜日判定と祝日判定について

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

何年何月何日はお休みだったっけ?

台風一過の晴天に恵まれた本日、みなさんいかがお過ごしでしょうか?さて、今日は、曜日判定と祝日判定について調べて居まして、ツール作ってみました。

曜日判定

曜日判定は、概ね世界共通ですね。日曜日、月曜日、火曜日、水曜日、木曜日、金曜日、土曜日のように七曜で扱いますね。プログラミングの世界でも、weekday関数を呼び出せば0から6までの曜日を表す数字が帰ってきますので特別なロジックは必要ありません。

祝日判定

祝日というのは、国によって異なります。そのため、日本の祝日を判定するロジックは、プログラミング言語の仕様として含まれていません。また、祝日は追加やルール変更があるため、簡単なロジックでは算出できません。

曜日と祝日を判定するプログラム

先人の知恵をお借りしまして、機能を修正したプログラムをご紹介したいと思います。まずは、セットアップからです。Pythonを用います。

$ sudo pip install pyyaml
$ vi jpholidaycsv

そして、以下が完成したプログラムです。

#!/usr/bin/env python import sys import os import errno from datetime import datetime, date, timedelta import urllib2 import yaml import cPickle as pickle

argvs = sys.argv argc = len(argvs)

datadir = "~/.jpholidayp" cachefile = "cache" cachedays = 5

class Cache: def __init__(self): try: os.mkdir(os.path.expanduser(datadir)) except OSError: if sys.exc_info()[1].errno != errno.EEXIST: raise

def get(self): file = os.path.join(os.path.expanduser(datadir), cachefile) if not os.path.exists(file): return None today = date.today() with open(file) as f: dat = pickle.load(f) if dat["expires"] <= today: return None else: return dat["val"] def set(self, val): expires = date.today() + timedelta(cachedays) dat = {"expires": expires, "val": val} file = os.path.join(os.path.expanduser(datadir), cachefile) with open(file, "w") as f: pickle.dump(dat, f) class HolidayJp: URL = 'https://raw.githubusercontent.com/k1LoW/holiday_jp/master/holidays.yml' def __init__(self): cache = Cache() c = cache.get() if c: dat = c["holiday_jp"] else: res = urllib2.urlopen(self.URL) dat = yaml.load(res) cache.set({"holiday_jp": dat}) self.holiday_jp = dat def is_holiday(self, dt): return dt in self.holiday_jp.keys() class JpHoliday: @classmethod def is_national_holiday(self, dt): holiday_jp = HolidayJp() return holiday_jp.is_holiday(dt) # value of datetime.weekday() SATURDAY = 5 SUNDAY = 6 @classmethod def is_holiday(self, dt): w = dt.weekday() if w == self.SATURDAY or w == self.SUNDAY: return True elif self.is_national_holiday(dt): return True else: return False # exit statuses EXIT_HOLIDAY = 0 EXIT_WEEKDAY = 1 EXIT_ERROR = 2 def jpholidayp(): start_date = datetime.strptime(argvs[1], "%Y/%m/%d") end_date = datetime.strptime(argvs[2], "%Y/%m/%d") total_days = (end_date - start_date).days + 1 #inclusive 5 days header = ["date","year","month","day","holiday","weekday"] header_str = map(str,header) print ",".join(header) for day_number in range(total_days): current_date = (start_date + timedelta(days = day_number)).date() csv = [] csv.append(current_date) csv.append(current_date.year) csv.append(current_date.month) csv.append(current_date.day) csv.append(int(JpHoliday.is_holiday(current_date))) csv.append(current_date.weekday()) csv_str = map(str,csv) print ",".join(csv_str) if __name__ == "__main__": jpholidayp() [/python]

satoshi7 / jpholidaycsv

本プログラム作成に当たりまして以下Githubを大変参考にさせて頂きました。と言いますが、ほぼそのままです。。。

emasaka / jpholidayp

祝日&曜日判定プログラムの出力結果

完成したプログラムを実行してみますね。年月日、年、月、日、祝日(TRUE=1)、曜日(日=0〜土=6)で出力されています。

$ ./jpholidaycsv 2015/04/25 2015/05/15 > output.csv
$ cat output.csv 
date,year,month,day,holiday,weekday
2015-04-25,2015,4,25,1,5
2015-04-26,2015,4,26,1,6
2015-04-27,2015,4,27,0,0
2015-04-28,2015,4,28,0,1
2015-04-29,2015,4,29,1,2
2015-04-30,2015,4,30,0,3
2015-05-01,2015,5,1,0,4
2015-05-02,2015,5,2,1,5
2015-05-03,2015,5,3,1,6
2015-05-04,2015,5,4,1,0
2015-05-05,2015,5,5,1,1
2015-05-06,2015,5,6,1,2
2015-05-07,2015,5,7,0,3
2015-05-08,2015,5,8,0,4
2015-05-09,2015,5,9,1,5
2015-05-10,2015,5,10,1,6
2015-05-11,2015,5,11,0,0
2015-05-12,2015,5,12,0,1
2015-05-13,2015,5,13,0,2
2015-05-14,2015,5,14,0,3
2015-05-15,2015,5,15,0,4

まとめ

一部のクラスタの方に刺さるのではと。。。。