Pastebin: Java 内閣府の「国民の祝日」CSVをダウンロードして祝日かどうかを返すクラス

Format
Java
Post date
2021-02-06 20:23
Publication Period
Unlimited
  1. import java.io.BufferedReader;
  2. import java.io.BufferedWriter;
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.FileWriter;
  6. import java.io.IOException;
  7. import java.io.InputStreamReader;
  8. import java.net.HttpURLConnection;
  9. import java.net.MalformedURLException;
  10. import java.net.URL;
  11. import java.nio.file.Files;
  12. import java.nio.file.attribute.BasicFileAttributes;
  13. import java.nio.file.attribute.FileTime;
  14. import java.time.Instant;
  15. import java.util.HashMap;
  16. import java.util.regex.Matcher;
  17. import java.util.regex.Pattern;
  18. /*
  19. * 内閣府の「国民の祝日」CSVを取得して祝日情報を管理するクラス
  20. */
  21. public class HolidayInfo{
  22. /*******************************************************************************
  23. * 定数
  24. ******************************************************************************/
  25. private final static String FETCH_URI = "https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv";
  26. private final static String FILENAME = "env"+File.separator+"holidays.csv";
  27. private final static String encoding = "MS932";
  28. /*******************************************************************************
  29. * 静的メンバー
  30. ******************************************************************************/
  31. private static HashMap<String, HolidayInfo> holidays = null;
  32. /*******************************************************************************
  33. * 部品以外のインスタンスメンバー
  34. ******************************************************************************/
  35. private int year;
  36. private int month;
  37. private int day;
  38. private String holidayName;
  39. /*******************************************************************************
  40. * コンストラクタ
  41. ******************************************************************************/
  42. public HolidayInfo(){
  43. year = 0;
  44. month = 0;
  45. day = 0;
  46. holidayName = null;
  47. }
  48. /*******************************************************************************
  49. * 公開メソッド
  50. ******************************************************************************/
  51. // 祝日の西暦年を返す
  52. public int getYear(){
  53. return year;
  54. }
  55. // 祝日の月を返す
  56. public int getMonth(){
  57. return month;
  58. }
  59. // 祝日の日を返す
  60. public int getDay(){
  61. return day;
  62. }
  63. // 祝日の名称を返す
  64. public String getHolidayName(){
  65. return holidayName;
  66. }
  67. /*******************************************************************************
  68. * 静的公開メソッド
  69. ******************************************************************************/
  70. /*
  71. * CSVファイルを読み込む
  72. */
  73. public static boolean Load(String uri, int interval){
  74. if (IsCSVFileLifetimeExpired(interval)){
  75. FetchCSVFile(uri);
  76. }
  77. return LoadFromCSVFile(FILENAME);
  78. }
  79. /*
  80. * CSVファイルを更新する
  81. */
  82. public static boolean Refresh(String uri, int interval){
  83. if (!IsCSVFileLifetimeExpired(interval))
  84. return true;
  85. FetchCSVFile(uri);
  86. return LoadFromCSVFile(FILENAME);
  87. }
  88. /*
  89. * CSVファイルを内閣府のサーバーからダウンロードする
  90. */
  91. public static boolean FetchCSVFile(String uri){
  92. if (uri == null || uri.isEmpty())
  93. uri = FETCH_URI;
  94. BufferedWriter bw = null;
  95. BufferedReader br = null;
  96. try {
  97. // 内閣府のホームページに接続する
  98. URL url = new URL(uri);
  99. HttpURLConnection ucon = (HttpURLConnection)url.openConnection();
  100. ucon.setConnectTimeout(5000);
  101. ucon.setReadTimeout(5000);
  102. ucon.setRequestMethod("GET");
  103. ucon.connect();
  104. // レスポンスを一時ファイルに書き出す
  105. String tmpfile = FILENAME + ".tmp";
  106. bw = new BufferedWriter(new FileWriter(tmpfile));
  107. br = new BufferedReader(new InputStreamReader(ucon.getInputStream(), encoding));
  108. String str;
  109. while((str = br.readLine()) != null){
  110. bw.write(str);
  111. bw.write("\n");
  112. }
  113. br.close();
  114. br = null;
  115. bw.close();
  116. bw = null;
  117. // CSVファイルにリネームする
  118. File ofile = new File(FILENAME);
  119. if ( ofile.exists() && ! ofile.delete() ) {
  120. System.err.println("[HolidayInfo]CSVファイルを削除できない:" + ofile.getAbsolutePath());
  121. }
  122. File nfile = new File(tmpfile);
  123. if ( ! nfile.renameTo(ofile) ) {
  124. System.err.println("[HolidayInfo]CSVファイルをリネームできない:" +
  125. nfile.getAbsolutePath() + "=>" + ofile.getAbsolutePath());
  126. return false;
  127. }
  128. return true;
  129. } catch (MalformedURLException e) {
  130. e.printStackTrace();
  131. } catch (IOException e) {
  132. e.printStackTrace();
  133. }
  134. finally{
  135. if (br != null) try { br.close(); } catch (Exception e) {}
  136. if (bw != null) try { bw.close(); } catch (Exception e) {}
  137. }
  138. return false;
  139. }
  140. /*
  141. * CSVファイルを読み込む
  142. */
  143. public static boolean LoadFromCSVFile(String path){
  144. if (path == null)
  145. return false;
  146. HashMap<String, HolidayInfo> map = new HashMap<String, HolidayInfo>();
  147. BufferedReader br = null;
  148. // CSVファイルが存在するかチェックする
  149. File file = new File(path);
  150. try {
  151. if (!file.exists()){
  152. System.err.println("[HolidayInfo]ファイルがない: " + file.getAbsolutePath());
  153. return false;
  154. }
  155. br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
  156. // 1行ずつ読み込む
  157. String str;
  158. while ((str = br.readLine()) != null) {
  159. // CSVの形式は YYYY/MM/DD,名称となっている
  160. Matcher ma = Pattern.compile("^(\\d{4})/(\\d{1,2})/(\\d{1,2}),(.*)$").matcher(str);
  161. if (!ma.find())
  162. continue;
  163. // 祝日情報を生成する
  164. HolidayInfo hi = new HolidayInfo();
  165. hi.year = Integer.parseInt(ma.group(1));
  166. hi.month = Integer.parseInt(ma.group(2));
  167. hi.day = Integer.parseInt(ma.group(3));
  168. hi.holidayName = ma.group(4);
  169. // キーに紐づけてハッシュマップに追加する
  170. String s = FormatKey( hi.year, hi.month, hi.day);
  171. map.put(s, hi);
  172. }
  173. }
  174. catch (Exception e) {
  175. e.printStackTrace();
  176. System.err.println("[HolidayInfo]ファイルの読み込みに失敗: "+file.getAbsolutePath());
  177. return false;
  178. }
  179. finally {
  180. if (br != null) try { br.close(); } catch (Exception e) {}
  181. }
  182. holidays = map;
  183. System.out.println("[HolidayInfo]祝日数: "+map.size());
  184. return true;
  185. }
  186. /*
  187. * 指定した日が祝日かどうかを返す
  188. */
  189. public static boolean IsHoliday(int year, int month, int day){
  190. return IsHoliday(FormatKey(year, month, day));
  191. }
  192. /*
  193. * 指定した日が祝日の場合、その名前を返す
  194. */
  195. public static String GetHolidayName(int year, int month, int day){
  196. return GetHolidayName(FormatKey(year, month, day));
  197. }
  198. /*
  199. * 指定した日の祝日情報を返す
  200. */
  201. public static HolidayInfo GetHolidayInfo(int year, int month, int day){
  202. return GetHolidayInfo(FormatKey(year, month, day));
  203. }
  204. /*
  205. * YYYY/MM/DD形式で指定した日が祝日かどうかを返す
  206. */
  207. public static boolean IsHoliday(String date){
  208. HolidayInfo hi = GetHolidayInfo(date);
  209. return (hi != null);
  210. }
  211. /*
  212. * YYYY/MM/DD形式で指定した日が祝日の場合、その名前を返す
  213. */
  214. public static String GetHolidayName(String date){
  215. HolidayInfo hi = GetHolidayInfo(date);
  216. return (hi != null) ? hi.holidayName : null;
  217. }
  218. /*
  219. * YYYY/MM/DD形式で指定した日の祝日情報を返す
  220. */
  221. public static HolidayInfo GetHolidayInfo(String date){
  222. if (date == null || holidays == null)
  223. return null;
  224. if (date.length() > 10)
  225. date = date.substring(0, 10);
  226. return holidays.get(date);
  227. }
  228. /*******************************************************************************
  229. * 静的内部関数
  230. ******************************************************************************/
  231. /*
  232. * ハッシュマップのキーを生成する
  233. */
  234. private static String FormatKey(int year, int month, int day){
  235. return String.format("%04d/%02d/%02d", year, month, day);
  236. }
  237. /*
  238. * CSVファイルの寿命が尽きているかどうかを返す
  239. */
  240. private static boolean IsCSVFileLifetimeExpired(int interval){
  241. // インターバルが0以下の場合は寿命はない
  242. if (interval <= 0)
  243. return false;
  244. // CSVファイルが存在しない場合は尽きているとみなす
  245. File file = new File(FILENAME);
  246. if (!file.exists())
  247. return true;
  248. try {
  249. BasicFileAttributes attrs = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
  250. FileTime time = attrs.creationTime();
  251. Instant now = Instant.now();
  252. // ファイル生成後の経過ミリ秒数を計算する
  253. long elapsed = now.toEpochMilli() - time.toMillis();
  254. System.out.println("[HolidayInfo]経過時間(日):" + (elapsed/1000/24/3600));
  255. // インターバルを超えていない場合は尽きていない
  256. if ( elapsed/1000 < interval*24*3600)
  257. return false;
  258. } catch (IOException e) {
  259. }
  260. return true;
  261. }
  262. }
다운로드 Printable view

URL of this paste

Embed with JavaScript

Embed with iframe

Raw text