きっかけ
PowerAutomateで休日(祝日)を取得する処理を検索したのですが、自社環境で使えないアクションが必要、データ更新の手間があるなど、思った通りのものがヒットしませんでした。
過去の祝日は求めない、皇室イベントなど不定イベントや法改正は考慮しないなど、妥協すれば計算式で算出できます。PowerAutomate:子フローの作成 をベースに祝日+会社休日を取得するフローを作ったので内容を紹介します。
<実行結果>
子フローの返り値として祝日配列を受け取れてます。
祝日について
フローを作るためには祝日を理解しなければいけません。内閣府HPで公開されている祝日情報をフロー化するため種類別に分類します。
日付固定の祝日
日付 | 名称 | 備考 |
---|---|---|
01/01 | 元日 | 1948年より適用 |
02/11 | 建国記念の日 | 1967年より適用 |
02/23 | 天皇誕生日 | 2020年より適用(令和天皇) 平成天皇は12/23、昭和天皇は4/29 |
04/29 | 昭和の日 | 1948年より適用 1988年までは天皇誕生日、2006年まではみどりの日 |
05/03 | 憲法記念日 | 1948年より適用 |
05/04 | みどりの日 | 1988-2006年までは国民の祝日(日曜除く) 1989-2006年は4/29がみどりの日 |
05/05 | こどもの日 | 1948年より適用 |
08/11 | 山の日 | 2016年より適用 東京オリンピックの影響で2020年は8/10、2021年は8/8に変更 |
11/03 | 文化の日 | 1948年より適用 |
11/23 | 勤労感謝の日 | 1948年より適用 |
日付可変の祝日(ハッピーマンデー・春分/秋分の日)
日付 | 名称 | 備考 |
---|---|---|
01月第2月曜 | 成人の日 | 1948年制定時は固定日(1/15) 2000年以降は1月第2月曜に変更 |
03月特定日 | 春分の日 | 1948年より適用 3/19-22のいずれかになり、国立天文台『暦象年表』に基づき前年2月頃に公示 |
07月第3月曜 | 海の日 | 1996年施行時は固定日(7/20) 2003年以降は7月第3月曜に変更 |
09月第3月曜 | 敬老の日 | 1966年施行時は固定日(9/15) 2003年以降は9月第3月曜に変更 |
09月特定日 | 秋分の日 | 1948年より適用 9/22-24のいずれかになり、国立天文台『暦象年表』に基づき前年2月頃に公示 |
10月第2月曜 | スポーツの日 | 1966年施行時は固定日(10/10) 2000年以降は10月第2月曜に変更 東京オリンピックの影響で2020年は7/24、2021年は7/23に変更 |
「春分・秋分の日」は地球の状況によって変わる可能性がありますが、計算ロジックによって算出できます。
その他の祝日
- 振替休日
1973年以降、祝日が日曜の場合はその直後の平日が該当。
通常は月曜になりますが、5/3-5は2007年以降、すべて祝日のためどれかが日曜となる場合は5/6が月曜以外でも祝日となる。(例:5/3(日)の場合、5/4-5も祝日のため5/6(水)が振替休日) - 皇室慶弔行事に伴う休日
結婚、大葬、即位等の皇室行事が行われる日 - 国民の休日
1988年以降の2つの祝日に挟まれた平日。2006年までは5/4が該当したが、2007年に5/4は祝日となったため対象外に。2003年以降、敬老の日がハッピーマンデーになったことで、秋分の日が水曜になると適用される。
子フロー全体像
①トリガ設定
親フローからは2つの引数を渡します。
- [任意:数値] 対象年
休日を取得する西暦年を指定します。指定がない場合は当年情報を取得できるようにします。 - [任意:はい/いいえ] 会社休暇
休日情報に会社休暇を含めるかを指定します。
②変数初期化
『変数を初期化する』で2つの変数を設定します。初期値設定するのは1つです。
- 対象年
本日日付の西暦年を初期値として設定します。
@{int(convertTimeZone(utcNow(),'UTC','Tokyo Standard Time','yyyy'))}
③入力対象年=空値?
『条件』で入力対象年の空値判定をします。
- 左辺: (式)
triggerBody()?['number']
- 条件:次の値に等しい
- 右辺: (式)
null
③-2) 入力値の範囲チェック
『条件』で入力値の範囲を制限します。2021年以前は現在と異なる祝日ルールが含まれるため、2022年以降のみ指定できるようにします。
- And (条件1)
- 左辺: (式)
triggerBody()?['number']
- 条件:次の値以上
- 右辺: 2022
- 左辺: (式)
- And (条件2)
- 左辺: (式)
triggerBody()?['number']
- 条件:次の値以下
- 右辺: 2050
- 左辺: (式)
③-3) 対象年の設定
『変数の設定』で入力値を対象年に設定します。
値:@{triggerBody()?['number']}
③-4) PowerApp または Flow に応答する(空値)
『PowerApp または Flow に応答する』で休日配列を空配列で設定します。
- 休日配列:
[]
③-5) 終了:年指定エラー
『終了』で処理を止めます。
④固定日祝日(5月)スコープ
固定日祝日が3日連続する5/3~5を切り出してスコープとします。
構成は以下の通りです。
④-1~3)憲法記念日/みどりの日/こどもの日追加
『配列変数に追加』で休日配列に3つの祝日を追加します。
(憲法記念日追加)値:@{variables('対象年')}-05-03
(みどりの日追加)値:@{variables('対象年')}-05-04
(こどもの日追加)値:@{variables('対象年')}-05-05
④-4)ゴールデンウィーク振替休日あり?
『条件』で5/5の曜日から振替休日有無を判定します。
- 左辺: (式)
dayOfWeek(concat(variables('対象年'),'-05-05'))
- 条件:次の値以下
- 右辺: 2
④-5)祝日配列にゴールデンウイーク振替休日追加
『配列変数に追加』で振替休日を追加します。
値:@{variables('対象年')}-05-06
⑤固定日祝日(5月除く)スコープ
5月以外の固定日祝日(7つ)を切り出してスコープとします。
- 元旦
- 建国記念の日
- 天皇誕生日
- 昭和の日
- 山の日
- 文化の日
- 勤労感謝の日
途中省略していますが、7つの祝日で同様の処理を繰り返します。
実装当初はJSONデータに祝日を埋めてループ処理したのですが、処理時間がかかったため処理を分離しました。個別処理に変更したことで、処理時間は3分の1以下に減ってます。
⑤-1)祝日追加
『配列変数に追加』で休日配列に祝日を追加します。
- (元旦)値:
@{variables('対象年')}-01-01
- (建国記念の日)値:
@{variables('対象年')}-02-11
- (天皇誕生日)値:
@{variables('対象年')}-02-23
- (昭和の日)値:
@{variables('対象年')}-04-29
- (山の日)値:
@{variables('対象年')}-08-11
- (文化の日)値:
@{variables('対象年')}-11-03
- (勤労感謝の日)値:
@{variables('対象年')}-11-23
⑤-2)祝日=日曜?
『条件』で該当祝日が日曜日か判定します。
- 左辺:(式)
dayOfWeek(last(variables('休日配列')))
- 条件:次の値以下
- 右辺: 0
⑤-3)祝日:振替休日追加
『配列変数に追加』で休日配列に振替休日を追加します。
- (元旦)値:
@{variables('対象年')}-01-02
- (建国記念の日)値:
@{variables('対象年')}-02-12
- (天皇誕生日)値:
@{variables('対象年')}-02-24
- (昭和の日)値:
@{variables('対象年')}-04-30
- (山の日)値:
@{variables('対象年')}-08-12
- (文化の日)値:
@{variables('対象年')}-11-04
- (勤労感謝の日)値:
@{variables('対象年')}-11-24
⑥春分秋分スコープ
春分の日・秋分の日を切り出してスコープとします。
構成は以下の通りです。
⑥-1)春分の日作成
『作成』で春分の日を計算して設定します。
値:@{concat(variables('対象年'),'-03-',string(sub(int(split(string(add(20.8431,mul(0.242194,sub(variables('対象年'),1980)))),'.')[0]),int(split(string(div(sub(variables('対象年'),1980),4)),'.')[0]))))}
振替休日は固定日のように特定日付で指定できず、last+addDaysで休日配列から値取得+計算して再格納すると自己参照エラーとなってしまうため、値定義を切り出します。
⑥-2)春分の日追加
『配列変数に追加』で休日配列に春分の日を追加します。
値:@{outputs('春分の日作成')}
⑥-3)春分の日=日曜?
『条件』で春分の日が日曜日か判定します。
- 左辺:(式)
dayOfWeek(last(variables('休日配列')))
- 条件:次の値以下
- 右辺: 0
⑥-4)春分の日:振替休日追加
『配列変数に追加』で休日配列に振替休日を追加します。
- 値:
@{addDays(outputs('春分の日作成'),1,'yyyy-MM-dd')}
⑥-5)秋分の日作成
『作成』で秋分の日を計算して設定します。
値:@{concat(variables('対象年'),'-09-',string(sub(int(split(string(add(23.2488,mul(0.242194,sub(variables('対象年'),1980)))),'.')[0]),int(split(string(div(sub(variables('対象年'),1980),4)),'.')[0]))))}
⑥-6~8)
⑥-2~4と同様の処理を行います。
⑥-9)シルバーウィーク国民の祝日?
秋分の日は9/22-24、敬老の日は9月第3月曜(9/15~21)となるため、秋分の日が水曜の場合、間に挟まれた平日は国民の祝日になります。『条件』で秋分の日が水曜日か判定します。
- 左辺:(式)
dayOfWeek(last(variables('休日配列')))
- 条件:次の値に等しい
- 右辺: 3
⑥-10)シルバーウィーク:国民の祝日追加
『配列変数に追加』で休日配列に国民の祝日を追加します。
- 値:
@{addDays(outputs('秋分の日作成'),-1,'yyyy-MM-dd')}
⑦ハッピーマンデースコープ
ハッピーマンデー祝日(4つ)を切り出してスコープとします。
- 成人の日
- 海の日
- 敬老の日
- スポーツの日
『配列変数に追加』で休日配列に祝日を追加します。
- (成人の日)値:
@{concat(variables('対象年'),'-01-',formatNumber(sub(14,dayOfWeek(concat(variables('対象年'),'-01-06'))),'00'))}
- (海の日)値:
@{concat(variables('対象年'),'-07-',formatNumber(sub(21,dayOfWeek(concat(variables('対象年'),'-07-06'))),'00'))}
- (敬老の日)値:
@{concat(variables('対象年'),'-09-',formatNumber(sub(21,dayOfWeek(concat(variables('対象年'),'-09-06'))),'00'))}
- (スポーツの日)値:
@{concat(variables('対象年'),'-10-',formatNumber(sub(14,dayOfWeek(concat(variables('対象年'),'-10-06'))),'00'))}
ハッピーマンデーは月曜固定なので振替休日の考慮は不要です。
⑧会社休暇スコープ
自社の年末年始休暇は12/29~1/3なので、元旦、元旦振替休日と重複しないよう休日追加します。
構成は以下の通りです。
⑧-1)会社休暇含む?
『条件』で引数が会社休暇含むを選択しているか判定します。
- 左辺:(式)
triggerBody()?['boolean']
- 条件:次の値に等しい
- 右辺:true
⑧-2)1月2日データ作成
『作成』で1/2を計算して設定します。
値:@{variables('対象年')}-01-02
⑧-3)1月2日=月曜?
『条件』で1/2が月曜日(振替休日)か判定します。
- 左辺:(式)
dayOfWeek(outputs('1月2日データ作成'))
- 条件:次の値に等しい
- 右辺:1
⑧-4)1月2日追加
『配列変数に追加』で休日配列に1/2を追加します。
- 値:
@{outputs('1月2日データ作成')}
⑧-5~8)1/3、12/29~31追加
『配列変数に追加』で休日配列に1/3、12/29~31を追加します。
- (1/3)値:
@{variables('対象年')}-01-03
- (12/29)値:
@{variables('対象年')}-12-29
- (12/30)値:
@{variables('対象年')}-12-30
- (12/31)値:
@{variables('対象年')}-12-31
⑨PowerApp または Flow に応答する
『PowerApp または Flow に応答する』で作成した休日配列をソート・JSON文字列化して返り値として設定します。
- 休日配列:
@concat('["',join(sort(variables('休日配列')),'","'),'"]')
休日配列は応答値に配列型設定できないため、配列形式の文字列で設定します。親フロー側で配列として扱う場合はjson関数で変換する必要があります。