Die Uhrzeit in Worten - oder aus 13:50 Uhr wird "Es ist zehn vor zwei"

Begonnen von binford6000, 13 März 2018, 15:55:59

Vorheriges Thema - Nächstes Thema

binford6000

Hallo Zusammen,
in Anlehnung an das Original "QLOCKTWO" von Biegert & Funk habe ich ein kleines Stück Perl-Code für die 99_myUtils.pm geschrieben.
Der Code beansprucht keinen Schönheitspreis - form follows function...

Was macht es? Ganz einfach: Es gibt die aktuelle Uhrzeit in Worten aus, also so wie man sie ausspricht.
Aus 13:50 Uhr wird "Es ist zehn vor zwei.", aus 20:25 Uhr wird "Es ist fünf vor halb neun." usw.
Durch Auf- bzw. Abrunden ändert sich die Ausgabe nur alle volle 5 Minuten.

Mögliche Anwendungen sind zB. die Anzeige in einem Frontend oder eine Sprachausgabe.

## Ausgabe der Zeit in natürlicher Sprache mit Auf- und Abrundung

sub qlock2() {
my ($Sekunden, $Minuten, $Stunden, $Monatstag, $Monat, $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime(time);
my $Minute = $Minuten;
my $Stunde = $Stunden;
my $spoke = "Es ist $Stunden Uhr $Minuten.";
## 24h in 12h umwandeln
if ($Stunden <= 12) { $Stunde = $Stunden }
if ($Stunden >= 13) { $Stunde = $Stunden - 12 }
if ($Stunden == 0) { $Stunde = 12 }
{
  ## Variante West: Ab Minute 23 die nächste Stunde ansagen > viertel vor 12 um 11:45 Uhr
  if ($Minuten >= 23 && ($Stunde >= 1 && $Stunde <= 11)) { $Stunde = $Stunde + 1 }
  elsif ($Minuten >= 23 && $Stunde == 12) { $Stunde = $Stunde - 11 }
}
## Umwandlung der Stunde von einer Zahl in Text
my @hourNames=('eins','zwei','drei','vier','fünf','sechs','sieben','acht','neun','zehn','elf','zwölf');
$Stunde=$hourNames[$Stunde-1];
## Aufrunden (bei Minuten 3,4,8,9) / Abrunden (bei Minuten 1,2,6,7) auf volle 5 Minuten
if ($Minuten =~ /([0-5]*1$)|([0-5]*6$)/) { $Minute = $Minuten - 1 }
if ($Minuten =~ /([0-5]*4$)|([0-5]*9$)/) { $Minute = $Minuten + 1 }
if ($Minuten =~ /([0-5]*2$)|([0-5]*7$)/) { $Minute = $Minuten - 2 }
if ($Minuten =~ /([0-5]*3$)|([0-5]*8$)/) { $Minute = $Minuten + 2 }
## Zusammensetzen der gesprochenen Uhrzeit
if ($Minute =~ /(^0)|(60)/) {
  $spoke = "Es ist ein Uhr." if ($Stunde eq "eins");
  $spoke = "Es ist $Stunde Uhr." if ($Stunde ne "eins");
}
elsif ($Minute == 5) {
  $spoke = "Es ist fünf nach $Stunde.";
}
elsif ($Minute == 10) {
  $spoke = "Es ist zehn nach $Stunde.";
}
elsif ($Minute == 15) {
  $spoke = "Es ist viertel nach $Stunde.";
}
elsif ($Minute == 20) {
  $spoke = "Es ist zwanzig nach $Stunde.";
}
elsif ($Minute == 25) {
  $spoke = "Es ist fünf vor halb $Stunde.";
}
elsif ($Minute == 30) {
  $spoke = "Es ist halb $Stunde.";
}
elsif ($Minute == 35) {
  $spoke = "Es ist fünf nach halb $Stunde.";
}
elsif ($Minute == 40) {
  $spoke = "Es ist zwanzig vor $Stunde.";
}
elsif ($Minute == 45) {
  $spoke = "Es ist viertel vor $Stunde.";
}
elsif ($Minute == 50) {
  $spoke = "Es ist zehn vor $Stunde.";
}
elsif ($Minute == 55) {
  $spoke = "Es ist fünf vor $Stunde.";
}
## Ausgabe der gesprochenen Uhrzeit: "Es ist ..." in ein Reading, oder direkt als Sprachausgabe oder...
fhem "setreading device zeit $spoke";
fhem "set Sonos_Kueche speak 40 DE $spoke";
return $spoke;
}


Politisch korrekt wahlweise auch im "Es ist viertel 11." / "Es ist drei viertel elf." Format  ;)

