0
Help us understand the problem. What are the problem?

posted at

updated at

【Flutter】祝日判定

内閣府のデータを使って祝日判定

条件分岐で祝日を個別に判定しようと試みましたが、振替休日などの判定が難しく誤った祝日が発生しかねないので、内閣府の祝日データを元に祝日判定を行うことにしました。

祝日データをダウンロード

内閣府の祝日データをダウンロード
https://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html

Assetsの読み込み準備

Assetsの読み込みはこちらを参照
https://docs.flutter.dev/development/ui/assets-and-images

プロジェクトのディレクトリ直下にassetsフォルダを作成
assetsフォルダにダウンロードしたデータをコピー

directory
.
├── android
├── assets // 追加
│   └── syukujitsu.csv // 追加
├── build
├── ios
├── lib
│   └── main.dart
├── test
└── pubspec.yaml

pubspec.yamlassetsを記述

pubspec.yaml
flutter:
  assets:
    - assets/syukujitsu.csv

文字列の日付をDateTimeに置き換える関数

DateTime stringToDate(String str) {
  List<String> splitDate = str.split('/');
  int year = int.parse(splitDate[0]);
  int month = int.parse(splitDate[1]);
  int day = int.parse(splitDate[2]);
  return DateTime(year, month, day);
}

CSVをDateTime型の配列に変換

デコードにはこのプラグインを使いました。
https://pub.dev/packages/charset_converter

import 'package:charset_converter/charset_converter.dart';

Future<List<DateTime>> loadCsv() async {
  // assetsからCSVを読み込んで、ByteDataを取得
  final ByteData byteData = await rootBundle.load('assets/syukujitsu.csv');
  // ByteDataをUint8Listに変換
  final Uint8List uint8List = byteData.buffer.asUint8List();
  // charset_converterでデコード
  final String? decode = await CharsetConverter.decode('cp932', uint8list);
  // 余分な余白を削除
  final String trim = decode!.trim();

  List<HolidayModel> list = [];
  // 改行で分割
  for (String line in trim.split('\r\n')) {
    // コンマで分割
    List<String> rows = line.split(',');
    // ヘッダーを読み飛ばす
    if (rows[0] == '国民の祝日・休日月日' && rows[1] == '国民の祝日・休日名称') continue;
    // 文字列をDateTimeに変換
    DateTime date = stringToDate(rows[0]);
    // 配列に格納
    list.add(date);
  }
  return list;
}

rootBundle.loadString()で読み込みが出来ればもう少し簡単に文字列での取得ができましたが、文字コードがUTF-8にのみ対応しているみたいなので今回は使えませんでした。
rootBundle.load()ByteDataで取得して、Uint8Listへ変換しCharsetConverterを使ってデコード。
最後の行に空白があるので、trim()で削除して\r\n,で分割する。
ヘッダーは必要ないのでcontinueで読み飛ばし、文字列の日付をDateTimeに変換して配列へ格納。

祝日を判定

Future<bool> isHoliday(DateTime date) async {
  // 読み込みの結果を待つ
  var result = await loadCsv();
  for (var i = 0; i < result.length; i++) {
    // 祝日データと引数の日付を比較
    if (DateUtils.isSameDay(result[i], date)) {
      return true;
    } else {
      continue;
    }
  }
  return false;
}
final DateTime date = DateTime(2021, 1, 1);
isHoliday(date).then((result) {
  print('$result'); // true
});
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?