GASで日付を特定フォーマット(yyyy/MM/dd)に変換する方法

GAS

※本記事はプロモーションを含みます

目次

Google Apps Script(GAS)でスプレッドシートの業務自動化を組んでいると、日付の扱いには必ずと言っていいほど悩まされます。なぜなら、セルから取得した日付データやスクリプト実行時に生成した現在時刻をそのまま文字列結合しようとすると、長い英語表記のタイムスタンプに変換されてしまうからです。ただし、意図せず前日の日付になってしまうトラブルも頻繁に発生します。なので、この記事ではGASで日付のフォーマット変換を確実に行う手順を整理します。というのは、狙い通りの「yyyy/MM/dd」や「yyyy/MM/dd HH:mm:ss」といった形式へ安全に変換する方法を、皆様に知っていただく必要があるからです。

new Date() をそのまま文字列化して起きていた悲劇と整形後の状態

Google Apps Scriptで日付データを扱う際、初心者がもっとも直面しやすい問題はDateオブジェクトを文字列として出力したときの見た目の崩れです。なぜなら、実行時のログに日付を残そうとしたりスプレッドシートの特定セルに日付を書き込もうとしたりして、標準の生成処理である new Date() をそのまま文字列として連結してしまうからです。ただし、何も手を加えていない状態のDateオブジェクトを文字列として評価すると、「Wed May 15 2024 14:30:00 GMT+0900 (Japan Standard Time)」のような非常に冗長な文字列になります。なので、そのまま使うと予期せぬ表示崩れにつながります。というのは、文字列の長さが原因でシートのレイアウトが乱れてしまうからです。

この状態のままスプレッドシートのセルへ流し込むと、セルの表示幅を大幅に超えてしまってシートの見栄えが一気に崩れます。ただし、文字列として認識されて後続の計算式や日付フィルタが効かなくなる原因にもなります。なので、日付データの取り扱いには細心の注意を払いましょう。というのは、この日付文字列を使って「売上管理_20240515.pdf」のようなファイル名を作ろうとした場合にも大きなトラブルが起きるからです。Googleドライブの命名規則においてコロンや空白が含まれることでエラーが発生します。ただし、極端に長くて視認性の悪いファイル名が作られてしまうこともあります。なので、実務の運用に耐えられないファイルが量産されることになります。

一方、適切な日付変換処理を通したあとはデータが綺麗に整います。なぜなら、new Date() によって生成された内部的なタイムスタンプから必要な要素(年、月、日、時、分、秒)だけを正確に取り出せるからです。ただし、「2024/05/15」や「2024-05-15 14:30:00」といった無駄のない文字列に一発で置き換えることができます。なので、桁数も2桁固定(ゼロ埋め)で綺麗に整えられます。というのは、日報シートの見出しやチャットツールへの通知本文やバックアップフォルダのフォルダ名など、どの用途に引き渡しても崩れない強固なデータ構造が完成するからです。処理前と処理後では、データの安全性も保守性もまったく異なる次元になります。したがって、正しいコードの書き方をしっかり確認しましょう。

日付を期待通りの文字列に書き換える標準的な変換手順

GASでDateオブジェクトを特定フォーマットに変換する際、JavaScript標準のメソッド(getFullYearやgetMonthなど)を自力で組み合わせてゼロ埋め処理を書く必要はありません。なぜなら、Google Apps Scriptには標準で Utilities.formatDate という極めて強力なツールが用意されているからです。ただし、これを利用するのがGAS環境における最も確実で標準的なアプローチになります。なので、日付の整形を行う際はこのメソッドを優先的に活用しましょう。というのは、無駄な処理を記述せずにシンプルなコードで目的の文字列を得られるからです。

このメソッドは、変換したいDateオブジェクトと適用するタイムゾーンと指定したいフォーマットパターンの3つの引数を受け取ります。ただし、これを実行するタイミングはセルから取り出した日付を他のシステム(SlackやChatworkなどの通知、あるいは外部APIへのリクエストボディ)に渡す直前が最適です。なので、ドライブ上に新規作成するファイル名やシート名に日付文字列を埋め込む瞬間にも活用しましょう。というのは、内部計算を行う間はDateオブジェクトのまま保持しておき、人間が見る場所や外部の固定フォーマットに合わせる最後の境界線でこの変換を挟むのが定石だからです。変換のタイミングを間違えないようにコードの記述位置を確認しましょう。

const now = new Date();
const formatted = Utilities.formatDate(now, "Asia/Tokyo", "yyyy-MM-dd HH:mm:ss");
Logger.log(formatted);

上記のコードは現在時刻を取得した上で日本の標準時に合わせたフォーマット変換を行い、ログに出力する一連の流れです。なぜなら、これを実行するとログには「2024-05-15 14:30:00」といった整然とした文字列が出力されるからです。ただし、区切り文字をスラッシュにしたい場合は第3引数を「yyyy/MM/dd」や「yyyy/MM/dd HH:mm:ss」に変更するだけで即座に対応可能です。なので、自前で月加算(+1)やゼロ埋めの三項演算子を書く必要は一切ありません。というのは、コードの可読性と保守性が大幅に向上するからです。プログラムを書く際は記述内容を毎回確認しましょう。

タイムゾーンの不一致で日付が1日ズレるトラブルと安全な指定

Utilities.formatDate を使い始めた人が必ずと言っていいほど一度は直面するのが、「日付がなぜか1日前の日付(あるいは前日の夜)にずれてしまう」というタイムゾーン起因のトラブルです。なぜなら、このズレは第2引数に渡すタイムゾーンの設定とスクリプト実行環境が認識している基準時刻の乖離によって引き起こされるからです。ただし、正しく設定を行えばこの問題は簡単に防ぐことができます。なので、タイムゾーンの指定方法を正しく理解しましょう。というのは、時刻の計算ミスは業務上の重大なエラーに直結するからです。

