Zomertijd / Wintertijd

Hoewel je in je Salesforce omgeving de tijdzone waarin je werkt wel goed kunt instellen, kun je soms toch verrast worden door een tijd die ineens in GMT blijkt te worden weergegeven.

Waarom en wanneer gebeurt dit?

Het probleem doet zich voor wanneer je een datum/tijd waarde gebruikt in een formule waarvan het output type niet datum/tijd is.

Standaard worden Datum/tijd waarden opgeslagen in de tijdzone GMT / UTC. Het omrekenen naar je lokale tijd, wordt eigenlijk door de Salesforce User Interface gedaan.

Met Salesforce Inspector (een browser plugin voor Chrome) kun je dit snel in de praktijk zien. Zoek een willekeurig datum/tijd veld op in een record in je omgeving en bekijk daarna de waarde van ditzelfde veld via Salesforce Inspector. Wat er in je User Interface uitziet als 29-03-2023 12:00, blijkt onder water 2023-03-29T10:00:00.000+0000 te zijn.

Op het moment dat je deze Datum/Tijd waarde in een formule gebruikt en de output bevat geen datum, dan is nooit vast te stellen of het zomertijd of wintertijd is en kan de juiste correctie dus niet berekend worden. Op de laatste zondagen van maart en oktober kan bovendien zonder de tijd niet vastgesteld worden of het zomertijd of wintertijd is.

Dus wanneer je de Datum/Tijd waarde gebruikt om deze om te zetten in een Text of Tijd waarde, zul je de tijd in GMT zien en niet de tijd in je lokale tijdzone (als die afwijkt van GMT).

Als je de datum en tijd van een afspraak in een prettig leesbaar formaat in een email wilt opnemen, gebruik je daar waarschijnlijk een of meerdere formules voor die tekst of een tijd als uitvoer hebben.

Je wilt natuurlijk niet een onjuiste afspraaktijd aan de klant communiceren, dus kun je een correctie inbouwen op je formuleveld, maar je moet daarin ook nog rekening houden met of het nu zomertijd of wintertijd is. En dan wordt het wel gauw een complexe formule.

Dan is dit de formule die je nodig hebt, waarbij je myDateTimeField natuurlijk vervangt door het veld dat jij naar een correcte tijdsaanduiding wilt converteren.

myDateTimeField
+
IF(
    OR(
        /* april - september : always summertime */
        MONTH( DATEVALUE( myDateTimeField ) ) < 10 &&
        MONTH( DATEVALUE( myDateTimeField ) ) > 3,
        
        /* after last sunday of march : always summertime */
        MONTH( DATEVALUE( myDateTimeField ) ) = 3 &&
        DATEVALUE(myDateTimeField) >
        DATE(
            YEAR( DATEVALUE( myDateTimeField ) ),
            3,
            24
        ) +
        8 -
        WEEKDAY(
            DATE(
                YEAR( DATEVALUE( myDateTimeField ) ),
                3,
                24
            )
        ),
        
        /* before last sunday of october : always summertime */
        MONTH( DATEVALUE( myDateTimeField ) ) = 10 &&
        DATEVALUE(myDateTimeField) <
        DATE(
            YEAR( DATEVALUE( myDateTimeField ) ),
            10,
            24
        ) +
        8 -
        WEEKDAY(
            DATE(
                YEAR( DATEVALUE( myDateTimeField ) ),
                10,
                24
            )
        ),

        /* on last sunday of march after 3 AM CEST = 1 AM UTC: always summertime */
        MONTH( DATEVALUE( myDateTimeField ) ) = 3 &&
        DATEVALUE(myDateTimeField) = 
        DATE(
            YEAR( DATEVALUE( myDateTimeField ) ),
            3,
            24
        ) +
        8 -
        WEEKDAY(
            DATE(
                YEAR( DATEVALUE( myDateTimeField ) ),
                3,
                24
            )
        ) &&
        HOUR(
            TIMEVALUE ( myDateTimeField )
        ) >= 1,
        
        /* on last sunday of october before 2 AM CET = 1 AM UTC: always summertime */
        MONTH( DATEVALUE( myDateTimeField ) ) = 10 &&
        DATEVALUE(myDateTimeField) = 
        DATE(
            YEAR( DATEVALUE( myDateTimeField ) ),
            10,
            24
        ) +
        8 -
        WEEKDAY(
            DATE(
                YEAR( DATEVALUE( myDateTimeField ) ),
                10,
                24
            )
        ) &&
        HOUR(
            TIMEVALUE ( myDateTimeField  )
        ) < 1
    ),
    2,
    1
)
/ 24

Je kunt deze formule als volgt ontleden:

