n8n schedule trigger loopt verkeerd: tijdzones instellen
Een n8n schedule trigger wijkt af door drie conflicterende instellingen. Configureer de TZ variabele, GENERIC_TIMEZONE en de workflow instellingen correct voor de juiste tijd.
Waarom uw n8n schedule trigger op het verkeerde uur afgaat
Een n8n schedule trigger gaat op het verkeerde uur af omdat n8n de tijdzone op drie afzonderlijke plaatsen uitleest; het corrigeren van slechts één daarvan lost het probleem slechts gedeeltelijk op. De drie plaatsen zijn de TZ-variabele van de container zelf, de standaardinstelling van de instantie GENERIC_TIMEZONE, en een tijdzone die binnen een individuele workflow is ingesteld. Stel alle drie eenmalig in, zodat elke planning die u daarna maakt op het verwachte tijdstip wordt uitgevoerd.
Corrigeer eerst één aanname. Een nieuwe, zelfgehoste n8n-installatie plant taken niet in UTC (Coordinated Universal Time). De klok van de container staat op UTC, omdat de officiële image geen TZ instelt. Planning is een afzonderlijke laag, en de gedocumenteerde standaardwaarde van n8n voor GENERIC_TIMEZONE is America/New_York (peildatum augustus 2026). Een onaangepaste instantie voert zijn Schedule Triggers daarom uit op basis van de tijd in New York. Dit is de reden waarom de gerapporteerde afwijking zelden overeenkomt met de eigen afstand tot UTC. Een eigenaar in Berlijn die vraagt om 06:00 uur, krijgt 12:00 uur lokale tijd, en 11:00 uur tijdens de weken in maart waarin de Verenigde Staten al zijn overgeschakeld op zomertijd en Europa nog niet.
De drie tijdzonelagen en welke voorrang krijgt
TZ is de tijdzone van het besturingssysteem binnen de container. De n8n-documentatie beschrijft dit als de variabele die de systeem-tijdzone instelt om te bepalen wat scripts en commando's zoals date retourneren. Het bepaalt wat date binnen de container afdrukt, welke tijdstempel er op een logregel van de container verschijnt, wat new Date() in een Code-node retourneert en wat elk shell-script dat u daar uitvoert ziet. Het heeft geen invloed op het tijdstip waarop een Schedule Trigger wordt geactiveerd.
GENERIC_TIMEZONE is de tijdzone van de n8n-instantie. De documentatie noemt dit de n8n-instantie-tijdzone en merkt op dat deze belangrijk is voor schedule-nodes zoals Cron. Cron betekent hier de standaard op tijd gebaseerde planningssyntaxis, en n8n stelt deze beschikbaar als de optie Custom (Cron) in de Schedule Trigger.
De workflow-tijdzone wordt per workflow ingesteld. Open de workflow op het canvas, selecteer de drie puntjes in de rechterbovenhoek, selecteer Settings en wijzig vervolgens de waarde bij Timezone. Deze overschrijft GENERIC_TIMEZONE voor die specifieke workflow.
Voor een Schedule Trigger is de volgorde vastgelegd. n8n gebruikt de workflow-tijdzone als de workflow er een heeft, anders de instantie-tijdzone uit GENERIC_TIMEZONE, en anders de ingebouwde standaardwaarde America/New_York. TZ wordt bij geen enkele stap van die beslissing geraadpleegd.
Voor datums binnen uw nodes hangt het antwoord af van welke klok de code raadpleegt. Luxon, de datum-bibliotheek achter n8n-expressies, gebruikt de n8n-tijdzone, dus $now en $today volgen dezelfde volgorde (workflow, dan instantie) als de trigger. Standaard JavaScript new Date() in een Code-node raadpleegt het besturingssysteem, dus dit volgt TZ. Dat onderscheid is de bron van de meeste verwarring: de trigger kan correct zijn, terwijl elke tijdstempel die de workflow schrijft er uren naast zit.
Stel alle drie in het Compose-bestand in
Plaats TZ en GENERIC_TIMEZONE naast elkaar in het bestand, zodat niemand de ene instelt en de andere vergeet. Het onderstaande fragment is het tijdzone-relevante deel van een werkende service. De rest van het bestand, de reverse proxy en het certificaat, is afkomstig uit een zelfgehoste n8n op een VPS achter 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:Pas het toe met docker compose up -d, niet met docker compose restart. Een restart start dezelfde container opnieuw met de omgeving waarmee deze is aangemaakt; de bestandswijzigingen worden dus niet doorgevoerd in het draaiende proces. up -d ziet de gewijzigde omgeving en maakt de container opnieuw aan. Als u deze waarden in een env-bestand bewaart in plaats van inline, geldt dezelfde regel voor het opnieuw aanmaken, en de gids over Compose env-bestanden en het afhandelen van secrets beschrijft waar dat bestand wordt ingelezen.
Gebruik een IANA (Internet Assigned Numbers Authority) zonenaam in de vorm van Region/City, zoals Europe/Berlin of America/Sao_Paulo. Deze namen bevatten de regels voor zomertijd voor die locatie, waardoor de offset verandert wanneer de lokale klokken worden verzet. Een naam met een vaste offset zoals Etc/GMT+5 verandert nooit met de seizoenen, en het teken is tegengesteld aan wat u zou verwachten. Voer LC_ALL=C TZ=Etc/GMT+5 date +%z uit en het print -0500. Vermijd deze namen.
Waarom het instellen van slechts één van beide opties het probleem slechts gedeeltelijk oplost
Stel alleen GENERIC_TIMEZONE in en de Schedule Trigger wordt geactiveerd op het gewenste uur, terwijl alles wat het besturingssysteem uitleest op UTC blijft staan. Een Code node die new Date().toString() aanroept, retourneert een UTC-tekenreeks, containerlogregels krijgen een UTC-tijdstempel en elke bestandsnaam die is gebaseerd op de systeemklok verspringt op het verkeerde middernachtmoment.
Stel alleen TZ in en het tegenovergestelde gebeurt. docker compose exec n8n date toont uw lokale tijd, wat lijkt op een succes, terwijl de Schedule Trigger nog steeds op America/New_York staat en zes uur afwijkt van het door u gevraagde uur. Dit is de versie die de meeste tijd kost, omdat de controle die de meeste mensen als eerste uitvoeren, nu slaagt.
Stel een workflow-tijdzone in en wijzig daarna GENERIC_TIMEZONE; de workflow negeert deze wijziging. De waarde van de workflow krijgt voorrang en blijft voorrang houden totdat iemand de instellingen van die workflow opent. Een workflow die op een vreemd uur draait terwijl de naburige workflows correct functioneren, is bijna altijd hiervan het gevolg.
Controleer de klokken in plaats van te gokken
Vergelijk de host en de container direct met elkaar.
date
docker compose exec n8n date
docker compose exec n8n printenv TZ GENERIC_TIMEZONEDe eerste twee commando's moeten dezelfde kloktijd weergeven zodra TZ is ingesteld. printenv print één regel per variabele die bestaat; twee regels uitvoer betekent dus dat beide zijn ingesteld, en één regel betekent dat u naar de half-geconfigureerde status kijkt.
Vraag het nu aan n8n zelf, vanuit een workflow, omdat een container-shell u niet kan vertellen wat de tijdzone op workflow-niveau is. Voeg een Code-node toe aan de workflow die niet naar behoren werkt en voer deze eenmaal uit met Execute Workflow.
return [
{
json: {
n8n_time: $now.toISO(),
n8n_zone: $now.zoneName,
system_time: new Date().toString(),
},
},
];n8n_zone is de zone die de Schedule Trigger van deze workflow zal gebruiken, reeds opgelost via de volgorde workflow-dan-instantie, dus dit beantwoordt de vraag direct. system_time bevat de eigen zone van de container vanuit TZ. Voer dit uit in de workflow die niet naar behoren werkt in plaats van in een nieuwe, omdat de instelling op workflow-niveau met de workflow meereist. Als die twee waarden niet overeenkomen, heeft u het probleem gevonden zonder ook maar één configuratiebestand te openen.
Cron-expressies in de Schedule Trigger-node
De Schedule Trigger biedt vaste intervallen van seconden tot maanden, plus Custom (Cron) voor alles wat daarbuiten valt. De cron-expressie wordt gelezen in de opgeloste tijdzone van de workflow, dus 0 6 * * * betekent 06:00 in die tijdzone in plaats van 06:00 UTC. Een expressie met vijf velden van crontab guru kan direct worden geplakt. n8n accepteert ook een optioneel secondenveld, dat in de veldentabel van de documentatie als eerste wordt geplaatst: seconde, minuut, uur, dag van de maand, maand, dag van de week.
Codeer de offset nooit handmatig. Het schrijven van 0 4 * * * op een UTC-instantie om 06:00 in Berlijn te bereiken is correct in de winter, maar de hele zomer één uur fout, omdat Berlijn in de winter op UTC+1 draait en in de zomer op UTC+2. Stel de tijdzone in en schrijf het lokale uur dat u daadwerkelijk bedoelt.
Wat zomertijd doet met een taak gepland om 02:30
Een lokale kloktijd is geen gegarandeerd tijdstip. Twee keer per jaar verdwijnt er een uur en wordt er een uur herhaald; elke taak die binnen die uren is gepland, ondervindt hiervan hinder. U kunt dit zelf observeren met date op elke Linux-machine, zonder dat daar n8n bij komt kijken.
LC_ALL=C TZ=Europe/Berlin date -d '2027-03-28 02:30'date: invalid date '2027-03-28 02:30'Dat is geen typefout in het commando. Op 2027-03-28 springt de Berlijnse klok direct van 02:00 naar 03:00, waardoor 02:30 lokale tijd die dag niet bestaat en date weigert dit om te zetten naar een tijdstip. Een taak die is vastgepind op 02:30 lokale tijd heeft geen moment om uit te voeren. De omliggende tijden werken wel: date -d '2027-03-28 01:30' wordt opgelost als CET en date -d '2027-03-28 03:30' wordt opgelost als CEST.
De overgang in het najaar is het spiegelbeeld. Op 2027-10-31 gaat de Berlijnse klok terug van 03:00 naar 02:00, waardoor 02:30 twee keer voorkomt.
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
1824946200Twee verschillende tijdstippen, beide aangeduid als 02:30 lokale tijd, met 3600 seconden ertussen. Een taak die daarop is vastgepind, wordt ofwel twee keer uitgevoerd, of één keer op een uur dat niemand heeft gekozen. Geen van beide resultaten is wenselijk voor een facturatieproces of een back-uprotatie. Verplaats de planning buiten dit tijdsvenster. In de meeste Europese en Noord-Amerikaanse tijdzones is de risicovolle zone tussen 00:00 en 03:00 lokale tijd.
Plan infrastructuur in UTC en toon lokale tijd aan gebruikers
Het standaardantwoord scheidt de twee taken die een tijdzone uitvoert. Machines hebben een stabiel interval nodig. Mensen hebben een leesbaar uur nodig.
- Voor taken waar niemand toezicht op houdt, stelt u de tijdzone van de workflow in op UTC. Back-ups, het opwarmen van caches, het versturen van logs en het genereren van rapporten vallen hieronder. In UTC is het tijdsverschil tussen twee uitvoeringen exact het interval dat u heeft ingesteld, op elke dag van het jaar, omdat UTC geen zomertijd kent.
- Voor taken die door mensen worden gelezen, houdt u het schema in UTC en converteert u dit op het moment van weergave. Eén expressie volstaat:
{{ $now.setZone('Europe/Berlin').toFormat('yyyy-MM-dd HH:mm') }}plaatst de lokale tijd in de berichttekst terwijl de trigger stabiel blijft.
Dezelfde scheiding is van toepassing buiten n8n. Wanneer een deel van uw automatisering draait als een systemd service en timer op de VPS, wordt de OnCalendar-regel gelezen in de systeem-tijdzone, wat een vierde klok is met een eigen instelling. Door elke scheduler op UTC te houden, hoeft u slechts één regel te onthouden in plaats van vier. Dit is ook van belang voor alles wat een periode samenvat, omdat een n8n AI agent workflow die om de cijfers van gisteren vraagt, stilletjes andere 24 uur zal gebruiken, afhankelijk van welke tijdzone wordt toegepast.
Foutmodi en de output die u zult zien
Alles wordt met een afwijking van zes uur uitgevoerd. GENERIC_TIMEZONE was nooit ingesteld, dus de ingebouwde standaardwaarde America/New_York is van toepassing. docker compose exec n8n printenv GENERIC_TIMEZONE geeft niets weer. Stel deze in en maak de container vervolgens opnieuw aan.
U heeft het Compose-bestand bewerkt en er is niets veranderd. U heeft docker compose restart uitgevoerd, waardoor de container zijn oorspronkelijke omgeving heeft behouden. Voer docker compose up -d uit en bevestig dit vervolgens met docker compose exec n8n printenv TZ.
De trigger is correct, maar de tijdstempels kloppen niet. Alleen GENERIC_TIMEZONE is ingesteld. Een new Date() in een Code-node leest nog steeds UTC van het besturingssysteem. Stel TZ in op dezelfde waarde en maak de container opnieuw aan.
Eén workflow negeert de instelling van de instantie. Die workflow bevat een eigen tijdzone in de instellingen, die voorrang heeft op GENERIC_TIMEZONE. Open het canvas, klik op de drie puntjes, Instellingen, Tijdzone.
Een dagelijkse taak is dit jaar één keer twee keer uitgevoerd of heeft een dag overgeslagen. Het geplande uur valt binnen een overgang naar zomertijd of wintertijd. Verplaats het uur of zet die workflow om naar UTC.
FAQ
Waarom wordt mijn n8n-schedule-trigger op het verkeerde uur geactiveerd?
De workflow hanteert een andere tijdzone dan u verwacht. n8n kiest de tijdzone van de workflow als deze is ingesteld, anders de tijdzone van de instantie via GENERIC_TIMEZONE, en als laatste redmiddel de ingebouwde standaardwaarde America/New_York. Een zelfgehoste instantie waarbij GENERIC_TIMEZONE niet is ingesteld, plant taken in op New York-tijd in plaats van UTC. Daarom komt de offset zelden overeen met uw eigen afstand tot UTC. Voer docker compose exec n8n printenv GENERIC_TIMEZONE uit. Geen uitvoer betekent dat de variabele nooit is ingesteld.
Wat is het verschil tussen TZ en GENERIC_TIMEZONE in n8n?
TZ is de tijdzone van het besturingssysteem binnen de container. Deze bepaalt wat date binnen de container teruggeeft, welke tijdstempels in de containerlogs verschijnen, wat new Date() in een Code-node retourneert en wat elk script dat u daarin uitvoert ziet. GENERIC_TIMEZONE is de tijdzone van de n8n-instantie; dit is de waarde die schedule-nodes en Luxon-expressies zoals $now gebruiken. Als u slechts één van beide instelt, krijgt u een correcte trigger met onjuiste tijdstempels, of correcte tijdstempels met een trigger die op het verkeerde moment afgaat. Stel beide in op dezelfde waarde.
Moet ik de workflow-tijdzone of GENERIC_TIMEZONE instellen?
Stel GENERIC_TIMEZONE in als de standaard voor de gehele instantie en gebruik de instelling per workflow alleen wanneer een workflow daadwerkelijk in een andere tijdzone thuishoort. De waarde van de workflow overschrijft de waarde van de instantie en volgt latere wijzigingen in GENERIC_TIMEZONE niet. Een vergeten overschrijving per workflow is maanden later lastig te achterhalen.
Wat gebeurt er met een taak die gepland staat om 02:30 wanneer de klok wordt verzet?
Die lokale tijd verdwijnt of komt twee keer voor. LC_ALL=C TZ=Europe/Berlin date -d '2027-03-28 02:30' retourneert date: invalid date '2027-03-28 02:30', omdat de klok in Berlijn op die dag verspringt van 02:00 naar 03:00. Op 2027-10-31 komt dezelfde kloktijd overeen met twee tijdstippen die een uur uit elkaar liggen. Plan taken bij voorkeur niet in de lokale tijdsband tussen 00:00 en 03:00, of stel de workflow in op UTC en converteer pas naar lokale tijd op het moment dat een gebruiker de gegevens bekijkt.