วิธีแก้ปัญหา n8n Schedule Trigger ทำงานผิดเวลา
สาเหตุที่ n8n ทำงานผิดเวลาเกิดจากการตั้งค่าโซนเวลาไม่ตรงกันทั้ง 3 จุด คือ TZ, GENERIC_TIMEZONE และ Workflow Zone เรียนรู้วิธีตั้งค่าให้ถูกต้องเพื่อป้องกันปัญหาเวลาคลาดเคลื่อน
เหตุใด Schedule Trigger ของ n8n จึงทำงานผิดเวลา
Schedule Trigger ของ n8n ทำงานผิดเวลาเนื่องจาก n8n อ่านค่าโซนเวลาจาก 3 แหล่งที่แยกจากกัน การแก้ไขเพียงจุดเดียวจึงแก้ปัญหาได้ไม่ครบถ้วน แหล่งข้อมูลทั้ง 3 แห่ง ได้แก่ ตัวแปร TZ ของคอนเทนเนอร์, ค่าเริ่มต้น GENERIC_TIMEZONE ของอินสแตนซ์ และโซนเวลาที่ตั้งค่าไว้ภายใน Workflow แต่ละรายการ หากคุณตั้งค่าทั้ง 3 จุดให้ตรงกันตั้งแต่แรก Schedule ทุกรายการที่คุณสร้างหลังจากนั้นจะทำงานในเวลาที่คุณต้องการ
ก่อนอื่นต้องแก้ไขความเข้าใจผิดที่พบบ่อย n8n ที่ติดตั้งแบบ self-hosted ไม่ได้ตั้งเวลาตาม UTC (Coordinated Universal Time) โดยค่าเริ่มต้น นาฬิกาของคอนเทนเนอร์เป็น UTC เนื่องจากอิมเมจอย่างเป็นทางการไม่ได้กำหนดค่า TZ ไว้ แต่การตั้งเวลาเป็นอีกเลเยอร์หนึ่ง ซึ่งค่าเริ่มต้นตามเอกสารของ n8n สำหรับ GENERIC_TIMEZONE คือ America/New_York (ข้อมูล ณ เดือนสิงหาคม 2026) ดังนั้นอินสแตนซ์ที่ไม่ได้ปรับแต่งจะสั่งให้ Schedule Trigger ทำงานตามเวลาของนิวยอร์ก นี่คือสาเหตุที่ส่วนต่างของเวลาที่ผู้ใช้รายงานมักไม่ตรงกับระยะห่างจาก UTC ของตนเอง ตัวอย่างเช่น ผู้ใช้ในเบอร์ลินที่ตั้งเวลาไว้ 06:00 น. จะพบว่างานทำงานจริงตอน 12:00 น. ตามเวลาท้องถิ่น และเป็น 11:00 น. ในช่วงสัปดาห์ของเดือนมีนาคมที่สหรัฐอเมริกาปรับเวลา Daylight Saving Time แล้ว แต่ยุโรปยังไม่ได้ปรับ
เลเยอร์ของเขตเวลาทั้งสามและลำดับความสำคัญ
TZ คือเขตเวลาของระบบปฏิบัติการภายในคอนเทนเนอร์ เอกสารของ n8n อธิบายว่าตัวแปรนี้ทำหน้าที่กำหนดเขตเวลาของระบบเพื่อควบคุมผลลัพธ์ของสคริปต์และคำสั่งอย่างเช่น date โดยจะเป็นตัวตัดสินว่า date จะแสดงผลอย่างไรภายในคอนเทนเนอร์, ประทับเวลาใดที่จะปรากฏในบรรทัด log ของคอนเทนเนอร์, new Date() จะส่งค่าใดกลับมาในโหนด Code และสคริปต์ shell ใดๆ ที่คุณรันภายในนั้นจะมองเห็นเวลาใด ทั้งนี้ตัวแปรดังกล่าวไม่มีผลต่อเวลาที่ Schedule Trigger จะทำงาน
GENERIC_TIMEZONE คือเขตเวลาของอินสแตนซ์ n8n เอกสารระบุว่าเป็นเขตเวลาของอินสแตนซ์ n8n และเน้นย้ำว่ามีความสำคัญสำหรับโหนดกำหนดเวลาอย่างเช่น Cron โดยในที่นี้ Cron หมายถึงไวยากรณ์การกำหนดเวลาตามมาตรฐาน ซึ่ง n8n เปิดให้ใช้งานผ่านตัวเลือก Custom (Cron) ใน Schedule Trigger
เขตเวลาของเวิร์กโฟลว์จะถูกกำหนดแยกกันในแต่ละเวิร์กโฟลว์ ให้เปิดเวิร์กโฟลว์บนผืนผ้าใบ เลือกจุดสามจุดที่มุมขวาบน เลือก Settings จากนั้นเปลี่ยนค่า Timezone ซึ่งค่านี้จะไปแทนที่ GENERIC_TIMEZONE สำหรับเวิร์กโฟลว์นั้นๆ
สำหรับ Schedule Trigger ลำดับความสำคัญจะถูกกำหนดไว้ตายตัว n8n จะใช้เขตเวลาของเวิร์กโฟลว์หากมีการตั้งค่าไว้ หากไม่มีจะใช้เขตเวลาของอินสแตนซ์จาก GENERIC_TIMEZONE และหากไม่มีอีกจะใช้ค่าเริ่มต้นที่ระบบกำหนดไว้คือ America/New_York โดยที่ TZ จะไม่ถูกนำมาพิจารณาในขั้นตอนใดๆ ของการตัดสินใจนี้
สำหรับวันที่ภายในโหนดต่างๆ คำตอบจะขึ้นอยู่กับว่าโค้ดเรียกใช้เวลาจากนาฬิกาตัวใด Luxon ซึ่งเป็นไลบรารีจัดการวันที่ที่อยู่เบื้องหลังนิพจน์ของ n8n จะใช้เขตเวลาของ n8n ดังนั้น $now และ $today จึงเป็นไปตามลำดับความสำคัญเดียวกันกับตัวทริกเกอร์ คือเวิร์กโฟลว์ก่อนแล้วจึงเป็นอินสแตนซ์ ส่วนคำสั่ง new Date() ของ JavaScript ปกติในโหนด Code จะเรียกใช้เวลาจากระบบปฏิบัติการ จึงเป็นไปตาม TZ ความแตกต่างนี้เองที่เป็นสาเหตุของความสับสนส่วนใหญ่ โดยทริกเกอร์อาจทำงานได้ถูกต้องในขณะที่ประทับเวลาทั้งหมดที่เวิร์กโฟลว์เขียนลงไปกลับคลาดเคลื่อนไปหลายชั่วโมง
ตั้งค่าทั้งสามรายการในไฟล์ Compose
วาง TZ และ GENERIC_TIMEZONE ไว้ติดกันในไฟล์ เพื่อป้องกันไม่ให้มีการตั้งค่ารายการหนึ่งแล้วลืมอีกรายการหนึ่ง ตัวอย่างด้านล่างนี้คือส่วนที่เกี่ยวข้องกับเขตเวลาของบริการที่ทำงานได้ตามปกติ ส่วนที่เหลือของไฟล์ รวมถึง reverse proxy และใบรับรอง สามารถดูได้จาก การติดตั้ง n8n บน VPS ด้วยตนเองผ่าน 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:ให้ปรับใช้การตั้งค่าด้วย docker compose up -d ไม่ใช่ docker compose restart เนื่องจากการสั่ง restart จะเป็นการเริ่ม container เดิมซ้ำด้วยสภาพแวดล้อมที่ถูกกำหนดไว้ตั้งแต่ตอนสร้าง ทำให้การเปลี่ยนแปลงในไฟล์ไม่มีผลกับกระบวนการที่ทำงานอยู่ ส่วน up -d จะตรวจพบสภาพแวดล้อมที่เปลี่ยนไปและสร้าง container ขึ้นมาใหม่ หากคุณเก็บค่าเหล่านี้ไว้ในไฟล์ env แทนการระบุในไฟล์โดยตรง กฎการสร้างใหม่นี้ก็ยังคงมีผลเช่นเดิม โดยสามารถดูรายละเอียดว่าไฟล์ดังกล่าวถูกอ่านจากที่ใดได้ในคู่มือ การจัดการไฟล์ env และ secrets ใน Compose
ให้ใช้ชื่อโซนตามมาตรฐาน IANA (Internet Assigned Numbers Authority) ในรูปแบบ Region/City เช่น Europe/Berlin หรือ America/Sao_Paulo ชื่อเหล่านี้จะรวมกฎการปรับเวลาตามฤดูกาล (daylight saving) ไว้ด้วย ทำให้ค่าชดเชยเวลาเปลี่ยนไปตามการปรับนาฬิกาในพื้นที่นั้นๆ ส่วนชื่อที่ระบุค่าชดเชยคงที่อย่าง Etc/GMT+5 จะไม่มีการเปลี่ยนแปลงตามฤดูกาล และเครื่องหมายบวก/ลบจะตรงกันข้ามกับที่คุณคาดคิด หากคุณรันคำสั่ง LC_ALL=C TZ=Etc/GMT+5 date +%z ระบบจะแสดงผลเป็น -0500 ดังนั้นควรหลีกเลี่ยงการใช้ชื่อในรูปแบบดังกล่าว
เหตุผลที่การตั้งค่าเพียงอย่างใดอย่างหนึ่งทำให้ปัญหาได้รับการแก้ไขเพียงครึ่งเดียว
หากตั้งค่าเพียง GENERIC_TIMEZONE อย่างเดียว Schedule Trigger จะทำงานตามชั่วโมงที่คุณต้องการ ในขณะที่ทุกอย่างที่อ่านค่าจากระบบปฏิบัติการจะยังคงเป็น UTC อยู่ โหนด Code ที่เรียกใช้ new Date().toString() จะส่งคืนค่าเป็นสตริง UTC บรรทัดใน log ของคอนเทนเนอร์จะประทับเวลาเป็น UTC และชื่อไฟล์ใดๆ ที่สร้างขึ้นจากนาฬิกาของระบบจะเปลี่ยนวันในเวลาเที่ยงคืนที่ไม่ถูกต้อง
หากตั้งค่าเพียง TZ อย่างเดียว ผลลัพธ์จะตรงกันข้าม docker compose exec n8n date จะแสดงเวลาท้องถิ่นของคุณซึ่งดูเหมือนว่าสำเร็จ ในขณะที่ Schedule Trigger ยังคงอ้างอิงตาม America/New_York และทำงานห่างจากชั่วโมงที่คุณตั้งไว้ถึงหกชั่วโมง นี่คือเวอร์ชันที่ทำให้เสียเวลามากที่สุด เนื่องจากการตรวจสอบที่คนส่วนใหญ่ทำเป็นอันดับแรกคือสิ่งที่ผ่านการทดสอบไปแล้วในตอนนี้
หากคุณตั้งค่า timezone ของ workflow ไว้ แล้วเปลี่ยน GENERIC_TIMEZONE ในภายหลัง workflow นั้นจะเพิกเฉยต่อการเปลี่ยนแปลงดังกล่าว ค่าที่ตั้งไว้ใน workflow จะมีความสำคัญสูงสุดและจะมีผลต่อไปจนกว่าจะมีคนเปิดการตั้งค่าของ workflow นั้นขึ้นมาแก้ไข กรณีที่ workflow หนึ่งทำงานในเวลาที่ผิดปกติในขณะที่ workflow อื่นๆ ทำงานได้ตามปกติ มักเกิดจากสาเหตุนี้เสมอ
ตรวจสอบเวลาแทนการคาดเดา
เปรียบเทียบเวลาของโฮสต์และคอนเทนเนอร์โดยตรง
date
docker compose exec n8n date
docker compose exec n8n printenv TZ GENERIC_TIMEZONEคำสั่งสองคำสั่งแรกควรแสดงเวลา wall-clock ที่ตรงกันเมื่อตั้งค่า TZ เรียบร้อยแล้ว printenv จะแสดงผลลัพธ์หนึ่งบรรทัดต่อตัวแปรที่มีอยู่ ดังนั้นหากแสดงผลสองบรรทัดหมายความว่ามีการตั้งค่าทั้งสองตัวแล้ว แต่หากแสดงเพียงบรรทัดเดียวหมายความว่าคุณกำลังอยู่ในสถานะที่แก้ไขเพียงบางส่วน
จากนั้นให้สอบถามจากตัว n8n เองภายใน workflow เนื่องจาก shell ของคอนเทนเนอร์ไม่สามารถบอกคุณได้ว่า timezone ในระดับ workflow คืออะไร ให้เพิ่ม Code node เข้าไปใน workflow ที่มีปัญหาแล้วกดรันหนึ่งครั้งด้วย Execute Workflow
return [
{
json: {
n8n_time: $now.toISO(),
n8n_zone: $now.zoneName,
system_time: new Date().toString(),
},
},
];n8n_zone คือโซนเวลาที่ Schedule Trigger ของ workflow นี้จะใช้งาน ซึ่งถูกกำหนดผ่านลำดับความสำคัญจาก workflow ไปยัง instance แล้ว จึงเป็นคำตอบโดยตรงสำหรับปัญหานี้ ส่วน system_time จะดึงโซนเวลาของคอนเทนเนอร์เองมาจาก TZ ให้รันคำสั่งนี้ใน workflow ที่มีปัญหาแทนการสร้าง workflow ใหม่ เพราะการตั้งค่าระดับ workflow จะติดไปกับตัว workflow นั้นๆ หากค่าทั้งสองไม่ตรงกัน คุณจะพบสาเหตุของปัญหาโดยไม่ต้องเปิดไฟล์ config เลยแม้แต่ไฟล์เดียว
นิพจน์ Cron ในโหนด Schedule Trigger
Schedule Trigger มีช่วงเวลาที่กำหนดไว้ล่วงหน้าตั้งแต่ระดับวินาทีไปจนถึงระดับเดือน รวมถึงตัวเลือก Custom (Cron) สำหรับกรณีที่ช่วงเวลาเหล่านั้นไม่ครอบคลุม นิพจน์ cron จะถูกอ่านตามเขตเวลาที่กำหนดไว้ใน workflow ดังนั้น 0 6 * * * จึงหมายถึงเวลา 06:00 น. ในเขตเวลานั้น ไม่ใช่ 06:00 น. ตามเวลา UTC คุณสามารถคัดลอกนิพจน์ 5 ฟิลด์จาก crontab guru มาวางได้ทันที นอกจากนี้ n8n ยังรองรับฟิลด์วินาทีเพิ่มเติม ซึ่งตารางฟิลด์ในเอกสารประกอบจะระบุไว้เป็นลำดับแรก ได้แก่: วินาที, นาที, ชั่วโมง, วันที่ของเดือน, เดือน, วันในสัปดาห์
ห้ามคำนวณค่า offset ด้วยตนเอง การเขียน 0 4 * * * บนอินสแตนซ์ที่ตั้งค่าเป็น UTC เพื่อให้ทำงานในเวลา 06:00 น. ของกรุงเบอร์ลินนั้นถูกต้องในช่วงฤดูหนาว แต่จะคลาดเคลื่อนไปหนึ่งชั่วโมงตลอดช่วงฤดูร้อน เนื่องจากกรุงเบอร์ลินใช้เวลา UTC+1 ในฤดูหนาวและ UTC+2 ในฤดูร้อน ให้ตั้งค่าเขตเวลาและระบุชั่วโมงตามเวลาท้องถิ่นที่คุณต้องการใช้งานจริงแทน
ผลกระทบของ Daylight Saving ต่อกำหนดการงานที่ตั้งไว้เวลา 02:30
เวลาบนนาฬิกาตามท้องถิ่นไม่ใช่จุดเวลาที่แน่นอนเสมอไป ในหนึ่งปีจะมีสองครั้งที่เวลาหายไปหนึ่งชั่วโมงและเวลาซ้ำหนึ่งชั่วโมง ซึ่งจะส่งผลกระทบต่องานใดก็ตามที่ตั้งเวลาไว้ในช่วงดังกล่าว คุณสามารถตรวจสอบเหตุการณ์นี้ได้ด้วย date บนเครื่อง Linux ใดก็ได้โดยไม่ต้องใช้ n8n
LC_ALL=C TZ=Europe/Berlin date -d '2027-03-28 02:30'date: invalid date '2027-03-28 02:30'นั่นไม่ใช่การพิมพ์ผิดในคำสั่ง ในวันที่ 2027-03-28 นาฬิกาในเบอร์ลินจะข้ามจาก 02:00 ไปเป็น 03:00 ทันที ดังนั้นเวลา 02:30 ตามท้องถิ่นจึงไม่มีอยู่จริงในวันนั้น และ date จะปฏิเสธการแปลงเวลานี้ให้เป็นจุดเวลาที่ใช้งานได้ งานที่ผูกไว้กับเวลา 02:30 ตามท้องถิ่นจึงไม่มีช่วงเวลาให้ทำงาน ส่วนเวลาใกล้เคียงนั้นไม่มีปัญหา: date -d '2027-03-28 01:30' จะถูกแปลงเป็น CET และ date -d '2027-03-28 03:30' จะถูกแปลงเป็น CEST
การเปลี่ยนเวลาในฤดูใบไม้ร่วงจะเป็นภาพสะท้อนของเหตุการณ์นี้ ในวันที่ 2027-10-31 นาฬิกาในเบอร์ลินจะถอยหลังจาก 03:00 กลับไปเป็น 02:00 ดังนั้นเวลา 02:30 จึงเกิดขึ้นสองครั้ง
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
1824946200นี่คือจุดเวลาที่แตกต่างกันสองจุด ซึ่งทั้งคู่ถูกเรียกว่า 02:30 ตามท้องถิ่น โดยห่างกัน 3600 วินาที งานที่ถูกกำหนดไว้ในช่วงเวลานี้จะทำงานสองครั้งหรือทำงานเพียงครั้งเดียวในชั่วโมงที่ไม่มีใครเลือก ซึ่งผลลัพธ์ทั้งสองแบบไม่ใช่สิ่งที่ระบบประมวลผลการเรียกเก็บเงินหรือระบบสำรองข้อมูลต้องการ คุณควรย้ายกำหนดการออกจากช่วงเวลาดังกล่าว ในเขตเวลาส่วนใหญ่ของยุโรปและอเมริกาเหนือ ช่วงเวลาที่มีความเสี่ยงคือ 00:00 ถึง 03:00 ตามเวลาท้องถิ่น
กำหนดตารางเวลาโครงสร้างพื้นฐานเป็น UTC และแสดงเวลาท้องถิ่นให้ผู้ใช้งาน
คำตอบมาตรฐานคือการแยกหน้าที่สองอย่างของเขตเวลาออกจากกัน เครื่องจักรต้องการช่วงเวลาที่เสถียร ส่วนมนุษย์ต้องการชั่วโมงที่อ่านเข้าใจได้
- สำหรับงานที่ไม่มีใครเฝ้าดู ให้ตั้งค่าเขตเวลาของเวิร์กโฟลว์เป็น UTC งานประเภทการสำรองข้อมูล (backups), การอุ่นแคช (cache warming), การส่ง log และการสร้างรายงานควรอยู่ในกลุ่มนี้ ในรูปแบบ UTC ระยะห่างระหว่างการทำงานสองครั้งจะเป็นระยะเวลาที่กำหนดไว้จริงเสมอในทุกวันของปี เนื่องจาก UTC ไม่มีการปรับเวลาตามฤดูกาล (daylight saving)
- สำหรับงานที่มนุษย์ต้องอ่าน ให้คงตารางเวลาไว้เป็น UTC แล้วแปลงค่าที่จุดแสดงผล นิพจน์เดียวที่ทำหน้าที่นี้คือ
{{ $now.setZone('Europe/Berlin').toFormat('yyyy-MM-dd HH:mm') }}ซึ่งจะใส่เวลาท้องถิ่นลงในเนื้อหาข้อความในขณะที่ตัวกระตุ้น (trigger) ยังคงมีความเสถียร
การแบ่งแยกในลักษณะเดียวกันนี้ใช้ได้กับงานภายนอก n8n เมื่อส่วนหนึ่งของระบบอัตโนมัติของคุณทำงานเป็น systemd service และ timer บน VPS บรรทัด OnCalendar ของมันจะถูกอ่านตามเขตเวลาของระบบ ซึ่งเป็นนาฬิกาชุดที่สี่ที่มีการตั้งค่าเฉพาะของตนเอง การคงตัวกำหนดตารางเวลาทุกตัวไว้ที่ UTC จะทำให้คุณจำกฎเพียงข้อเดียวแทนที่จะเป็นสี่ข้อ นอกจากนี้ยังมีความสำคัญสำหรับงานใดก็ตามที่สรุปผลข้อมูลในช่วงเวลาหนึ่ง เพราะ n8n AI agent workflow ที่ถูกถามถึงตัวเลขของเมื่อวานจะใช้ช่วงเวลา 24 ชั่วโมงที่แตกต่างกันไปโดยเงียบๆ ขึ้นอยู่กับว่าเขตเวลาใดเป็นตัวกำหนดผลลัพธ์
รูปแบบความล้มเหลวและผลลัพธ์ที่คุณจะพบ
ทุกอย่างทำงานคลาดเคลื่อนไปหกชั่วโมง GENERIC_TIMEZONE ไม่เคยถูกตั้งค่าไว้ ค่าเริ่มต้นในตัวระบบคือ America/New_York จึงถูกนำมาใช้ docker compose exec n8n printenv GENERIC_TIMEZONE ไม่แสดงผลลัพธ์ใดๆ ออกมา ให้ตั้งค่าตัวแปรนี้แล้วสร้างคอนเทนเนอร์ขึ้นมาใหม่
คุณแก้ไขไฟล์ Compose แล้วไม่มีอะไรเปลี่ยนแปลง คุณรันคำสั่ง docker compose restart ไปแล้ว คอนเทนเนอร์จึงยังคงใช้สภาพแวดล้อมเดิมอยู่ ให้รันคำสั่ง docker compose up -d จากนั้นตรวจสอบความถูกต้องด้วย docker compose exec n8n printenv TZ
ตัวกระตุ้นทำงานถูกต้องแต่เวลาไม่ตรง มีเพียง GENERIC_TIMEZONE เท่านั้นที่ถูกตั้งค่าไว้ ส่วน new Date() ในโหนด Code ยังคงอ่านค่าเวลา UTC จากระบบปฏิบัติการ ให้ตั้งค่า TZ เป็นค่าเดียวกันแล้วสร้างคอนเทนเนอร์ใหม่
เวิร์กโฟลว์หนึ่งรายการเพิกเฉยต่อการตั้งค่าของอินสแตนซ์ เวิร์กโฟลว์นั้นมีการตั้งค่าเขตเวลาของตัวเอง ซึ่งจะมีลำดับความสำคัญสูงกว่า GENERIC_TIMEZONE ให้เปิดหน้า Canvas เลือกจุดสามจุด ไปที่ Settings แล้วเลือก Timezone
งานรายวันทำงานสองครั้ง หรือข้ามไปหนึ่งวันในช่วงปีนี้ ชั่วโมงที่กำหนดไว้สำหรับการทำงานนั้นอยู่ในช่วงเวลาที่มีการปรับเปลี่ยน Daylight Saving Time ให้ย้ายเวลาที่กำหนด หรือเปลี่ยนเวิร์กโฟลว์นั้นให้ใช้เวลาแบบ UTC แทน
FAQ
ทำไมตัวกระตุ้น (trigger) แบบกำหนดเวลาของ n8n ถึงทำงานผิดชั่วโมง?
เวิร์กโฟลว์กำลังใช้เขตเวลาที่ต่างจากที่คุณคาดไว้ n8n จะเลือกใช้เขตเวลาของเวิร์กโฟลว์หากมีการตั้งค่าไว้ หากไม่มีจะใช้เขตเวลาของอินสแตนซ์จาก GENERIC_TIMEZONE และหากไม่มีอีกจะใช้ค่าเริ่มต้นของระบบคือ America/New_York อินสแตนซ์ที่โฮสต์เองซึ่งไม่มีการตั้งค่า GENERIC_TIMEZONE จะกำหนดเวลาตามเขตเวลา New York ไม่ใช่ UTC ซึ่งเป็นสาเหตุที่ค่าชดเชยเวลาไม่ตรงกับระยะห่างจาก UTC ของคุณ ให้รันคำสั่ง docker compose exec n8n printenv GENERIC_TIMEZONE หากไม่มีผลลัพธ์แสดงว่าไม่ได้มีการตั้งค่าไว้
TZ และ GENERIC_TIMEZONE ใน n8n ต่างกันอย่างไร?
TZ คือเขตเวลาของระบบปฏิบัติการภายในคอนเทนเนอร์ ซึ่งควบคุมสิ่งที่ date ส่งกลับมาภายในคอนเทนเนอร์, รูปแบบเวลาที่ปรากฏในบรรทัด log ของคอนเทนเนอร์, สิ่งที่ new Date() ส่งกลับมาในโหนด Code และสิ่งที่สคริปต์ใดๆ ที่คุณรันในนั้นมองเห็น ส่วน GENERIC_TIMEZONE คือเขตเวลาของอินสแตนซ์ n8n ซึ่งเป็นสิ่งที่โหนดกำหนดเวลาและนิพจน์ Luxon เช่น $now ใช้งาน การตั้งค่าอย่างใดอย่างหนึ่งโดยไม่ตั้งอีกอย่างจะทำให้คุณได้ตัวกระตุ้นที่ถูกต้องแต่เวลาผิด หรือได้เวลาที่ถูกต้องแต่ตัวกระตุ้นทำงานผิดเวลาไปหลายชั่วโมง ควรตั้งค่าทั้งสองให้เป็นค่าเดียวกัน
ฉันควรตั้งค่าเขตเวลาที่เวิร์กโฟลว์หรือ GENERIC_TIMEZONE?
ให้ตั้งค่า GENERIC_TIMEZONE เป็นค่าเริ่มต้นสำหรับทั้งอินสแตนซ์ และใช้การตั้งค่ารายเวิร์กโฟลว์เฉพาะในกรณีที่เวิร์กโฟลว์นั้นจำเป็นต้องอยู่ในเขตเวลาอื่นจริงๆ ค่าของเวิร์กโฟลว์จะมีความสำคัญเหนือกว่าค่าของอินสแตนซ์ และจะไม่เปลี่ยนแปลงตามการแก้ไข GENERIC_TIMEZONE ในภายหลัง ดังนั้นการตั้งค่าทับรายเวิร์กโฟลว์ที่ถูกลืมไว้อาจตรวจสอบได้ยากในอีกหลายเดือนต่อมา
จะเกิดอะไรขึ้นกับงานที่กำหนดเวลาไว้ตอน 02:30 เมื่อมีการปรับเวลาตามฤดูกาล?
เวลาท้องถิ่นนั้นอาจหายไปหรือเกิดขึ้นสองครั้ง LC_ALL=C TZ=Europe/Berlin date -d '2027-03-28 02:30' จะส่งกลับค่า date: invalid date '2027-03-28 02:30' เนื่องจากนาฬิกาใน Berlin กระโดดข้ามจาก 02:00 ไปเป็น 03:00 ในวันนั้น ส่วนในวันที่ 2027-10-31 ค่าเวลาบนหน้าปัดนาฬิกาเดียวกันจะอ้างอิงถึงสองช่วงเวลาที่ห่างกันหนึ่งชั่วโมง ควรหลีกเลี่ยงการกำหนดเวลางานในช่วง 00:00 ถึง 03:00 ตามเวลาท้องถิ่น หรือตั้งค่าเวิร์กโฟลว์เป็น UTC แล้วแปลงเป็นเวลาท้องถิ่นเฉพาะในจุดที่ต้องแสดงผลให้มนุษย์อ่านเท่านั้น