こんにちは😊
株式会社プロドウガの@YushiYamamotoです!
らくらくサイトの開発・運営を担当しながら、React.js・Next.js専門のフリーランスエンジニアとしても活動しています❗️
今回は、n8nやJavaScript(Node.js)を触り始めた人が100%の確率で遭遇すると言っても過言ではない、「時間が9時間ズレる問題」についての備忘録です。
「朝9時に実行したはずなのに、ログを見たら深夜0時になっている…👻」
「今日の日付でファイルを作ったはずが、昨日の日付になっている…📅」
こんな経験はありませんか?それはバグではなく、タイムゾーンの呪いです。サクッと解呪する方法をまとめました。
🌏 なぜ9時間ズレるのか?
結論から言うと、n8n(および多くのサーバー環境)の標準時間は「UTC(協定世界時)」だからです。
私たち日本人が生活している「JST(日本標準時)」は、UTCよりも 9時間進んで います。
- UTC: 12:00
- JST: 21:00 (UTC + 9時間)
プログラム上で new Date() をして取得されるのは、基本的にUTC基準のタイムスタンプです。これをそのまま日本感覚で表示しようとすると、「あれ?9時間遅れてる?」という現象が発生します。
🛠️ 解決策1:n8n標準の「Luxon」を使う(推奨)
n8nには、日付操作の強力なライブラリである Luxon が組み込まれています。
Codeノード(JavaScript)内では、わざわざ npm install しなくても、n8n独自の変数 $now や DateTime オブジェクトを使って簡単に変換できます。
最も簡単な書き方
// 現在時刻をJST(東京)のタイムゾーンでフォーマットする
const jstTime = $now.setZone('Asia/Tokyo').toFormat('yyyy-MM-dd HH:mm:ss');
return { jstTime };
$now とは?
n8nのCodeノード内で使える特別なオブジェクトで、ワークフローが実行された瞬間の日時(LuxonのDateTimeオブジェクト)を持っています。これを使うのが一番確実です。
🛠️ 解決策2:バニラJS(標準機能)で戦う
n8n以外の環境(純粋なNode.jsなど)や、Luxonを使わずに標準の Date オブジェクトだけで解決したい場合は、toLocaleString を使います。
const date = new Date();
// オプションでタイムゾーンを指定する
const jstString = date.toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' });
return { jstString };
単純に date.setHours(date.getHours() + 9) のように時間を足し算する方法もありますが、うるう秒や将来的な変更に対応できない場合があるため、可能な限りタイムゾーン指定機能を使うことをお勧めします。
💻 実践コード:n8n Codeノード用サンプル
実際にn8nの「Codeノード」に貼り付けて、挙動の違いを確認できるサンプルコードです。
n8n_timezone_test.js
// n8nのCodeノードで実行してください
// 1. そのままのDate (UTCになることが多い)
const rawDate = new Date();
// 2. 手動で9時間足す (非推奨だがよく見るやつ)
const manualDate = new Date(rawDate.getTime() + 9 * 60 * 60 * 1000);
// 3. toLocaleStringを使う (標準JSでの正攻法)
const localeString = rawDate.toLocaleString('ja-JP', {
timeZone: 'Asia/Tokyo',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
// 4. n8n組み込みのLuxonを使う (推奨!一番楽)
// $now はn8nが提供するLuxon DateTimeオブジェクトです
const luxonTime = $now.setZone('Asia/Tokyo').toFormat('yyyy-MM-dd HH:mm:ss');
// 5. 昨日の日付を取得したい場合 (Luxonならチェーンメソッドで書ける)
const yesterday = $now.minus({ days: 1 }).setZone('Asia/Tokyo').toFormat('yyyy-MM-dd');
return [
{
json: {
label: "1. UTC (そのまま)",
value: rawDate.toISOString() // 末尾にZがつくのはUTC
}
},
{
json: {
label: "2. 手動計算 (JST)",
value: manualDate.toISOString().replace('Z', '') // 無理やりJSTの値にしたもの
}
},
{
json: {
label: "3. toLocaleString (JST)",
value: localeString
}
},
{
json: {
label: "4. Luxon (JST) ★推奨",
value: luxonTime
}
},
{
json: {
label: "5. 昨日 (Luxon)",
value: yesterday
}
}
];
⚙️ 環境設定:Dockerで動かしている場合
もしあなたがn8nをDocker(セルフホスト)で動かしているなら、環境変数でデフォルトのタイムゾーンを設定してしまうのが手っ取り早いです。
docker-compose.yml に以下を追加します。
environment:
- GENERIC_TIMEZONE=Asia/Tokyo
- TZ=Asia/Tokyo
注意点
GENERIC_TIMEZONE を設定しても、Cron(Scheduleノード)の実行時間はJSTになりますが、Codeノード内で new Date() をした際の結果は依然としてUTC(またはコンテナのシステム時刻)になる場合があります。
コード内で日時を扱う際は、やはり 解決策1(Luxon) で明示的にタイムゾーンを指定するのが最も安全です。
まとめ
- n8nやNode.jsは基本的に UTC(世界標準時) で動いている。
- 日本時間は UTC + 9時間。
- n8n内なら
$now.setZone('Asia/Tokyo')を使うのが最強の解決策。 - Docker環境なら環境変数
GENERIC_TIMEZONEも忘れずに。
これで「日付がズレててデータが取れない!」という呪いからは解放です🧙♂️
良き自動化ライフを!
最後に:業務委託のご相談を承ります
私は業務委託エンジニアとしてWEB制作やシステム開発を請け負っています。最新技術を活用したレスポンシブなWebサイト制作、インタラクティブなアプリケーション開発、API連携など幅広いご要望に対応可能です。
「課題解決に向けた即戦力が欲しい」「高品質なWeb制作を依頼したい」という方は、お気軽にご相談ください。一緒にビジネスの成長を目指しましょう!
👉 ポートフォリオ
🌳 らくらくサイト