[Patch] 99_Utils.pm: decimal_mark()

Begonnen von Loredo, 11 April 2017, 00:28:27

Vorheriges Thema - Nächstes Thema

Loredo

Hallo,

ich habe eine Funktion für 99_Utils geschrieben, um Dezimaltrennzeichen zu einer Zahl hinzuzufügen.
Dabei wird die global gesetzte Spracheinstellung berücksichtigt, eine explizit übergebene Sprache oder ein SI-Standard.

Die CommandRef habe ich ebenfalls dafür erweitert:


    <li><b>decimal_mark(value, format)</b><br>
      add decimal marks to &lt;value&gt;. Defaults to SI standard format
      according to language attribute from global. Format may be set explicitly
      either to a specific language or a number equivalent:<br>
      SI standard (english): std or 0 (example: 1 234 456.780 932)<br>
      SI standard (french): std-fr or 1 (example: 1 234 456,780 932)<br>
      English: en or 0 (example: 4456.780 932)<br>
      Swiss: de_ch or 0 (example: 4456.780 932)
      German: de or 1 (example: 4456,780 932)<br>
      French: fr or 1 (example: 4456,780 932)<br>
      Polish: pl or 1 (example: 4456,780 932)<br>
      Netherlandish: nl or 1 (example: 4456,780 932)<br>
      Old-English: old-english or 2 (example: 1,234,567.890932)<br>
      Old-European: old-european or 3 (example: 1.234.567,890932)<br>
      Swiss: ch or 4 (example: 1'234'567.890932)
      Austrian: de_at or 5 (example: 4 456,780 932)<br>
      </li><br/>


Da ich glaube, dass diese Funktion auch andere brauchen können, würde ich sie gerne in 99_Utils zur Verfügung stellen.

Bei der Gelegenheit habe ich bei round() den zweiten Parameter optional gesetzt, vielleicht wäre es auch möglich diesen Einzeiler mit zu übernehmen.


Gruß
Julian
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER

rudolfkoenig

Zu welchem Zweck wird das benoetigt?

Ich sehe die Gefahr, dass Modulautoren / Benutzer Readings damit formatieren, und dadurch diese fuer die nachfolgende Datenverarbeitung unbrauchbar machen. Die Benutzer wuerden danach einzeln bei den Maintainer dieser nachfolgenden "Problem-Module" auftauchen, die entweder versuchen eine Loesung zu finden, oder das Problem boykottieren. Eine solche Lawine moechte ich ungern ausloesen.

Abgesehen davon bin ich der Ansicht, dass man sowas auch durch Verwendung von Betriebsystemfunktonen realisieren kann, eine FHEM-Locale-Datenbank (und das auch noch als Code) aufzubauen finde ich unklug.

Loredo

#2
Ich habe den Patch oben nochmals etwas angepasst, so dass auch normaler Text damit formatiert werden kann.
Beispielsweise kann eine IBAN Nummer damit korrekt formatiert werden:


{ decimal_mark("DE44500105175407324931", {  group=>4, reverse=>0 } ) }

Ergebnis:
DE44 5001 0517 5407 3249 31


Zitat von: rudolfkoenig am 11 April 2017, 09:43:20
Zu welchem Zweck wird das benoetigt?

Der Zweck ist z.B. dafür, dass man Textblöcke mit Zahlenwerten, die man z.B. bei Benachrichtigungen per Pushnachricht oder E-Mail verwendet und aus Reading-Values generiert, besser lesbar bzw. nach lokaler Sprache formatieren kann. Aus 26.5°C kann dann z.B. 26,5°C werden, aus 112345.45 Wh wird 112 345,45 Wh (wenn man die Einheit im Text manuell dahinter hängt).

Zitat von: rudolfkoenig am 11 April 2017, 09:43:20
Ich sehe die Gefahr, dass Modulautoren / Benutzer Readings damit formatieren, und dadurch diese fuer die nachfolgende Datenverarbeitung unbrauchbar machen.

Hier würde ich an den Verstand von Modulautoren und Benutzern appellieren wollen. Wir können das auch explizit im Wiki und der CommandRef betonen, dass dies zu reinen Formatierungszwecken dient.
Im Falle der Verwendung der SI-Standard Formatierung lässt sich allerdings die eigentliche Zahl ganz einfach wieder extrahieren, da nur mit (geschützten) Leerzeichen gearbeitet wird. Ich kann dafür noch eine Reverse-Funktion bereitstellen, die man dann bei Bedarf verwenden kann (EDIT: Zum Patch wurde decimal_markNum() hinzugefügt). Diese einfache Rücküberführung in maschinenlesbare Zahlen war wohl einer der Gründe, weshalb der SI-Standard mit Leerzeichen gewählt wurde.

