Power Automate の日付計算まとめ|翌月1日・前月末・営業日を月初から組み立てる

Power Automate 実践・Tips

📝 この記事は、Power Automate で日付を計算するときの型を、実際に動かしながら整理したものです。
式や関数の仕様はMicrosoft 公式(ワークフロー式の関数リファレンス)で確認しています。

🧭 なぜこの記事を書いたのか
月次の集計や締め日の通知は、社内でいちばん自動化の相談が多いところです。
ただ、月末の日数が月ごとに違うせいで、素直に日数を足し引きすると必ずどこかでずれます。
月初を基準にするという考え方1つで、この面倒がまとめて消えます。

「翌月1日」「前月末」「5営業日目」。月次フローを作ると必ず出てくる3つです。
どれも日数を数えて解こうとすると詰まります。
この記事では、月初を基準にして組み立てるという共通の型で、3つとも片づけます.

日付の相談は、だいたいこの3つに集まります。
最初は個別に答えていたのですが、どれも「月初から数える」で説明できると気づいてから、話が早く済むようになりました。

📋 この記事で分かること

  • 翌月1日・前月末・今月末を1行で出す式
  • なぜ日数を足し引きすると失敗するのか
  • 「◯営業日目」をループで数える組み方
  • utcNow() は UTC なので、そのまま使うと日付がずれるという話
  • 表示形式を整える formatDateTime の使いどころ

なぜ日数を足し引きすると失敗するのか

月末の日数は28〜31日と変わります。固定で日数を足すと、月によって結果がずれます。

addDays(utcNow(), 31) → 1月末に実行すると3月3日になる

一方で、どの月にも「1日」は必ず存在します
だから月初を基準にすると、月ごとの差に振り回されなくなります。

翌月1日・前月末・今月末

月初に丸めてから、月や日を動かす3/31前月末4/1起点4/30今月末5/1翌月1日addDays(…, -1)startOfMonth(addMonths(…, 1))addDays(…, -1)startOfMonth(utcNow())
起点は必ず「月初」。そこから月や日を動かすので、月末の日数に振り回されない

使う関数は startOfMonth()addMonths()addDays() の3つだけです。

翌月1日|1か月進めてから、その月の頭に丸めます。

startOfMonth(addMonths(utcNow(), 1))

今月1日|そのまま丸めるだけです。

startOfMonth(utcNow())

前月末|今月の1日から1日戻ります。月末を直接求めないのがコツです。

addDays(startOfMonth(utcNow()), -1)

今月末|翌月1日から1日戻ります。同じ考え方です。

addDays(startOfMonth(addMonths(utcNow(), 1)), -1)

💡 覚えるのは「月初に丸めてから動かす」だけ
4つとも、やっていることは同じです。
startOfMonth() で足場を作ってから、月や日を動かしています。
この順番を逆にすると、また月末の日数に悩むことになります。

📌 utcNow() は UTC を返す

utcNow() は UTC。日本時間とは9時間ずれる日本時間2026/04/01 05:00−9時間UTC(utcNow が返す値)2026/03/31 20:00↑ 日付はまだ「3月」startOfMonth(utcNow())→ 2026-03-01前月が返るconvertTimeZone(utcNow(),‘UTC’,’Tokyo Standard Time’)→ 2026-04-01日本時間の月初になる
月初1日の朝に動くフローは、変換しないと前月を拾う

ここが実務でいちばん効いてくる話です。

utcNow() が返すのは協定世界時(UTC)です。日本時間ではありません。
日本時間との差は9時間なので、日本の朝9時より前は、UTCではまだ前日です。

つまり、月初の午前に動く月次フローで startOfMonth(utcNow()) を使うと、
前月の1日が返ってくることがあります。月末の判定でも同じことが起きます。

日本時間で判断したいなら、先にタイムゾーンを変換します。

convertTimeZone(utcNow(), 'UTC', 'Tokyo Standard Time', 'yyyy-MM-dd')

