内閣府のデータを使って祝日判定
条件分岐で祝日を個別に判定しようと試みましたが、振替休日などの判定が難しく誤った祝日が発生しかねないので、内閣府の祝日データを元に祝日判定を行うことにしました。
祝日データをダウンロード
内閣府の祝日データをダウンロード
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.yaml
にassets
を記述
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
});