1

Falsche Berechnung/Anzeige von Uhrzeiten (Workaround)

Bei einigen Benutzern ist nach dem letzten Ninox-Update das Problem aufgetreten, dass Differenzen zwischen zwei Uhrzeiten scheinbar falsch berechnet werden. Beispiel: Es werden folgende Daten in zwei Felder vom Typ Uhrzeit eingegeben:

Uhrzeit_von: 08:00

Uhrzeit_bis: 09:15

Ein Berechnungsfeld mit der einfachen Formel "Uhrzeit_bis - Uhrzeit von" sollte als Ergebnis nun normalerweise 01:15. anzeigen. Und die berechneten Dezimalwerte für Stunden und Minuten sollten lauten: 1,25 (Std.) bzw. 75 (Min.).

Tatsächlich kann es aber sein, dass als Differenz statt dessen plötzlich "krumme" Werte angezeigt werden:

1:15:10.854 (Uhrzeiten-Differenz)

1,2530 (Stunden dezimal)

75,1809 (Minuten dezimal)

Die Abweichungen sind zwar nur gering, für Otto Normalnutzer aber sehr irritierend. Und sie können in der Summe, z. B. bei minutengenauen Abrechnungen, natürlich auch zu falschen Ergebnissen führen.

Ursache

Datums- und Uhrzeitwerte werden intern in Millisekunden umgerechnet und als Zahl gespeichert. Da in der Regel nur Stunden und Minuten eingegeben werden, z.B. 09:15, setzt Ninox den Wert für Sekunden und Millisekunden automatisch auf 0, die vollständige Zeitangabe also auf 09:15:00.000. Damit wird sicher gestellt, dass auch nur volle Minuten berechnet werden.

Seit dem letzten Update kann es aber sein, dass die Sekunden und Millisekunden NICHT automatisch auf 0 gesetzt, sondern mit den tatsächlichen Werten des Augenblicks der Eingabe gespeichert werden, also bspw. 09:15:28.998. Das führt natürlich zwangsläufig zu anderen, zumeist "krummen" Ergebnissen bei der Berechnung von Differenzen.

Das heißt, die Berechnungen sind im Grunde richtig, aber die Ausgangswerte sind falsch. Nach der eigentlichen Ursache, dem Nicht-auf-0-setzen der Sekunden und Millisekunden, suchen Support und Entwickler noch.

Lösung (Workaround):

Sollte das Problem bei jemandem auftreten: Keine Panik! Es ist weniger dramatisch, als es auf den ersten Blick den Anschein hat. Es gehen keine Daten verloren und die angezeigten Ergebnisse lassen sich auch relativ einfach korrigieren.

Prophylaktisch, in dem man die Werte für Sekunden und Millisekunden bei der Eingabe der Uhrzeit mit Hilfe der Funktion time() auf 0 setzt. Dazu erstellt man in den Uhrzeitfeldern einen Trigger "Nach Änderung" mit folgendem Code (am Beispiel des Feldes Uhrzeit_von):

let myTime := split(text(Uhrzeit_von), ":");
let myStd := number(item(myTime, 0));
let myMin := number(item(myTime, 1));
Uhrzeit_von := time(myStd, myMin, 0, 0)

Damit werden die Stunden und Minuten der soeben erfassten Uhrzeit ausgelesen, Sekunden und Millisekunden auf 0 gesetzt und das Feld mit dem neuen Wert aktualisiert. Da das kleine Script nur bei der Eingabe einer Uhrzeit ausgeführt wird, wirkt es sich nicht negativ auf die Performance der Tabelle oder der Datenbank aus.

Um nachträglich bereits falsch gespeicherte Uhrzeiten und deren Ergebnisse zu korrigieren, kann man einmalig über die Console oder einen Button folgendes Script ausführen (am Beispiel zweier Uhrzeitfelder namens Uhrzeit_von und Uhrzeit_bis):

for i in select TABELLE do
   let myTimeV := split(text(i.Uhrzeit_von), ":");
   let myStdV := number(item(myTimeV, 0));
   let myMinV := number(item(myTimeV, 1));
   let myTimeB := split(text(i.Uhrzeit_bis), ":");
   let myStdB := number(item(myTimeB, 0));
   let myMinB := number(item(myTimeB, 1));
   i.Uhrzeit_von := time(myStdV, myMinV, 0, 0));
   i.(Uhrzeit_bis := time(myStdB, myMinB, 0, 0))
end

Für TABELLE, Uhrzeit_von und Uhrzeit_bis sind natürlich die tatsächlichen Namen einzusetzen. Bei einer größeren Anzahl von Datensätzen (ab 3-stellig) empfiehlt sich zudem, den Code in ein "do as server ... end" einzubetten.

Ich selbst habe o. g. Scripte in mehreren Datenbanken eingesetzt, wo sie problemlos funktionieren.

Dennoch sollte nach Möglichkeit wie immer bei solchen Aktionen vorher eine Sicherheitskopie der Datenbank angelegt werden. User mit Starter-Account müssen halt das Risiko eingehen oder bis zum nächsten automatischen Backup von Ninox warten.

Disclaimer:

Zusammengestellt nach bestem Wissen und Gewissen, aber ohne Gewähr. Es gilt wie immer: Vorsicht an der Bahnsteigkante, Eltern haften für ihre Kinder etc. pp.

2 Antworten

null
    • Ninox-Professional
    • planoxpro
    • vor 1 Jahr
    • Gemeldet - anzeigen

    Weil gerade wieder danach gefragt wurde, erlaube ich mir, das Thema aus den Tiefen des Forums noch mal ans Tageslicht zu befördern. 

    • Ninox-Professional
    • planoxpro
    • vor 1 Jahr
    • Gemeldet - anzeigen

    Update

    Gestern ist es mir bei einem neuen Projekt wieder passiert, diesmal mit datetime(). Es gibt dort zwei Schaltflächen, eine für "Anfahrt" und eine für "Abfahrt", mit denen jeweils die Werte aus now() in gleichnamige Felder vom Typ Datum+Zeit geschrieben wurden. Und in einem weiteren Funktionsfeld wurde dann mit "Abfahrt - Anfahrt" einfach die Differenz, also die Dauer berechnet.

    Leider kam es dabei wieder zu falschen Ergebnissen, weil auch hier offenbar die Sekunden nicht automatisch auf 0 gesetzt wurden. Ich habe oben beschriebenen Workaround deshalb für datetime() angepasst. Damit scheint es nun wieder zu funktionieren.

    Der Code für die Schaltfläche, mit der die 'Anfahrt' gesetzt wird:

    let myNow := split(text(time(now())), ":");
    let myStd := number(item(myNow, 0));
    let myMin := number(item(myNow, 1));
    let myTime := time(myStd, myMin, 0, 0);
    let myDate := date(year(now()), month(now()), day(now()));
    let myDatetime := datetime(myDate, myTime);
    Anfahrt := myDatetime

    Bei "Abfahrt" muss nur der Feldbezug in der letzten Zeile geändert werden.

    Falls die Werte nicht per Schaltfläche gesetzt, sondern manuell eingegeben werden, kann der Code natürlich auch in einem Änderungstrigger eingesetzt werden. Dazu müsste nur jedes "now()" in der ersten und fünften Zeile durch das betreffende datetime-Feld ersetzt werden (im Beispiel: 'Anfahrt').

Content aside

  • 1 „Gefällt mir“ Klicks
  • vor 1 JahrZuletzt aktiv
  • 2Antworten
  • 201Ansichten
  • 2 Folge bereits