タイムゾーン名は Windows の標準的な名前を使います。日本は Tokyo Standard Time です。

「たまに1日ずれる」という話は、これが原因のことがあります。
毎日動かすフローだと月に1〜2回しか外れないので、原因にたどり着きにくいところです。私は日付を扱うとき、先に変換を入れてしまうようにしました。

表示の形を整える

計算結果はそのままだと 2026-04-01T00:00:00.0000000Z のような形で返ります。
メールやファイル名に使うなら整えます。

formatDateTime(startOfMonth(addMonths(utcNow(), 1)), 'yyyy/MM/dd')

formatDateTime() には書式のほかにロケールも渡せます。
曜日や月名を日本語で出したいときは、ここを指定します。

ファイル名やフォルダ名に使うなら yyyyMMdd
人が読む文章に入れるなら yyyy年M月d日 のように、用途で分けると読みやすくなります。

「◯営業日目」を出す

dayOfWeek() が返す数字(日曜が 0)01234560 と 6 を飛ばせば、平日だけ数えられる
祝日は判定できない。祝日も除くなら、別に一覧を持つ必要がある

営業日は、日数の計算では出せません。土日を飛ばして数える必要があるからです。
そこで1日ずつ進めながら数えるという素直な方法を使います。

✅ 組み方

  • 整数の変数 count を 0 で用意する
  • 文字列の変数 currentDate に月初を入れる
  • 「Do until」で count が目標値になるまでまわす
  • ループの中で dayOfWeek() を見て、土日でなければ count を1増やす
  • 最後に currentDate を1日進める

dayOfWeek() が返すのは数字です。
日曜が0、月曜が1、と続いて土曜が6になります。
つまり 0 と 6 を飛ばせば平日だけ数えられます。

祝日は判定できません。
dayOfWeek() は曜日しか見ないので、祝日は平日として数えられます。
祝日も除きたい場合は、SharePoint リストなどに祝日一覧を持たせて、
そこに含まれるかを条件で見る形になります。

⚠️ Do until には上限がある
ループの回数と時間には既定の上限があります。
条件の書き方を間違えて終わらないループを作ると、上限で止まります。
回数を数えるループは、抜ける条件を先に確かめてから本番に入れます。

実務での使いどころ

月次レポートの対象期間|前月1日と前月末をセットで出せば、集計範囲がそのまま決まります。

フォルダの自動作成yyyy年MM月 の形にして SharePoint のフォルダ名にします。

締め日のリマインド|5営業日目の朝に通知、という形にすると、月末の駆け込みが減ります。

期間で絞り込むときの書き方

日付を出せるようになったら、次は期間で絞る場面が来ます。
前月ぶんのデータだけ集計したい、といったケースです。

比較するときは、両方を同じ形にそろえるのが鉄則です。
片方が 2026-04-01、もう片方が 2026/04/01 だと一致しません。

formatDateTime(項目の日付, 'yyyy-MM-dd') と formatDateTime(基準日, 'yyyy-MM-dd') を比べる

大小を比べるときは、yyyy-MM-dd の形なら、文字列のままでも正しく並びます
年→月→日の順に桁がそろっているためです。
逆に M/d/yyyy の形にすると、文字として比べたときに順序が壊れます。

💡 変換した結果は「文字列」になります
convertTimeZone()formatDateTime() を通した値は、
日付そのものではなく文字列として扱われます。
そのあとで addDays() に渡すことはできますが、
書式を短くしすぎると時刻の情報が落ちて、計算が合わなくなることがあります。
計算しているあいだは既定の形のまま持ち、表示の直前に整えるのが安全です。

スケジュール実行の時刻もそろえる

毎朝動かすフローを作るとき、トリガー側にもタイムゾーンの設定があります。
ここが未設定のままだと、想定と違う時刻に動きます。

フローの中で日本時間に変換していても、
起動する時刻そのものがずれていたら意味がありません
繰り返しトリガーのタイムゾーンを日本に設定したうえで、中の計算も日本時間にそろえる。
この2つはセットになります。

