Cara Memperbaiki Zona Waktu Schedule Trigger n8n
n8n self-hosted membaca tiga pengaturan zona waktu. Pelajari cara mengatur TZ, GENERIC_TIMEZONE, dan zona workflow agar Schedule Trigger tidak meleset berjam-jam.
Mengapa pemicu jadwal n8n berjalan pada jam yang salah
Pemicu jadwal n8n berjalan pada jam yang salah karena n8n membaca zona waktu dari tiga tempat terpisah. Memperbaiki satu tempat hanya memperbaiki sebagian masalah. Ketiga tempat tersebut adalah variabel TZ milik container, default instance GENERIC_TIMEZONE, dan zona waktu yang ditetapkan dalam workflow individual. Tetapkan ketiganya satu kali agar setiap jadwal yang Anda buat setelahnya berjalan pada waktu yang diharapkan.
Luruskan satu asumsi terlebih dahulu. n8n self-hosted yang baru tidak menjadwalkan tugas dalam UTC (waktu universal terkoordinasi). Jam container menggunakan UTC karena image resmi tidak menetapkan TZ. Penjadwalan merupakan lapisan terpisah, dan default GENERIC_TIMEZONE yang didokumentasikan untuk n8n adalah America/New_York (per Agustus 2026). Karena itu, instance yang belum dikonfigurasi menjalankan Schedule Triggers berdasarkan waktu New York. Itulah sebabnya selisih waktu yang dilaporkan sering tidak sesuai dengan perbedaan lokasi mereka sendiri terhadap UTC. Pemilik di Berlin yang menetapkan jadwal pukul 06:00 akan mendapat waktu 12:00 setempat, dan 11:00 selama beberapa minggu pada bulan Maret ketika Amerika Serikat sudah beralih ke daylight saving time, tetapi Eropa belum.
Tiga lapisan zona waktu, dan lapisan yang digunakan
TZ adalah zona waktu sistem operasi di dalam container. Dokumentasi n8n menjelaskannya sebagai variabel yang menetapkan zona waktu sistem untuk menentukan hasil skrip dan perintah seperti date. Variabel ini menentukan hasil yang dicetak date di dalam container, timestamp yang dicatat pada baris log container, hasil new Date() di dalam Code node, serta zona waktu yang dilihat skrip shell apa pun yang Anda jalankan di dalamnya. Variabel ini tidak memengaruhi waktu Schedule Trigger berjalan.
GENERIC_TIMEZONE adalah zona waktu instance n8n. Dokumentasi menyebutnya sebagai zona waktu instance n8n dan menjelaskan bahwa zona waktu ini penting untuk node penjadwalan seperti Cron. Cron di sini berarti sintaks penjadwalan berbasis waktu standar. n8n menyediakan sintaks ini sebagai opsi Custom (Cron) pada Schedule Trigger.
Zona waktu workflow ditetapkan untuk setiap workflow. Buka workflow pada canvas, pilih tiga titik di sudut kanan atas, pilih Settings, lalu ubah nilai Timezone. Pengaturan ini menggantikan GENERIC_TIMEZONE hanya untuk workflow tersebut.
Untuk Schedule Trigger, urutannya tetap. n8n menggunakan zona waktu workflow jika workflow memilikinya. Jika tidak, n8n menggunakan zona waktu instance dari GENERIC_TIMEZONE. Jika itu juga tidak tersedia, n8n menggunakan nilai bawaan America/New_York. TZ tidak diperiksa pada tahap mana pun dalam keputusan tersebut.
Untuk tanggal di dalam node, jawabannya bergantung pada jam yang diminta oleh kode. Luxon, yaitu pustaka tanggal yang digunakan oleh ekspresi n8n, menggunakan zona waktu n8n. Karena itu, $now dan $today mengikuti urutan workflow lalu instance yang sama seperti trigger. JavaScript new Date() biasa di dalam Code node meminta zona waktu sistem operasi, sehingga mengikuti TZ. Perbedaan ini adalah sumber sebagian besar kebingungan: trigger dapat berjalan dengan benar, sementara setiap timestamp yang ditulis workflow meleset beberapa jam.
Atur ketiganya dalam file Compose
Letakkan TZ dan GENERIC_TIMEZONE bersebelahan dalam file agar tidak ada yang mengatur salah satunya lalu melupakan yang lain. Fragmen di bawah ini adalah bagian terkait zona waktu dari service yang berfungsi. Bagian lain dari file, yaitu reverse proxy dan sertifikat, berasal dari n8n yang di-hosting sendiri pada VPS di balik HTTPS.
services:
n8n:
image: docker.n8n.io/n8nio/n8n
restart: unless-stopped
ports:
- "127.0.0.1:5678:5678"
environment:
- GENERIC_TIMEZONE=Europe/Berlin
- TZ=Europe/Berlin
- N8N_RUNNERS_ENABLED=true
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_data:Terapkan perubahan dengan docker compose up -d, bukan docker compose restart. Restart menjalankan kembali container yang sama dengan environment saat container tersebut dibuat. Akibatnya, perubahan pada file tidak diterapkan ke proses yang sedang berjalan. up -d mendeteksi perubahan environment lalu membuat ulang container. Jika Anda menyimpan nilai ini dalam env file, bukan secara inline, aturan pembuatan ulang yang sama tetap berlaku. Panduan penanganan env file dan secrets Compose menjelaskan lokasi pembacaan file tersebut.
Gunakan nama zona IANA (Internet Assigned Numbers Authority) dalam format Region/City, misalnya Europe/Berlin atau America/Sao_Paulo. Nama tersebut menyertakan aturan daylight saving untuk lokasi itu, sehingga offset berubah saat jam lokal berubah. Nama dengan offset tetap seperti Etc/GMT+5 tidak pernah berubah mengikuti musim, dan tandanya terbalik dari perkiraan Anda. Jalankan LC_ALL=C TZ=Etc/GMT+5 date +%z untuk menampilkan -0500. Hindari nama tersebut.
Mengapa hanya mengatur salah satunya membuat perbaikan tidak tuntas
Atur GENERIC_TIMEZONE saja. Schedule Trigger berjalan pada jam yang Anda inginkan, tetapi semua komponen yang membaca sistem operasi tetap menggunakan UTC. Code node yang memanggil new Date().toString() mengembalikan string UTC, baris log container diberi stempel waktu UTC, dan nama file yang dibuat berdasarkan jam sistem berganti pada tengah malam yang salah.
Atur TZ saja. Yang terjadi justru sebaliknya. docker compose exec n8n date menampilkan waktu lokal dan terlihat berhasil, tetapi Schedule Trigger tetap menggunakan America/New_York dan berjalan enam jam lebih awal atau lebih lambat dari jam yang Anda tentukan. Versi ini paling banyak membuang waktu karena pemeriksaan yang biasanya dilakukan pertama kali kini berhasil.
Atur timezone workflow, lalu ubah GENERIC_TIMEZONE setelahnya. Workflow tersebut mengabaikan perubahan itu. Nilai pada workflow menjadi prioritas dan tetap berlaku sampai seseorang membuka pengaturan workflow tersebut. Jika satu workflow berjalan pada jam yang tidak wajar sementara workflow lain berjalan normal, hampir selalu penyebabnya adalah hal ini.
Periksa waktu pada jam, bukan berdasarkan perkiraan
Bandingkan host dan container secara langsung.
date
docker compose exec n8n date
docker compose exec n8n printenv TZ GENERIC_TIMEZONEDua perintah pertama seharusnya menampilkan waktu aktual yang sama setelah TZ ditetapkan. printenv menampilkan satu baris untuk setiap variabel yang ada. Jadi, dua baris output berarti keduanya telah ditetapkan, sedangkan satu baris berarti Anda sedang melihat kondisi yang baru diperbaiki sebagian.
Selanjutnya, tanyakan langsung kepada n8n dari dalam workflow. Shell container tidak dapat memberi tahu zona waktu pada tingkat workflow. Tambahkan node Code ke workflow yang bermasalah, lalu jalankan satu kali dengan Execute Workflow.
return [
{
json: {
n8n_time: $now.toISO(),
n8n_zone: $now.zoneName,
system_time: new Date().toString(),
},
},
];n8n_zone adalah zona yang akan digunakan Schedule Trigger pada workflow ini. Nilainya telah ditentukan berdasarkan urutan workflow lalu instance, sehingga langsung menjawab pertanyaan tersebut. system_time berisi zona milik container yang diperoleh dari TZ. Jalankan pemeriksaan ini pada workflow yang bermasalah, bukan pada workflow baru, karena pengaturan tingkat workflow ikut tersimpan bersama workflow. Jika kedua nilai tersebut berbeda, Anda telah menemukan masalahnya tanpa perlu membuka satu pun file konfigurasi.
Ekspresi cron pada node Schedule Trigger
Schedule Trigger menyediakan interval tetap mulai dari detik hingga bulan, serta opsi Custom (Cron) untuk kebutuhan yang tidak tercakup oleh interval tersebut. Ekspresi cron dibaca dalam zona waktu workflow yang telah ditetapkan, sehingga 0 6 * * * berarti pukul 06:00 di zona tersebut, bukan pukul 06:00 UTC. Ekspresi lima field dari crontab guru dapat ditempel apa adanya. n8n juga menerima field detik opsional, yang dalam tabel field pada dokumentasi ditempatkan di awal: detik, menit, jam, hari dalam bulan, bulan, hari dalam minggu.
Jangan mengodekan offset secara manual. Menulis 0 4 * * * pada instance UTC untuk mencapai pukul 06:00 di Berlin benar pada musim dingin, tetapi terlambat satu jam sepanjang musim panas, karena Berlin menggunakan UTC+1 pada musim dingin dan UTC+2 pada musim panas. Tetapkan zonanya, lalu tulis jam lokal yang benar-benar Anda maksud.
Dampak daylight saving time terhadap job yang dijadwalkan pada 02:30
Waktu lokal pada jam dinding bukan instant yang terjamin. Dua kali setahun, satu jam menghilang dan satu jam berulang. Setiap job yang dijadwalkan dalam rentang tersebut akan terdampak. Anda dapat mengamati hal ini dengan date pada sistem Linux apa pun, tanpa melibatkan n8n.
LC_ALL=C TZ=Europe/Berlin date -d '2027-03-28 02:30'date: invalid date '2027-03-28 02:30'Itu bukan kesalahan ketik pada perintah. Pada 2027-03-28, jam Berlin bergerak langsung dari 02:00 ke 03:00. Karena itu, waktu lokal 02:30 tidak ada pada hari tersebut, dan date menolak mengubahnya menjadi instant. Job yang ditetapkan pada waktu lokal 02:30 tidak memiliki waktu untuk dijalankan. Waktu di sekitarnya tetap valid: date -d '2027-03-28 01:30' dikenali sebagai CET dan date -d '2027-03-28 03:30' dikenali sebagai CEST.
Peralihan pada musim gugur merupakan kebalikannya. Pada 2027-10-31, jam Berlin mundur dari 03:00 ke 02:00. Karena itu, waktu 02:30 terjadi dua kali.
LC_ALL=C TZ=Europe/Berlin date -d '2027-10-31 02:30 CEST' '+%s'
LC_ALL=C TZ=Europe/Berlin date -d '2027-10-31 02:30 CET' '+%s'1824942600
1824946200Ada dua instant berbeda yang sama-sama disebut 02:30 waktu lokal, dengan jarak 3600 detik. Job yang ditetapkan pada waktu tersebut dapat berjalan dua kali atau berjalan sekali pada waktu yang tidak dipilih siapa pun. Keduanya bukan hasil yang diharapkan untuk proses billing atau rotasi backup. Pindahkan jadwal ke luar rentang tersebut. Di sebagian besar zona Eropa dan Amerika Utara, rentang berisiko adalah 00:00 hingga 03:00 waktu lokal.
Jadwalkan infrastruktur dalam UTC dan tampilkan waktu lokal kepada pengguna
Jawaban baku memisahkan dua fungsi timezone. Mesin memerlukan interval yang konsisten. Pengguna memerlukan waktu yang mudah dibaca.
- Untuk pekerjaan yang tidak dipantau siapa pun, atur timezone workflow ke UTC. Backup, pemanasan cache, pengiriman log, dan pembuatan laporan termasuk dalam kategori ini. Dalam UTC, jarak antara dua eksekusi selalu sama persis seperti yang Anda tetapkan pada setiap hari dalam setahun karena UTC tidak menggunakan daylight saving.
- Untuk pekerjaan yang dibaca oleh seseorang, simpan jadwal dalam UTC dan lakukan konversi saat menampilkan hasil. Satu ekspresi sudah cukup:
{{ $now.setZone('Europe/Berlin').toFormat('yyyy-MM-dd HH:mm') }}menempatkan waktu lokal di isi pesan, sementara trigger tetap konsisten.
Pemisahan yang sama berlaku di luar n8n. Jika sebagian automation Anda berjalan sebagai service dan timer systemd pada VPS, baris OnCalendar dibaca berdasarkan timezone sistem, yang merupakan clock keempat dengan pengaturan tersendiri. Dengan mempertahankan semua scheduler pada UTC, Anda hanya perlu mengingat satu aturan, bukan empat. Hal ini juga penting untuk apa pun yang merangkum suatu periode karena workflow AI agent n8n yang diminta menghitung angka kemarin akan menggunakan rentang 24 jam yang berbeda tanpa terlihat, bergantung pada zone yang digunakan.
Mode kegagalan dan output yang akan Anda lihat
Semua proses berjalan sekitar enam jam lebih awal atau lebih lambat. GENERIC_TIMEZONE belum pernah ditetapkan, sehingga nilai bawaan America/New_York berlaku. docker compose exec n8n printenv GENERIC_TIMEZONE tidak menampilkan apa pun. Tetapkan nilainya, lalu buat ulang container.
Anda mengedit file Compose, tetapi tidak ada perubahan. Anda menjalankan docker compose restart, sehingga container tetap menggunakan environment awalnya. Jalankan docker compose up -d, lalu konfirmasikan dengan docker compose exec n8n printenv TZ.
Pemicu sudah benar, tetapi timestamp salah. Hanya GENERIC_TIMEZONE yang ditetapkan. new Date() di node Code tetap membaca UTC dari sistem operasi. Tetapkan TZ dengan nilai yang sama, lalu buat ulang.
Satu workflow mengabaikan pengaturan instance. Workflow tersebut memiliki timezone sendiri dalam pengaturannya, dan pengaturan itu mengesampingkan GENERIC_TIMEZONE. Buka canvas, klik tiga titik, pilih Settings, lalu Timezone.
Job harian berjalan dua kali atau melewati satu hari pada suatu waktu tahun ini. Jam terjadwalnya berada dalam periode perubahan daylight saving. Pindahkan jam tersebut, atau ubah workflow itu agar menggunakan UTC.
FAQ
Mengapa pemicu jadwal n8n saya berjalan pada jam yang salah?
Workflow menggunakan zona waktu yang berbeda dari yang Anda perkirakan. n8n menggunakan zona waktu workflow jika telah ditetapkan. Jika belum, n8n menggunakan zona waktu instance dari GENERIC_TIMEZONE. Jika itu juga belum ditetapkan, n8n menggunakan nilai bawaan America/New_York. Instance self-hosted yang tidak menetapkan GENERIC_TIMEZONE akan menjadwalkan berdasarkan waktu New York, bukan UTC. Karena itu, selisih waktunya jarang sesuai dengan perbedaan waktu Anda sendiri terhadap UTC. Jalankan docker compose exec n8n printenv GENERIC_TIMEZONE. Tidak ada output berarti nilai tersebut belum pernah ditetapkan.
Apa perbedaan antara TZ dan GENERIC_TIMEZONE di n8n?
TZ adalah zona waktu sistem operasi di dalam container. Nilai ini menentukan hasil date di dalam container, timestamp pada baris log container, hasil new Date() di dalam Code node, serta hal yang dilihat oleh skrip apa pun yang Anda jalankan di dalamnya. GENERIC_TIMEZONE adalah zona waktu instance n8n. Nilai ini digunakan oleh node jadwal dan ekspresi Luxon seperti $now. Menetapkan salah satunya tanpa menetapkan yang lain dapat menghasilkan pemicu yang benar dengan timestamp yang salah, atau timestamp yang benar dengan pemicu yang berjalan beberapa jam dari waktu yang seharusnya. Tetapkan keduanya ke nilai yang sama.
Sebaiknya saya menetapkan zona waktu workflow atau GENERIC_TIMEZONE?
Tetapkan GENERIC_TIMEZONE sebagai nilai default untuk seluruh instance. Gunakan pengaturan per-workflow hanya jika suatu workflow memang berjalan di zona waktu lain. Nilai workflow mengesampingkan nilai instance. Nilai tersebut juga tidak mengikuti perubahan GENERIC_TIMEZONE di kemudian hari. Karena itu, override per-workflow yang terlupakan akan sulit dilacak beberapa bulan kemudian.
Apa yang terjadi pada job yang dijadwalkan pada 02:30 saat jam berubah?
Waktu lokal tersebut dapat hilang atau muncul dua kali. LC_ALL=C TZ=Europe/Berlin date -d '2027-03-28 02:30' mengembalikan date: invalid date '2027-03-28 02:30' karena jam Berlin maju dari 02:00 ke 03:00 pada hari itu. Pada 2027-10-31, pembacaan jam lokal yang sama mengacu pada dua waktu berbeda dengan jarak satu jam. Hindari menjadwalkan pekerjaan pada rentang 00:00 hingga 03:00 waktu lokal, atau tetapkan workflow ke UTC dan konversikan ke waktu lokal hanya saat dibaca oleh seseorang.