## Ausgabe der Zeit in natürlicher Sprache mit Auf- und Abrundung

sub qlock2() {
my ($Sekunden, $Minuten, $Stunden, $Monatstag, $Monat, $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime(time);
my $Minute = $Minuten;
my $Stunde = $Stunden;
my $spoke = "Es ist $Stunden Uhr $Minuten.";
## 24h in 12h umwandeln
if ($Stunden <= 12) { $Stunde = $Stunden }
if ($Stunden >= 13) { $Stunde = $Stunden - 12 }
if ($Stunden == 0) { $Stunde = 12 }
{
  ## Variante Ost: Zwischen Minute 13 und 17 sowie ab Minute 23 die nächste Stunde ansagen > drei viertel 12 um 11:45 Uhr
  if ((($Minuten >= 13 && $Minuten <= 17) || $Minuten >= 23) && ($Stunde >= 1 && $Stunde <= 11)) { $Stunde = $Stunde + 1 }
  elsif ((($Minuten >= 13 && $Minuten <= 17) || $Minuten >= 23) && $Stunde == 12) { $Stunde = $Stunde - 11 }
}
## Umwandlung der Stunde von einer Zahl in Text
my @hourNames=('eins','zwei','drei','vier','fünf','sechs','sieben','acht','neun','zehn','elf','zwölf');
$Stunde=$hourNames[$Stunde-1];
## Aufrunden (bei Minuten 3,4,8,9) / Abrunden (bei Minuten 1,2,6,7) auf volle 5 Minuten
if ($Minuten =~ /([0-5]*1$)|([0-5]*6$)/) { $Minute = $Minuten - 1 }
if ($Minuten =~ /([0-5]*4$)|([0-5]*9$)/) { $Minute = $Minuten + 1 }
if ($Minuten =~ /([0-5]*2$)|([0-5]*7$)/) { $Minute = $Minuten - 2 }
if ($Minuten =~ /([0-5]*3$)|([0-5]*8$)/) { $Minute = $Minuten + 2 }
## Zusammensetzen der gesprochenen Uhrzeit
if ($Minute =~ /(^0)|(60)/) {
  $spoke = "Es ist ein Uhr." if ($Stunde eq "eins");
  $spoke = "Es ist $Stunde Uhr." if ($Stunde ne "eins");
}
elsif ($Minute == 5) {
  $spoke = "Es ist fünf nach $Stunde.";
}
elsif ($Minute == 10) {
  $spoke = "Es ist zehn nach $Stunde.";
}
elsif ($Minute == 15) {
  $spoke = "Es ist viertel $Stunde.";
}
elsif ($Minute == 20) {
  $spoke = "Es ist zwanzig nach $Stunde.";
}
elsif ($Minute == 25) {
  $spoke = "Es ist fünf vor halb $Stunde.";
}
elsif ($Minute == 30) {
  $spoke = "Es ist halb $Stunde.";
}
elsif ($Minute == 35) {
  $spoke = "Es ist fünf nach halb $Stunde.";
}
elsif ($Minute == 40) {
  $spoke = "Es ist zwanzig vor $Stunde.";
}
elsif ($Minute == 45) {
  $spoke = "Es ist drei viertel $Stunde.";
}
elsif ($Minute == 50) {
  $spoke = "Es ist zehn vor $Stunde.";
}
elsif ($Minute == 55) {
  $spoke = "Es ist fünf vor $Stunde.";
}
## Ausgabe der gesprochenen Uhrzeit: "Es ist ..." in ein Reading, oder direkt als Sprachausgabe oder...
fhem "setreading device zeit $spoke";
fhem "set Sonos_Kueche speak 40 DE $spoke";
return $spoke;
}


Hier noch eine weitere Variante, welche nur alle vollen 5 Minuten die Zeit in gesprochener
Sprache ausgibt. Bei allen anderen Minuten wird die Zeit als "Stunden Uhr Minuten." ausgegeben.

##Ausgabe der Zeit in natürlicher Sprache

sub qlock2() {
my ($Sekunden, $Minuten, $Stunden, $Monatstag, $Monat, $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime(time);
my $Minute = $Minuten;
my $Stunde = $Stunden;
my $spoke = "Es ist $Stunden Uhr $Minuten.";
## 24h in 12h umwandeln
if ($Stunden <= 12) { $Stunde = $Stunden }
if ($Stunden >= 13) { $Stunde = $Stunden - 12 }
if ($Stunden == 0) { $Stunde = 12 }
## Wahlweise West- oder Ost-VAriante. Bitte den jeweils anderen Block auskommentieren!
{
  ## Ost: Zwischen Minute 13 und 17 sowie ab Minute 23 die nächste Stunde ansagen > drei viertel 12 um 11:45 Uhr
  if ((($Minuten >= 13 && $Minuten <= 17) || $Minuten >= 23) && ($Stunde >= 1 && $Stunde <= 11)) { $Stunde = $Stunde + 1 }
  elsif ((($Minuten >= 13 && $Minuten <= 17) || $Minuten >= 23) && $Stunde == 12) { $Stunde = $Stunde - 11 }
}
##{
## West: Ab Minute 23 die nächste Stunde ansagen > viertel vor 12 um 11:45 Uhr
##  if ($Minuten >= 23 && ($Stunde >= 1 && $Stunde <= 11)) { $Stunde = $Stunde + 1 }
##  elsif ($Minuten >= 23 && $Stunde == 12) { $Stunde = $Stunde - 11 }
##}
## Zusammensetzen der gesprochenen Uhrzeit
if ($Minute =~ (/(^0{1})|(5)|(10)|(15)|(20)|(25)|(30)|(35)|(40)|(45)|(50)|(55)|(60)/)) {
my @hourNames=('eins','zwei','drei','vier','fünf','sechs','sieben','acht','neun','zehn','elf','zwölf');
$Stunde=$hourNames[$Stunde-1];
  if ($Minute =~ /(^0{1})|(60)/) {
    $spoke = "Es ist ein Uhr." if ($Stunde eq "eins");
$spoke = "Es ist $Stunde Uhr." if ($Stunde ne "eins");
    }
  elsif ($Minute == 5) {
    $spoke = "Es ist fünf nach $Stunde.";
  }
  elsif ($Minute == 10) {
    $spoke = "Es ist zehn nach $Stunde.";
  }
  elsif ($Minute == 15) {
    ##$spoke = "Es ist viertel nach $Stunde.";
    $spoke = "Es ist viertel $Stunde.";
  }
  elsif ($Minute == 20) {
    $spoke = "Es ist zwanzig nach $Stunde.";
  }
  elsif ($Minute == 25) {
    $spoke = "Es ist fünf vor halb $Stunde.";
  }
  elsif ($Minute == 30) {
    $spoke = "Es ist halb $Stunde.";
  }
  elsif ($Minute == 35) {
    $spoke = "Es ist fünf nach halb $Stunde.";
  }
   elsif ($Minute == 40) {
    $spoke = "Es ist zwanzig vor $Stunde.";
  }
  elsif ($Minute == 45) {
    ##$spoke = "Es ist viertel vor $Stunde.";
    $spoke = "Es ist drei viertel $Stunde.";
  }
  elsif ($Minute == 50) {
    $spoke = "Es ist zehn vor $Stunde.";
  }
  elsif ($Minute == 55) {
    $spoke = "Es ist fünf vor $Stunde.";
  }
}
## Ausgabe der gesprochenen Uhrzeit: "Es ist ..." in ein Reading, oder direkt als Sprachausgabe oder...
fhem "setreading device zeit $spoke";
##fhem "set Sonos_Kueche speak 40 DE $spoke";
return $spoke;
}


Teile des Codes wurden von https://forum.fhem.de/index.php/topic,34891.0.html weiterverwendet. Danke an Toto1973.
Viel Spaß damit!
VG Sebastian

EDIT: Umwandlung von Zahl in Text geändert (jetzt ohne PERL WARNING). Danke an Benni!
EDIT 2: Zwei Beispiele angehängt.

Invers

Pi3B+ mit SSD/ Bullseye | FB7590 AX | 12 x Dect200 | CUL433+868 | SDuino | HM-LAN | 3 x Heizung FHT + FKontakte | KeyMatic + 4 FB | HM Wandtaster 2-fach m. LED | 6 x Türkont. TFK-TI | HM-Bew.-Melder innen | 3 x Smoked. HM-SEC-SD-2

raiderxxl

Hallo

Anzeigen lässt es sich... nur wie lasse ich mir das jetzt vorlesen? Steh grade auf Schlauch,,,

Also set mytts tts {qlock2} tut nicht...
Sorry ist meine erste Funktion in 99_myUtils.pm ;-)

Grüßle

Pascal
FHEM VM Ubuntu-Server auf Intel® NUC-Kit NUC6i5SYH ESXi 6.5
FHEM auf Raspberry2 OSMC Hyperion und TTS

Homematic,TradfriHub und Lampen,WIFILight,Fritzbox,FritzDECT,NanoCul433,IT Steckdosen,Diverse Nachbar-Sensoren,XiaomiZigbee,
ESP_Signalduino,ESPEasy,Amad,HarmonyHub,WLED,MQTT,Tasmota....

the ratman

du rufst das zeug einfach auf mit {qclock2} dort, wo du normaler weise dein set mytts ... stehen würde, wenn du kein myutils verwenden würdest.
bei nem doif wäre das also im ausführungsteil ungefähr so: ({qclock2}) zu behandeln. funzt zumindest bei mir.

dein mytts ... gibst du dafür dann im script am ende an.
dort hat der nette onkel eh schon 2 bspl. rein getan - siehe:## Ausgabe der gesprochenen Uhrzeit: "Es ist ..." in ein Reading, oder direkt als Sprachausgabe oder...
## fhem "setreading device zeit $spoke";
## fhem "set Sonos_Kueche speak 40 DE $spoke";
fhem "set mytts tts $spoke";
return $spoke;
die 2 beispiele tust raus, deinen befehl rein und den "return $spoke;" lässt du leben ... funzt ... und dann kannst dich über jede menge warnings im log freuen,weil die jeweils gesprochene zahl als wort von perl bemängelt wird.
da müsste mal ein perl-pro drüber tippen - ich habs nicht hingebracht die warnings los zu werden ... aber ansagen tut er mal wie gewollt ...
→do↑p!dnʇs↓shit←

binford6000

Zitatda müsste mal ein perl-pro drüber tippen - ich habs nicht hingebracht die warnings los zu werden ... aber ansagen tut er mal wie gewollt ...

Ja das wäre sehr nett! Ich habe jeweils immer nur einmal die PERL WARNING im Log, und zwar bei jeder neuen Stunde:
2018.03.15 17:33:21 1: PERL WARNING: Argument "sechs" isn't numeric in numeric eq (==) at ./FHEM/99_myUtils.pm line 43.
2018.03.15 18:49:01 1: PERL WARNING: Argument "sieben" isn't numeric in numeric eq (==) at ./FHEM/99_myUtils.pm line 43.
2018.03.15 20:01:12 1: PERL WARNING: Argument "acht" isn't numeric in numeric eq (==) at ./FHEM/99_myUtils.pm line 44.


Beliebige Wiederholungen der Sprachausgabe in der gleichen Stunde werden nicht mehr beanstandet... ???
VG Sebastian

Frank_Huber

Zitat von: binford6000 am 15 März 2018, 20:13:32
2018.03.15 17:33:21 1: PERL WARNING: Argument "sechs" isn't numeric in numeric eq (==) at ./FHEM/99_myUtils.pm line 43.
2018.03.15 18:49:01 1: PERL WARNING: Argument "sieben" isn't numeric in numeric eq (==) at ./FHEM/99_myUtils.pm line 43.
2018.03.15 20:01:12 1: PERL WARNING: Argument "acht" isn't numeric in numeric eq (==) at ./FHEM/99_myUtils.pm line 44.


Bin kein Perl Profi, aber das klingt einfach.
Poste mal bitte deine Zeilen 43 und 44.
Da gibt's nen numerischen Vergleich gegen ein Wort.

Mit dem Handy online, daher kurz gefasst...

the ratman

jo, und ich denke, hier is der hund begraben## Umwandlung der Stunde von einer Zahl in Text
if ($Stunde == 1) { $Stunde = "eins" } if ($Stunde == 2) { $Stunde = "zwei" }
if ($Stunde == 3) { $Stunde = "drei" } if ($Stunde == 4) { $Stunde = "vier" }
if ($Stunde == 5) { $Stunde = "fünf" } if ($Stunde == 6) { $Stunde = "sechs" }
if ($Stunde == 7) { $Stunde = "sieben" } if ($Stunde == 8) { $Stunde = "acht" }
if ($Stunde == 9) { $Stunde = "neun" } if ($Stunde == 10) { $Stunde = "zehn" }
if ($Stunde == 11) { $Stunde = "elf" } if ($Stunde == 12) { $Stunde = "zwölf" }

wenn er mal was gesagt hat, is ja "1"dann "eins" geworden. btw. im 1. post findest das script ...
→do↑p!dnʇs↓shit←

binford6000

ZitatDa gibt's nen numerischen Vergleich gegen ein Wort.
Korrekt.  ;)
Das ist der gesamte Block. Wer nur Sprachausgabe machen möchte, braucht den nicht.
Aber zur Anzeige in einem Frontend muss ja die Zahl wider in Text umgewandelt werden.
Es soll ja wie gesagt die original QLOCKTWO wiedergegeben werden. OK, die hat auch noch Pünktchen in den Ecken für die Minuten...  ;)
## Umwandlung der Stunde von einer Zahl in Text
if ($Stunde == 1) { $Stunde = "eins" } if ($Stunde == 2) { $Stunde = "zwei" }
if ($Stunde == 3) { $Stunde = "drei" } if ($Stunde == 4) { $Stunde = "vier" }
if ($Stunde == 5) { $Stunde = "fünf" } if ($Stunde == 6) { $Stunde = "sechs" }
if ($Stunde == 7) { $Stunde = "sieben" } if ($Stunde == 8) { $Stunde = "acht" }
if ($Stunde == 9) { $Stunde = "neun" } if ($Stunde == 10) { $Stunde = "zehn" }
if ($Stunde == 11) { $Stunde = "elf" } if ($Stunde == 12) { $Stunde = "zwölf" }

