【GAS】日付・時刻のズレは必ず解決できます!原因の特定方法を解説(スプレッドシート)
日付や時刻が期待通りにならない、数時間ズレてる...、前日が表示される...。GASを実装してスプレッドシートを使用していると、こうした問題に遭遇することがあります。しかし、心配は無用です!この問題は必ず解決できます。
この記事では、日付・時刻のズレの原因を特定し、それを解決する方法を解説します。
日付・時刻のズレが発生する理由
日時が合わない、日付・時刻がズレてしまう主な原因は2つあります。
- タイムゾーンの設定の問題
- 日時データを扱う際の変換や計算が適切でない。(実装ミス)
現状の確認
タイムゾーンの設定は、スクリプトエディタとスプレッドシートの2つがあります。
タイムゾーンを確認するコードは以下の通りです。
function checkTimezone() {
const date = Utilities.formatDate(new Date(), "Asia/Tokyo", "yyyy/MM/dd HH:mm:ss");
console.log("現在の日時: " + date);
// スプレッドシートのタイムゾーンを確認
const ss = SpreadsheetApp.getActiveSpreadsheet()
const spreadsheetTimezone = ss.getSpreadsheetTimeZone();
const userLocale = ss.getSpreadsheetLocale();
console.log("スプレッドシートのタイムゾーン: " + spreadsheetTimezone);
console.log("スプレッドシートの言語設定: " + userLocale);
// スクリプト(GAS)のタイムゾーンを確認
const scriptTimeZone = Session.getScriptTimeZone();
console.log("スクリプト(GAS)のタイムゾーン: " + scriptTimeZone);
}
正しく日本時間が反映される場合は以下のようになります。
現在の日時: 2023/07/03 14:40:23
スプレッドシートのタイムゾーン: Asia/Tokyo
スプレッドシートの言語設定: ja_JP
スクリプト(GAS)のタイムゾーン: Asia/Tokyo
スプレッドシートのタイムゾーンの変更方法
スプレッドシートのメニューバーから[ファイル]→[設定]の順でクリックする。
[言語と地域]を日本、タイムゾーンを(GMT+09:00)Tokyoにする。
コードの実行で変更する場合は以下のようになります。
const ss = SpreadsheetApp.getActiveSpreadsheet()
ss.setSpreadsheetTimeZone("Asia/Tokyo");
ss.setSpreadsheetLocale("ja_JP");
スクリプトエディタ(GAS)のタイムゾーンを変更する
スクリプトエディタを開き、画面左にある[プロジェクトの設定]をクリックする。
タイムゾーンの設定を(GMT+09:00) 日本標準時 – 東京にする。
タイムゾーンが日本以外になるのはどんなときですか?
Googleドライブから新しくスプレッドシートを作成した場合、タイムゾーンは日本時間になっています。日本時間以外になるのは以下のような場合です。
1. Googleフォームと連携したスプレッドシートのタイムゾーンはDili
Googleフォームの回答は自動的にスプレッドシートに反映させることができます。
この時、フォームの管理画面からスプレッドシートを作成すると、タイムゾーンは東ティモールのディリ(Dili)になります。
2. GASで作成したスプレッドシート
以下のようなコードで、新しくスプレッドシートを作成できます。
const ssNew = SpreadsheetApp.create("新しいスプレッドシート");
console.log(ssNew.getUrl());
GASで作成したスプレッドシートはアメリカ時間で設定されています。(未設定・空欄になる場合など様々あります。)
3. その他
GoogleドライブのExcelファイルからスプレッドシートに自動変換した場合や、Googleアカウントの地域・言語、タイムゾーンが日本以外になっている場合も要注意です。
時刻が37分ズレる問題の答え
前述したようにGoogleフォームの管理画面からスプレッドシートを作成するとタイムゾーンはDiliになります。日本と同じ協定世界時間の+9時間(GMT+09:00)の地域なので大丈夫そうに思いますが...。
検証
スプレッドシートのタイムゾーンをDiliのままにして、セルに日付と時刻を入力します。
このセルをgetValueで取得してconsole.logで出力してみると以下のようになります。
Mon Jul 03 2023 00:00:00 GMT+0900 (Japan Standard Time)
Sat Dec 30 1899 00:37:40 GMT+0900 (Japan Standard Time)
日付を正しいですが時刻が37分40秒でズレてるのがわかります。
スクリプトエディタのタイムゾーンをDiliに変えて実行してみます。
Mon Jul 03 2023 00:00:00 GMT+0900 (East Timor Time)
Sat Dec 30 1899 00:00:00 GMT+0822 (East Timor Time)
時刻が正しく00時00分で取得できました。ただよく見るとGMT+0822になってます。正しいGMTは+0900なので約37分ズレてます。これが原因で、セルから時刻を取得したときやUtilities.formatDateを使ってEast Timor TimeからJapan Standard Timeに時刻を変換したときにズレが発生します。
タイムゾーンを韓国・ソウル(seoul)にして試したところ同様の事象になりました。結論としては恐らくスプレッドシート(GAS)のバグだと思います。ズレを防ぐにはスクリプトエディタとスプレッドシートの2つのタイムゾーンを揃えるのがとても重要です。
時刻データの変換や計算ミス、実装コードの誤り
タイムゾーンは正しいのにそれでも日時がズレる場合があります。実装したコードに原因がある可能性が高いです。原因としてよくある3つの例を紹介します。
1. ChatGPTで生成したコードをコピペしてないですか?
現在の日時は以下のようなコードで出力できます。
const date = Utilities.formatDate(new Date(), "Asia/Tokyo", "yyyy/MM/dd HH:mm:ss");
Utilities.formatDateのタイムゾーンをAsia/Tokyoに指定しているので正しい日時が出力されます。ChatGPTにコードを生成してもらうと、このタイムゾーンがGMTになってる場合があります。正しいタイムゾーンを指定しましょう。
2. Dateオブジェクトは月が0~11で表される
1月は0、12月は11になります。
const date1 = new Date();
console.log(Utilities.formatDate(date1, "JST", "yyyy/MM/dd"));
//2023/07/03
const month = date1.getMonth();
console.log("Month: " + month);
//Month: 6
const date2 = new Date(2023, 1, 15); //2月は1
console.log(Utilities.formatDate(date2, "JST", "yyyy/MM/dd"));
//2023/02/15
getMonth()やsetMonth()の処理をするときは注意しましょう。
1月31日の1ヶ月後は何月何日ですか?
各月の日数はバラバラです。以下のコードのように1月31日から月を+1して処理しようとすると、2月31日は存在しないので、2月28日から3日後の3月3日になります。
const date1 = new Date(2023, 0, 31); //1月31日
date1.setMonth(date1.getMonth() + 1);
console.log(Utilities.formatDate(date1, "JST", "yyyy/MM/dd"));
// 2023/03/03
const date2 = new Date(2023, 1, 28); //2月28日
date2.setDate(date2.getDate() + 3);
console.log(Utilities.formatDate(date2, "JST", "yyyy/MM/dd"));
// 2023/03/03
setDate()で1日にしてから、月を+1するなどして対処できます。
解決できません、助けてください!
コメント欄に現状をご記入ください。サポートいたします。
Discussion