Zitat von: rudolfkoenig am 11 April 2017, 09:43:20Die Benutzer wuerden danach einzeln bei den Maintainer dieser nachfolgenden "Problem-Module" auftauchen, die entweder versuchen eine Loesung zu finden, oder das Problem boykottieren. Eine solche Lawine moechte ich ungern ausloesen.
Das könnte man verhindern, indem man (endlich) Unit/RType zentral in FHEM bereitstellt, so dass die Anzeige von Werten in GUIs getrennt von dem ursprünglichen Value sein kann. Dann kommt auch kein User oder Modulautor in Versuchung das Reading-Value direkt zu formatieren.

Zitat von: rudolfkoenig am 11 April 2017, 09:43:20
Abgesehen davon bin ich der Ansicht, dass man sowas auch durch Verwendung von Betriebsystemfunktonen realisieren kann, eine FHEM-Locale-Datenbank (und das auch noch als Code) aufzubauen finde ich unklug.


Ich kann keine vergleichbare Perl Funktion finden. Zudem wäre da auch die Frage der Verfügbarkeit auf jedem System.

Ich glaube auch, dass es da kein einheitliches Perl Modul für geben wird/kann, da die Formatierungen lt. Wikipedia ohnehin hier und da Interpretationsspielraum lassen. Das Ergebnis meiner Interpretation ist die Funktion decimal_mark() von der ich glaube, dass sie für FHEM so sinnvoll ist.

Dass man die passende Formatierung auch über die Sprache auswählen kann, ist nur eine Vereinfachung (es wird sogar ein userAttribut von global berücksichtigt, mit dem man eine bei Bedarf zentrale Voreinstellung abweichend vom globalen language-Attribut hinterlegen kann). Maßgeblich sind die Formate


   "std" - SI-Standard nach englischer Nomenklatur - unabhängig der Sprache
   "std-fr" - SI-Standard nach französischer Nomenklatur - unabhängig der Sprache
   "old-english" - für die alte Schreibweise mit Komma statt Leerzeichen als Tausender Trenner
   "old-european" - für die alte Schreibweise mit Punkt statt Leerzeichen als Tausender Trenner
   "ch" - die Schweiz hat hier ihr eigenes Süppchen, zumindest in der Schule lt. Wikipedia.

Im Grunde nutzen alle Länder inzwischen einen der beiden SI-Standards, weshalb auch die Vorauswahl für alle einer der beiden Standards ist. Ein Trennzeichen wird erst ab 5-stelligen Zahlenreihen vorgenommen. Österreich bildet hier eine Ausnahme und macht das bereits ab 4 Stellen. Kann man aber alles in der Wikipedia nachlesen, wenn es interessiert  ;)   Ich habe dazu im Quellcode eine Reihe von Links mit hinterlegt.
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER

rudolfkoenig

ZitatDer Zweck ist z.B. dafür, dass man Textblöcke mit Zahlenwerten, die man z.B. bei Benachrichtigungen per Pushnachricht oder E-Mail verwendet und aus Reading-Values generiert, besser lesbar bzw. nach lokaler Sprache formatieren kann.

Ich sehe ein, dass vorgelesene Texte merkwuerdig sind, wenn sie nicht in der lokalen Sprache formatiert sind. Aber wenn man nicht ganz sicher ist, nach welchen Regeln es formatiert ist, dann ist 123.345 oder 3/4/2017 mehrdeutig und sowas wie 3/4/2017 kann man weder alphabetisch sortieren noch einfach vergleichen. Ich habe Angst, dass Du durch diese Hintertuer mit der Lokalisierung anfaengst, und ich in den naechsten 10 Jahren damit beschaeftigt bin, in allen Modulen locale nachzuziehen. Wenn locale, dann nicht als Feierabendprojekt.

Ich bin bereit die Funktion aufzunehmen, falls sie einen besseren Namen (sowas wie humanReadable) bekommt, und in der Doku darauf hingewiesen wird, dass es nur fuer Vorlesen/Darstellung verwendet wird, und mit so formatierten Daten nie mehr eine Weiterverarbeitung (Rechnen, Vergleichen, Sortieren, Plot, etc) moeglich sein wird. Selbst damit habe ich Bauchschmerzen, weil die Leute keine Doku lesen, und am Anfang nicht wissen, dass sie spaeter doch rechnen/sortieren/etc wollen, und dann kommen sie zu mir betteln.

JoWiemann

Zitat von: Loredo am 11 April 2017, 10:41:13
Ich habe den Patch oben nochmals etwas angepasst, so dass auch normaler Text damit formatiert werden kann.
Beispielsweise kann eine IBAN Nummer damit korrekt formatiert werden:


{ decimal_mark("DE44500105175407324931", {  group=>4, reverse=>0 } ) }

Ergebnis:
DE44 5001 0517 5407 3249 31



Prüfung der IBAN:

Diese IBAN hat die richtige Länge für dieses Land (Deutschland).
Bankleitzahl 50010517: Dieser Bankcode ist korrekt.
Kontonummer 5407324931: Die Kontonummer enthält eine falsche Prüfziffer. (Details)
IBAN DE44500105175407324931: Die IBAN-Prüfsumme stimmt.

Deine Kontonummer?!

Jörg Wiemann

Slave: RPi B+ mit 512 MB, COC (868 MHz), CUL V3 (433.92MHz SlowRF); FHEMduino, Aktuelles FHEM