JavaScriptの内部では、日時は協定世界時(UTC)を基準としたエポックミリ秒として管理されています。ただし、日本標準時(JST)はUTCよりも9時間進んでいます(UTC+9)。なので、もし第2引数に指定したタイムゾーンがデフォルトのUTCのままになっていたりアメリカなどの別のタイムゾーンとして評価されてしまうと問題が生じます。というのは、日本時間の午前0時から午前8時59分までの間に実行されたスクリプトは、すべて「前日の日付」として文字列化されてしまうからです。月末や月初に自動実行される請求書発行スクリプトなどでこのズレが発生すると、当月の日付になるはずが先月末の日付で書類が作られてしまう致命的な業務事故につながります。プログラムを運用する前に設定内容をしっかり確認しましょう。

このズレを確実に回避するためのアプローチは2つあります。なぜなら、1つ目は先ほどのコード例のように第2引数へ文字列として明示的に “Asia/Tokyo” をハードコードして渡す方法だからです。ただし、日本国内の業務で完結するツールであれば環境設定に依存せずに常に日本時間で変換されます。なので、最も手堅くズレを防ぐことができます。というのは、コード上で直接設定を指定することで予期せぬ挙動を排除できるからです。

2つ目は、プロジェクトの設定に連動させるために Session.getScriptTimeZone() を指定する方法です。なぜなら、このメソッドを使うとスクリプトプロジェクトに設定されているタイムゾーンを動的に取得して第2引数に渡してくれるからです。ただし、この方法を使う場合は「appsscript.json(マニフェストファイル)」に記述されている timeZone が正しく “Asia/Tokyo” になっていることを事前に確認しておく必要があります。なので、設定ファイルの記述内容を必ずチェックしましょう。というのは、新規で作成したスクリプトファイルの設定がまれに “America/New_York” や “Etc/GMT” になっているケースがあり、その状態で Session.getScriptTimeZone() を使うと9時間のズレが発生して前日問題が再発するからです。基本的には “Asia/Tokyo” を直接指定するか、マニフェストの設定を日本時間に固定した上で Session.getScriptTimeZone() を使う運用のどちらかに統一して事故を防止しましょう。

スプレッドシート出力やファイル名生成でフォーマット崩れを起こさない実践例

日付のフォーマット変換は、単にログに出すだけでなく実際の業務ワークフローに組み込んでこそ真価を発揮します。なぜなら、特によく使われるのが「日付を含むファイル名の自動生成」と「スプレッドシートへの履歴追記」の2つの場面だからです。ただし、それぞれの場面で正しい指定を行わないと予期せぬエラーが発生します。なので、フォーマットが崩れる原因とその回避策について深く理解しましょう。というのは、適切な実装パターンを知ることで安全なスクリプトを記述できるようになるからです。

まず、ファイル名やバックアップフォルダ名に日付を埋め込むケースです。なぜなら、日次でスプレッドシートをPDF化してGoogleドライブに保存するような運用では、ファイル名に「yyyyMMdd」や「yyyy-MM-dd」といった形式で日付を付与するからです。ただし、ここでUtilities.formatDateを使って変換せずにDateオブジェクトの文字列をそのまま埋め込むと、先述の通り空白やコロンが含まれてしまいます。なので、他のシステムとの連携時にURLエンコードが崩れたりダウンロードしたローカル環境で不正なファイル名として警告が出たりします。というのは、OSごとのファイル名制限に引っかかってしまうからです。さらに、時分秒までファイル名に含めたい場合に「HH:mm:ss」と指定してしまうと、WindowsなどのOSではコロン(:)がファイル名に使えないためローカル同期時にエラーが発生する要因になります。そのため、ファイル名用途では「yyyyMMdd_HHmmss」のようにハイフンやアンダースコアのみで構成するフォーマットを指定しましょう。

次に、スプレッドシートのセルへ日付を書き込むケースです。なぜなら、スプレッドシートに対して Utilities.formatDate で生成した「2024/05/15」という文字列を setValue() で書き込むと、スプレッドシート側の仕様によって自動的に「日付データ(シリアル値)」として再解釈されることがあるからです。ただし、セルの表示形式が「yyyy/M/d」など別のもので設定されていると、せっかくスクリプト側でゼロ埋めした「2024/05/15」がシート上では「2024/5/15」と表示されてしまい、見た目の統一感が失われることがあります。なので、出力結果の見た目を事前に想定しておく必要があります。というのは、表示形式の自動変換によって意図しない形式へ書き換えられてしまうからです。見た目を完全に文字列として固定したい場合は、セルの表示形式をあらかじめプレーンテキストにしておくか、書き込む文字列の先頭にシングルクォートを付与しましょう。あるいはセル側の setNumberFormat(“yyyy/mm/dd”) をスクリプトから明示的に呼び出して表示形式そのものを制御しましょう。

年月日や時刻のフォーマットパターンでよくある指定ミス

Utilities.formatDate の第3引数で渡すフォーマット文字列は、Javaの SimpleDateFormat の仕様に準拠しています。なぜなら、大文字と小文字のたった1文字の違いによって意図しない値が出力される原因になるからです。ただし、正しいパターン文字の指定方法を把握していればミスを防ぐことができます。なので、よくある指定ミスとその理由をあらかじめ確認しておきましょう。というのは、間違った識別子を使うとプログラムが不具合を起こすからです。

タイトルとURLをコピーしました