Het buitenste gedeelte telt als het zomertijd is 2 uur bij je oorspronkelijke DatumTijd waarde op en 1 uur als het wintertijd is. De /24 op het einde zorgt ervoor dat je uren optelt in plaats van hele dagen.

myDateTimeField
+
IF(
    /* isSummerTime * /,
    2,
    1
)
/ 24

Binnen de test van deze If formule zit de test of het nu zomertijd is. De uitkomst van die formule is een Boolean: waar of niet waar. Hierin werken we van groot naar klein:

OR(
    /* april - september : always summertime */,
    
    /* after last sunday of march : always summertime */,

    /* before last sunday of october : always summertime */,

    /* on last sunday of march after 3 AM CEST = 1 AM UTC: always summertime */,
    
    /* on last sunday of october before 2 AM CET = 1 AM UTC: always summertime */
)
  1. In de maanden april tot en met september is het altijd zomertijd
  2. In maart is het zomertijd ná de laatste zondag van de maand
  3. In oktober is het zomertijd vóór de laatste zondag van de maand
  4. Op de laatste zondag van maart is het zomertijd ná 2:00 CET / 3:00 CEST (1:00 GMT)
  5. Op de laatste zondag van oktober is het zomertijd vóór 2:00 CEST (0:00 GMT)
  6. Op de laatste zondag van oktober komt het uur 2:00 – 3:00 in zowel de zomertijd als de wintertijd voor, dus of het in dat uur zomertijd of wintertijd is, kun je niet vaststellen. Zorg dat er in dat uur niets belangrijks gebeurt waarvan je de datum en tijd moet tonen of communiceren.

De 5 losse tests of het zomertijd is, zitten samengevat in de OR formule. Dus als één van die losse testen waar is, is het resultaat van de OR formule waar en is het zomertijd.

De losse testen:

In de maanden april (maand groter dan 3) tot en met september (maand kleiner dan 10) is het altijd zomertijd

MONTH( DATEVALUE( myDateTimeField ) ) < 10 &&
MONTH( DATEVALUE( myDateTimeField ) ) > 3,

In maart is het zomertijd ná de laatste zondag van de maand

MONTH( DATEVALUE( myDateTimeField ) ) = 3 &&
DATEVALUE(myDateTimeField) >
DATE(
    YEAR( DATEVALUE( myDateTimeField ) ),
    3,
    24
) +
8 -
WEEKDAY(
    DATE(
        YEAR( DATEVALUE( myDateTimeField ) ),
        10,
        24
    )
)

In oktober is het zomertijd vóór de laatste zondag van de maand

MONTH( DATEVALUE( myDateTimeField ) ) = 10 &&
DATEVALUE(myDateTimeField) <
DATE(
    YEAR( DATEVALUE( myDateTimeField ) ),
    10,
    24
) +
8 -
WEEKDAY(
    DATE(
        YEAR( DATEVALUE( myDateTimeField ) ),
        10,
        24
    )
)

Op de laatste zondag van maart is het zomertijd ná 2:00 CET / 3:00 CEST (1:00 GMT)

MONTH( DATEVALUE( myDateTimeField ) ) = 3 &&
DATEVALUE(myDateTimeField) = 
DATE(
    YEAR( DATEVALUE( myDateTimeField ) ),
    3,
    24
) +
8 -
WEEKDAY(
    DATE(
        YEAR( DATEVALUE( myDateTimeField ) ),
        3,
        24
    )
) &&
HOUR(
    TIMEVALUE ( myDateTimeField )
) >= 1

Op de laatste zondag van oktober is het zomertijd vóór 2:00 CEST (0:00 GMT)

MONTH( DATEVALUE( myDateTimeField ) ) = 10 &&
DATEVALUE(myDateTimeField) = 
DATE(
    YEAR( DATEVALUE( myDateTimeField ) ),
    10,
    24
) +
8 -
WEEKDAY(
    DATE(
        YEAR( DATEVALUE( myDateTimeField ) ),
        10,
        24
    )
) &&
HOUR(
    TIMEVALUE ( myDateTimeField  )
) < 1

Test vooral goed welke afwijking je weergegeven tijd heeft ten opzichte van de bedoelde tijd. Soms dien je de afwijking erbij op te tellen en soms dien je de afwijking ervan af te trekken. Pas ook op om niet dubbel te corrigeren of twee tegenstrijdige correcties te maken die elkaar uitdoven.

Als je de formule copy-paste in notepad, kun je in één bewerking myDateTimeField overal vervangen door het veld dat in jouw omgeving van toepassing is. Gebruik het eerste codeblok van het artikel. Dit is de volledige formule.