Master: CubieTruck; Debian; Aktuelles FHEM

Loredo

#5
Zitat von: rudolfkoenig am 11 April 2017, 12:32:20
Ich sehe ein, dass vorgelesene Texte merkwuerdig sind, wenn sie nicht in der lokalen Sprache formatiert sind. Aber wenn man nicht ganz sicher ist, nach welchen Regeln es formatiert ist, dann ist 123.345 oder 3/4/2017 mehrdeutig und sowas wie 3/4/2017 kann man weder alphabetisch sortieren noch einfach vergleichen. Ich habe Angst, dass Du durch diese Hintertuer mit der Lokalisierung anfaengst, und ich in den naechsten 10 Jahren damit beschaeftigt bin, in allen Modulen locale nachzuziehen. Wenn locale, dann nicht als Feierabendprojekt.

Die Regeln sind ganz klar und eindeutig, dafür gibt es die offiziellen Standards. Es geht auch nur um Messwerte, nicht um Datumsformatierung oder ähnliches (letzteres ist in Unit/RType abgedeckt, was bisher nicht direkt in FHEM eingebunden ist).

locale ist ein ganz anderes Thema. Das hier ist eine ganz einfache Funktion, mit der man nur seine Messwerte in übersichtlicher Art in einen Text mit einbinden kann, nichts weiter.

Zitat von: rudolfkoenig am 11 April 2017, 12:32:20
Ich bin bereit die Funktion aufzunehmen, falls sie einen besseren Namen (sowas wie humanReadable) bekommt, und in der Doku darauf hingewiesen wird, dass es nur fuer Vorlesen/Darstellung verwendet wird, und mit so formatierten Daten nie mehr eine Weiterverarbeitung (Rechnen, Vergleichen, Sortieren, Plot, etc) moeglich sein wird. Selbst damit habe ich Bauchschmerzen, weil die Leute keine Doku lesen, und am Anfang nicht wissen, dass sie spaeter doch rechnen/sortieren/etc wollen, und dann kommen sie zu mir betteln.

Die Formatierung lässt sich ganz einfach entfernen, die zweite Funktion dafür habe ich dem Patch oben bereits angefügt. Dann kann man auch mit einer zuvor formatierten Zahl wieder rechnen wie Graf Zahl  :)

Die Funktion in humanReadable() umzubenennen wäre durchaus nicht ganz unlogisch, denn man kann damit ja eben auch Text/Zahlenkombinationen wie IBAN Nummern gruppiert formatieren. Das ist dann nichts anderes.
Die Reverse-Funktion könnte man dann entweder humanReadableNum(), humanReadableReverse() oder machineReadable() nennen. Damit sie den letzten Namen verdient, müsste man vielleicht nochmal kurz darüber nachdenken, wie sie sich von ReadingsNum() unterscheiden lässt oder ob man dann machineReadable() nicht sogar in ReadingsNum() etc. hernähme, um die Nummer zu extrahieren und gleichzeitig evtl. Formatierung zu entfernen. So weit würde ich aber nicht unbedingt gehen; da will ich dich auch nicht zu sehr aus der Reserve locken  ;)



Gruß
Julian
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER

Loredo

Zitat von: JoWiemann am 11 April 2017, 12:49:33
Deine Kontonummer?!

Vielleicht von jemand anderem; habe ich aus der Wikipedia kopiert  :P
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER

rudolfkoenig

ZitatDie Formatierung lässt sich ganz einfach entfernen, die zweite Funktion dafür habe ich dem Patch oben bereits angefügt. Dann kann man auch mit einer zuvor formatierten Zahl wieder rechnen wie Graf Zahl  (https://forum.fhem.de/Smileys/default/smiley.gif)

Jein. Der Benutzer/Modulautor konvertiert die Daten, speichert sie konvertiert in der Logfile, und erwartet von mir, dass ich das per Plot richtig anzeige, weil er kann das dann nicht mehr. Oder es wird elendig langsam. Und das ist nur _ein_ Beispiel.

betateilchen

Das kann doch Number::Format alles von Haus aus?


use Number::Format;

my $fmt = Number::Format->new(
    THOUSANDS_SEP => q{.},
    DECIMAL_POINT => q{,},
);

return $fmt->format_number(1234.12, 2, 1);


einschließlich Berücksichtigung von locale, Währungen, Rundungen und vielem mehr.

Warum will man einmal mehr das Rad neu erfinden?
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

justme1968

eine solche funktion gehört meiner meinung nach ins frontend und nicht in die module. modul intern, für logfiles und plots sollte das perl format verwendet werden.

die lokale formatierung muss dann bei der anzeige im frontend berücksichtigt werden.

wenn man das lokale format bereits modul intern anwendet ist das ganze nicht mehr eindeutig, lässt sich nicht mehr vernünftig weiterverarbeiten und gibt alle möglichen probleme weil eventuell mehrfach hin und zurück konvertiert wird ohne das man eindeutig sagen kann in welchem format die daten waren.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968