ioBroker: Zeitdifferenzen formatieren
Ich sehe immer wieder, dass mit Blockly eine Zeitdifferenz formatiert werden soll. Dafür werden dann die Datums-Funktionen genutzt, welche aber dafür gedacht sind, einen UTC-Zeitstempel in ein Datum/Uhrzeit in meiner lokalen Zeitzone zu formatieren. Das führt immer wieder zu falschen Ergebnissen und zu Unverständnis. Daher möchte ich in diesem Beitrag einmal zusammenfassen, wie die Datumsfunktion eigentlich arbeitet und warum man diese für Zeit-Differenzen gar nicht verwenden kann. Denn dann gibt es nicht nur ein Problem mit der Zeitzone.
Video
Zusammenfassung
- Der UTC-Zeitstempel enthält die Millisekunden seit dem 01.01.1970 00:00 Uhr
- Die Datums-Funktionen erwarten einen UTC-Zeitstempel und formatieren diesen in ein lesbares Format in der Zeitzone des Systems
- 0 Uhr UTC ist bei uns (Europe/Berlin bzw. CET/MEZ) also 01:00 Uhr im Winter und 02:00 Uhr im Sommer (Sommerzeit)
Wenn man nun also eine Zeitdifferenz von 697185 Millisekunden formatieren möchte, ist das für die Datums-Funktion der Zeitstempel vom 01.01.1970 01:11:37.185
. In unserer Zeitzone ergibt das mit den Datums-Funktionen also im Sommer einen anderen Wert als im Winter!
- Sommer (UTC+2) =
MESZ
(Mitteleuropäische Sommerzeit):01.01.1970 02:11:37.185
- Winter (UTC+1) =
MEZ
(Mitteleuropäische Zeit):01.01.1970 01:11:37.185
Wenn man dies nun also als Stunde, Minute, Sekunde formatiert (SS:mm:ss
), dann erhält man im
- Sommer:
02:11:37
- Winter:
01:11:37
Und das für eine Zeitspanne, welche nur 11 Minuten lang ist. Das Ergebnis also völlig unbrauchbar, weil die Funktion “Datum formatieren” dafür überhaupt nicht gedacht ist. Die macht in diesem Fall genau das richtige - sie wird nur falsch angewendet!
Blockly aus dem Video
Falls Du nicht auf die neue JavaScript-Version (> 7.1.6) warten willst, hier das Blockly für den manuellen Weg.
<xml xmlns="https://developers.google.com/blockly/xml">
<variables>
<variable id="b%Z!x*.OQ1:xpUd2L1}d">wert</variable>
<variable id="C9!$x^u3H!0X_8AhU89q">differenz</variable>
<variable id="q|m4LFGW:9EM.I@+TuHi">zeitDifferenzMs</variable>
<variable id="@n!=!buWKLkR{#)CNfbb">h</variable>
<variable id="v5:^*@SuhLU@E:(rkTji">m</variable>
<variable id="Y6sidmV,eJ:33NfEyK`X">s</variable>
</variables>
<block type="procedures_defreturn" id="`),jny$3$v+/s2B=s`T{" x="188" y="-863">
<mutation>
<arg name="wert" varid="b%Z!x*.OQ1:xpUd2L1}d"></arg>
</mutation>
<field name="NAME">textFormatieren</field>
<comment pinned="false" h="80" w="160">Beschreibe diese Funktion …</comment>
<value name="RETURN">
<block type="logic_ternary" id="pkIQJXl[(-ed/O6$_ftH">
<value name="IF">
<block type="logic_compare" id="4H7^MdF9~4-Wpy1VqJzP">
<field name="OP">LT</field>
<value name="A">
<block type="variables_get" id="}x8JX#RLf+ML+G@aN#6{">
<field name="VAR" id="b%Z!x*.OQ1:xpUd2L1}d">wert</field>
</block>
</value>
<value name="B">
<block type="math_number" id="UAsvQaP$J]z9Mnzpg,@N">
<field name="NUM">10</field>
</block>
</value>
</block>
</value>
<value name="THEN">
<block type="text_join" id="a0m!*[eIPn$%{~=Ao9Im">
<mutation items="2"></mutation>
<value name="ADD0">
<block type="text" id="fJ+,SeHu3KKZ!{XVP_~%">
<field name="TEXT">0</field>
</block>
</value>
<value name="ADD1">
<block type="variables_get" id="2X^m3g*^pSTVwt])6LFB">
<field name="VAR" id="b%Z!x*.OQ1:xpUd2L1}d">wert</field>
</block>
</value>
</block>
</value>
<value name="ELSE">
<block type="variables_get" id="*v[O)n0+]-Fk_#dT^i_(">
<field name="VAR" id="b%Z!x*.OQ1:xpUd2L1}d">wert</field>
</block>
</value>
</block>
</value>
</block>
<block type="procedures_defreturn" id="K{y`):PVxR?)So/]__|D" x="188" y="-687">
<mutation>
<arg name="differenz" varid="C9!$x^u3H!0X_8AhU89q"></arg>
</mutation>
<field name="NAME">zeitDifferenzFormatierenHMS</field>
<comment pinned="false" h="80" w="160">Beschreibe diese Funktion …</comment>
<statement name="STACK">
<block type="variables_set" id="@)EIWb:79a(@be`#/XpR">
<field name="VAR" id="@n!=!buWKLkR{#)CNfbb">h</field>
<value name="VALUE">
<block type="math_round" id="t*^Y,rg,o!8MDB`H?Wa}">
<field name="OP">ROUNDDOWN</field>
<value name="NUM">
<shadow type="math_number" id="q,!WYL%nB;!*e#@Lq71v">
<field name="NUM">3.1</field>
</shadow>
<block type="math_arithmetic" id="`2y9ow.|1WtDPk(fG568">
<field name="OP">DIVIDE</field>
<value name="A">
<shadow type="math_number" id="wFQC`k!NL92En0#}-iuL">
<field name="NUM">1</field>
</shadow>
<block type="variables_get" id="l%^Z~@fm`h}Hhz)s0!NS">
<field name="VAR" id="C9!$x^u3H!0X_8AhU89q">differenz</field>
</block>
</value>
<value name="B">
<shadow type="math_number" id="z]OGf4Yw[#tAA)$~2OI?">
<field name="NUM">3600000</field>
</shadow>
</value>
</block>
</value>
</block>
</value>
<next>
<block type="variables_set" id="l0?,]M}85:#9Eg%/QNS=">
<field name="VAR" id="v5:^*@SuhLU@E:(rkTji">m</field>
<value name="VALUE">
<block type="math_round" id="V$~Af~WURSO]z4{WyW{4">
<field name="OP">ROUNDDOWN</field>
<value name="NUM">
<shadow type="math_number" id="q,!WYL%nB;!*e#@Lq71v">
<field name="NUM">3.1</field>
</shadow>
<block type="math_arithmetic" id="`-]YBQ/?mR7TatvSD44P">
<field name="OP">DIVIDE</field>
<value name="A">
<shadow type="math_number" id="^~CG]!Yc??I#d$pO?Q.%">
<field name="NUM">1</field>
</shadow>
<block type="math_modulo" id="$c/iF{x)1X}s5^n)[34#">
<value name="DIVIDEND">
<shadow type="math_number" id="_{Iit?D47qqR-0%}/.J!">
<field name="NUM">64</field>
</shadow>
<block type="variables_get" id="k!^8yQPPx|ctLeWlg)%H">
<field name="VAR" id="C9!$x^u3H!0X_8AhU89q">differenz</field>
</block>
</value>
<value name="DIVISOR">
<shadow type="math_number" id="EtQv~I*Y-}12EEX,5`-L">
<field name="NUM">3600000</field>
</shadow>
</value>
</block>
</value>
<value name="B">
<shadow type="math_number" id="Jw$#pF4!Qw6qis(,^T/,">
<field name="NUM">60000</field>
</shadow>
</value>
</block>
</value>
</block>
</value>
<next>
<block type="variables_set" id="E[f@;2QQW%v+G`b{+PKg">
<field name="VAR" id="Y6sidmV,eJ:33NfEyK`X">s</field>
<value name="VALUE">
<block type="math_round" id="YG(9T!Ag~Wm*`r:h~@4!">
<field name="OP">ROUNDDOWN</field>
<value name="NUM">
<shadow type="math_number" id="iftc+mU]9EIvhV1sV%mE">
<field name="NUM">3.1</field>
</shadow>
<block type="math_arithmetic" id="${yehg5Jug1c%My+#,M{">
<field name="OP">DIVIDE</field>
<value name="A">
<shadow type="math_number" id="^~CG]!Yc??I#d$pO?Q.%">
<field name="NUM">1</field>
</shadow>
<block type="math_modulo" id="iG!+[ZO_*JMwN1h1./zY">
<value name="DIVIDEND">
<shadow type="math_number" id="_{Iit?D47qqR-0%}/.J!">
<field name="NUM">64</field>
</shadow>
<block type="variables_get" id="yXF{+o=bj/g;s@K@m$VG">
<field name="VAR" id="C9!$x^u3H!0X_8AhU89q">differenz</field>
</block>
</value>
<value name="DIVISOR">
<shadow type="math_number" id=",~p7JI:2vY!*hr#.k`p#">
<field name="NUM">60000</field>
</shadow>
</value>
</block>
</value>
<value name="B">
<shadow type="math_number" id="WLY#93Gm7:M^#^XWr#42">
<field name="NUM">1000</field>
</shadow>
</value>
</block>
</value>
</block>
</value>
</block>
</next>
</block>
</next>
</block>
</statement>
<value name="RETURN">
<block type="text_join" id="/ewmP!hW}.+#Q5]6L:|O">
<mutation items="5"></mutation>
<value name="ADD0">
<block type="procedures_callreturn" id="deM..`5KSEe?0E8v@4uA">
<mutation name="textFormatieren">
<arg name="wert"></arg>
</mutation>
<value name="ARG0">
<block type="variables_get" id="2HxX1EG@J6Mb4@fNyAh3">
<field name="VAR" id="@n!=!buWKLkR{#)CNfbb">h</field>
</block>
</value>
</block>
</value>
<value name="ADD1">
<block type="text" id="y=B{Fqr;f]@|mZ@nQrVg">
<field name="TEXT">:</field>
</block>
</value>
<value name="ADD2">
<block type="procedures_callreturn" id="$m_+NRSEHe{Qkjb1F#k*">
<mutation name="textFormatieren">
<arg name="wert"></arg>
</mutation>
<value name="ARG0">
<block type="variables_get" id="2I.7pk%JxCzMM=53+_s-">
<field name="VAR" id="v5:^*@SuhLU@E:(rkTji">m</field>
</block>
</value>
</block>
</value>
<value name="ADD3">
<block type="text" id="`3|,tT7u$ytVP3b0$ecq">
<field name="TEXT">:</field>
</block>
</value>
<value name="ADD4">
<block type="procedures_callreturn" id="sea%v,K#~Z}~,!zBeOGv">
<mutation name="textFormatieren">
<arg name="wert"></arg>
</mutation>
<value name="ARG0">
<block type="variables_get" id="9f#bHh[=eQ@IB!U!78D,">
<field name="VAR" id="Y6sidmV,eJ:33NfEyK`X">s</field>
</block>
</value>
</block>
</value>
</block>
</value>
</block>
<block type="procedures_defreturn" id="SMadYH=SPcQ9q0!CR;JE" x="188" y="-287">
<mutation>
<arg name="differenz" varid="C9!$x^u3H!0X_8AhU89q"></arg>
</mutation>
<field name="NAME">zeitDifferenzFormatierenMS</field>
<comment pinned="false" h="80" w="160">Beschreibe diese Funktion …</comment>
<statement name="STACK">
<block type="variables_set" id="$JkCL$BXrxJP=ktb#3S|">
<field name="VAR" id="@n!=!buWKLkR{#)CNfbb">h</field>
<value name="VALUE">
<block type="math_round" id="e0bSL2gS/+FpJ9N:ICFx">
<field name="OP">ROUNDDOWN</field>
<value name="NUM">
<shadow type="math_number" id="q,!WYL%nB;!*e#@Lq71v">
<field name="NUM">3.1</field>
</shadow>
<block type="math_arithmetic" id="D~KH.=tN)EF:9S*G4lZW">
<field name="OP">DIVIDE</field>
<value name="A">
<shadow type="math_number" id="wFQC`k!NL92En0#}-iuL">
<field name="NUM">1</field>
</shadow>
<block type="variables_get" id="{zaBkw2@*2o0]8s-yF1n">
<field name="VAR" id="C9!$x^u3H!0X_8AhU89q">differenz</field>
</block>
</value>
<value name="B">
<shadow type="math_number" id="gof{o.5cq5qT29J[.xP}">
<field name="NUM">60000</field>
</shadow>
</value>
</block>
</value>
</block>
</value>
<next>
<block type="variables_set" id="!Fy6aX7Zc]zHy6/d4`Nk">
<field name="VAR" id="v5:^*@SuhLU@E:(rkTji">m</field>
<value name="VALUE">
<block type="math_round" id="[v?[TYO@Oe0F[Ekjw0wm">
<field name="OP">ROUNDDOWN</field>
<value name="NUM">
<shadow type="math_number" id="iftc+mU]9EIvhV1sV%mE">
<field name="NUM">3.1</field>
</shadow>
<block type="math_arithmetic" id="aT1-T(L|(f)YB#}E[6OS">
<field name="OP">DIVIDE</field>
<value name="A">
<shadow type="math_number" id="^~CG]!Yc??I#d$pO?Q.%">
<field name="NUM">1</field>
</shadow>
<block type="math_modulo" id="h_hLg{hSmV7L4b*_z;XC">
<value name="DIVIDEND">
<shadow type="math_number" id="_{Iit?D47qqR-0%}/.J!">
<field name="NUM">64</field>
</shadow>
<block type="variables_get" id="eX`H2[Mup!IUJ-ig?DCG">
<field name="VAR" id="C9!$x^u3H!0X_8AhU89q">differenz</field>
</block>
</value>
<value name="DIVISOR">
<shadow type="math_number" id="ob3xe7FdyeQMx*1s=UTG">
<field name="NUM">60000</field>
</shadow>
</value>
</block>
</value>
<value name="B">
<shadow type="math_number" id=".$[e:?vVZsPAh+$ZSz%B">
<field name="NUM">1000</field>
</shadow>
</value>
</block>
</value>
</block>
</value>
</block>
</next>
</block>
</statement>
<value name="RETURN">
<block type="text_join" id="{7VfIE8uvj=p)1!XeBiS">
<mutation items="3"></mutation>
<value name="ADD0">
<block type="procedures_callreturn" id="VOPf$qvwsq~R{8|]_ip@">
<mutation name="textFormatieren">
<arg name="wert"></arg>
</mutation>
<value name="ARG0">
<block type="variables_get" id="6eX6,|2uZ+AW3v|[n;k}">
<field name="VAR" id="@n!=!buWKLkR{#)CNfbb">h</field>
</block>
</value>
</block>
</value>
<value name="ADD1">
<block type="text" id="_:t2xARvsZ;t*_r4eg74">
<field name="TEXT">:</field>
</block>
</value>
<value name="ADD2">
<block type="procedures_callreturn" id="/ftDta-pCMJE4HURDHL)">
<mutation name="textFormatieren">
<arg name="wert"></arg>
</mutation>
<value name="ARG0">
<block type="variables_get" id="fr)9lh7fFXigpndP!zH|">
<field name="VAR" id="v5:^*@SuhLU@E:(rkTji">m</field>
</block>
</value>
</block>
</value>
</block>
</value>
</block>
<block type="variables_set" id=",7$ZV$F-lJZa_4uB]fSP" x="188" y="13">
<field name="VAR" id="q|m4LFGW:9EM.I@+TuHi">zeitDifferenzMs</field>
<value name="VALUE">
<block type="math_arithmetic" id="Co=/N[(NP+lDG`Le67g=">
<field name="OP">MINUS</field>
<value name="A">
<shadow type="math_number" id=",~%Fgq=bAhs(;h2bjoMe">
<field name="NUM">1</field>
</shadow>
<block type="time_get" id=":U@XAojD+6V~r1*vJ9E^">
<mutation xmlns="http://www.w3.org/1999/xhtml" format="false" language="false"></mutation>
<field name="OPTION">object</field>
</block>
</value>
<value name="B">
<shadow type="math_number" id="JW5b?XuQniD;a?g.6]Z_">
<field name="NUM">1698652676943</field>
</shadow>
</value>
</block>
</value>
<next>
<block type="comment" id="ezf$yM^f;}`{S:3@KFWz">
<field name="COMMENT">Minuten</field>
<next>
<block type="debug" id="qsX/yZ[V:pIZp9rToq!/">
<field name="Severity">log</field>
<value name="TEXT">
<shadow type="text" id="v+*Bxd]6I12#lx,-RffB">
<field name="TEXT">test</field>
</shadow>
<block type="procedures_callreturn" id="jCmagd=UmZ)?wZD2AZ/g">
<mutation name="zeitDifferenzFormatierenMS">
<arg name="differenz"></arg>
</mutation>
<value name="ARG0">
<block type="variables_get" id="dzMWI,`5|T#q21~jpPvo">
<field name="VAR" id="q|m4LFGW:9EM.I@+TuHi">zeitDifferenzMs</field>
</block>
</value>
</block>
</value>
<next>
<block type="debug" id="zl6ZL/(=ik;T3FXDY?)h">
<field name="Severity">log</field>
<value name="TEXT">
<shadow type="text" id="?=i0Pr1@gVaSl(IdKa4)">
<field name="TEXT">test</field>
</shadow>
<block type="procedures_callreturn" id="j*sa4(W-35yDRFG5P$,J">
<mutation name="zeitDifferenzFormatierenHMS">
<arg name="differenz"></arg>
</mutation>
<value name="ARG0">
<block type="variables_get" id="[iVD}DC7wXVWDC4pL?e}">
<field name="VAR" id="q|m4LFGW:9EM.I@+TuHi">zeitDifferenzMs</field>
</block>
</value>
</block>
</value>
</block>
</next>
</block>
</next>
</block>
</next>
</block>
</xml>