月初1日の朝に動かすフローは要注意です。
UTC のままだと、日本の1日午前0時から午前9時のあいだは
UTC ではまだ前月の末日です。
月初判定や月次集計は、ここでいちばん事故が起きます。

そのほか覚えておくと早い関数

時刻を切り落とす|日付だけで比べたいときに使います。

startOfDay(utcNow())

単位を指定して足す|時間や分の単位でも動かせます。

addToTime(utcNow(), 3, 'Hour')

期限までの日数で分ける|締切日と今日を同じ書式にそろえてから比べれば、
「期限切れだけ通知する」といった分岐が作れます。

関数は入れ子にできますが、3段を超えると読めなくなります。
2段までにして、それ以上は作成アクションに分けるのが、結局いちばん速いです。

実際に組んでみる:前月ぶんの月次レポート

ここまでの式を、1本のフローにつなげます。
「毎月1日の朝に、前月ぶんの申請件数を集計してメールで送る」という形です。

1毎月1日に起動させる

繰り返しトリガーを置き、間隔を「月」にして、実行する日を1日、時刻を朝に設定します。
タイムゾーンを日本に設定するのを忘れないでください。

2基準になる「今日」を作る

作成アクションを置いて、日本時間に直した現在時刻を入れます。
名前は「今日(日本時間)」のように、あとで見て分かる形にします。

convertTimeZone(utcNow(), 'UTC', 'Tokyo Standard Time')

3前月1日と前月末を出す

作成アクションをもう2つ置いて、それぞれに式を入れます。
ここで 手順2の出力を基準に使うのがポイントです。utcNow() を直接書くと、
せっかく変換した意味がなくなります。

前月1日:startOfMonth(addMonths(outputs('今日(日本時間)'), -1))

前月末:addDays(startOfMonth(outputs('今日(日本時間)')), -1)

4期間で絞って集計する

一覧を取得したあと、フィルター配列で日付が前月1日以降・前月末以前のものだけ残します。
比べる前に、両方を formatDateTime() で同じ書式にそろえます。

5件名に月を入れて送る

件名に月を入れておくと、受け取る側が一目で分かります。

formatDateTime(outputs('前月1日'), 'yyyy年M月') + 'ぶんの申請件数'

手順2を分けているのは、地味ですが効きます。
式の中に utcNow() を何度も書くと、あとで直すとき、全部を探して回るはめになりました。基準になる日付は1か所で作って、そこから参照する。この形にしてから、直す時間が減りました。

まとめ

📌 この記事のポイント

  • 日数を足し引きしない。月初に丸めてから動かす
  • 前月末・今月末は「翌月/今月の1日から1日戻る」で出す
  • utcNow() は UTC。日本時間で判断するなら先に変換する
  • 営業日は dayOfWeek() で土日を飛ばして数える(日曜が0
  • 祝日は別途リストを持つ必要がある

📚 仕様の出典

utcNow()startOfMonth()addDays()dayOfWeek()(日曜が0)・convertTimeZone()formatDateTime() の引数と戻り値は、ワークフロー式の関数リファレンス(Microsoft Learn)に記載されている内容です。

PA45 は毎週やっています

テーマを1つに絞った45分のオンライン講座です。プログラミング未経験でも、手を動かしながら1つずつ覚えられます。

次回のPA45を見る

※ 本記事は公開日時点の内容です。筆者が実際に試した手順をまとめたもので、Power Automate の仕様は今後変わる可能性があります。
※ 記事の構成・図解の一部は、AIを壁打ち相手にしながら作成しています。

\ 最新情報をチェック /

💌

最新のPower Automate Tipsを毎日チェック

1枚スライドで関数・概念をわかりやすく解説しています。

𝅧 @isamu_Automate をフォロー →

PA45 — 45分でPower Automateを一緒に学ぼう

毎週木曜夜・オンライン・無料のハンズオン講座。初心者歓迎。

次回PA45に参加する →

コメント

PAGE TOP