Das erzeugt die erwähnten PERL WARNINGS:
2018.03.15 20:01:12 1: PERL WARNING: Argument "acht" isn't numeric in numeric eq (==) at ./FHEM/99_myUtils.pm line 44.
VG Sebastian

Benni

Zitat von: binford6000 am 15 März 2018, 20:50:09
## Umwandlung der Stunde von einer Zahl in Text
if ($Stunde == 1) { $Stunde = "eins" } if ($Stunde == 2) { $Stunde = "zwei" }
if ($Stunde == 3) { $Stunde = "drei" } if ($Stunde == 4) { $Stunde = "vier" }
if ($Stunde == 5) { $Stunde = "fünf" } if ($Stunde == 6) { $Stunde = "sechs" }
if ($Stunde == 7) { $Stunde = "sieben" } if ($Stunde == 8) { $Stunde = "acht" }
if ($Stunde == 9) { $Stunde = "neun" } if ($Stunde == 10) { $Stunde = "zehn" }
if ($Stunde == 11) { $Stunde = "elf" } if ($Stunde == 12) { $Stunde = "zwölf" }

Das erzeugt die erwähnten PERL WARNINGS:
2018.03.15 20:01:12 1: PERL WARNING: Argument "acht" isn't numeric in numeric eq (==) at ./FHEM/99_myUtils.pm line 44.

Du solltest evtl. in Betracht ziehen, für das Ergebnis eine andere Variable zu nehmen, als für die zu überprüfenden (Eingangs-)Daten.

wenn $Stunde==8 ist, dann wird $Stunde auf "acht" gesetzt. In der nächsten Zeile wird dann überprüft, ob  $Stunde == 9 ist, das führt dann zu einem Fehler, weil $Stunde ja inzwischen mit "acht" belegt wurde und es sich somit nicht mehr um einen numerischen Vergleich handelt.

verständlich?

binford6000

Zitatverständlich?
Absolut. Ist ja auch eine sprechende Warnung.  ;)

Was ich aber nicht verstehe ist, dass die PERL WARNING nur EINMAL pro aktuell gültiger Stunde kommt und nicht bei jedem Aufruf der sub. ???

Bei der aktuellen Uhrzeit wird also um 21:13 Uhr (Ost-Version) und um 21:23 Uhr (West-Version) die PERL WARNING wieder (einmal) ins Log geschrieben...
VG Sebastian

Benni

Ich würde das über eine Array machen:


my @hourNames=('eins','zwei','drei','vier','fünf','sechs','sieben','acht','neun','zehn','elf','zwölf');

$Stunde=$hourNames[$Stunde-1];


Dann gibt's gar keinen Vergleich.

binford6000

Und so klappts dann auch mit der zwölf:
my @hourNames=('null','eins','zwei','drei','vier','fünf','sechs','sieben','acht','neun','zehn','elf','zwölf');
$Stunde=$hourNames[$Stunde];

Danke Benni  :)

VG Sebastian

the ratman

könnte man das noob-gerecht aufbereiten?

wäre echt super.
→do↑p!dnʇs↓shit←

binford6000

Zitatkönnte man das noob-gerecht aufbereiten?
wäre echt super.
Habs im ersten Beitrag angepasst  ;)
VG Sebastian

Benni

Zitat von: binford6000 am 15 März 2018, 21:29:22
Und so klappts dann auch mit der zwölf:

Deine Anpassung war absolut unnötig!
Es hat auch davor schon mit der zwölf funktioniert (ich hatte das getestet!)

Es sei denn du brauchst auch die 'null', das war aber im gegebenen Code-Segment nicht ersichtlich.