• Eigenständig gehostete oder lokal installierte Instanzen sind komplexer in der Einrichtung und Fehlerbehebung und erfordern daher kostenpflichtigen technischen Support. Kostenlosen Support erhalten Sie mit 3CX StartUP oder einer gehosteten 3CX-Installation mit einen unterstützten SIP-Trunk-Anbieter.

CFA: Namen von Feiertagen auslesen

patrickb

Gold Partner
Advanced Certified
Mitglied seit
6. Februar 2021
Beiträge
756
Gibt es eine Möglichkeit den Namen eines Feiertags auszulesen?

Ziel ist, dass ich im CallFlow einen Condition Baustein nutzen kann um dann anhand des Feiertag-Namens bestimmte Ansagen ausspielen zu können. Heißt der Script müsste am entsprechenden Datum auslesen, sofern dieses Datum ein in den Anlageneinstellungen definierter Feiertag ist, wie dieser im "Freifeld" betitelt wurde.

Hat da jemand eine Idee wie ich an diesen Parameter rankomme bzw. diesen abfragen kann?
 
Zuletzt bearbeitet:
  • Like
Reaktionen: fxbastler
Mit C# in einer CFA bekommt man bei Abfrage von PhoneSystem.Root.GetTenant().GetOfficeHolidays(); ein array von Feiertagseinträgen ( OfficeHoliday[] ) je mit u.a. den Parametern Name, Day, Month, Year, TimeOfStartDate, DayEnd, MonthEnd, YearEnd, TimeOfEndDate, IsRecurrent und ID. Durchsuche das und du wirst evtl. fündig.

Ich würde die Feiertage nicht je manuell in die 3CX eintragen sondern ausrechnen lassen, s.o.. Die in der 3CX dort manuell eingetragenen Werte wären zusätzlich und individuell, Betriebsferien z.B..

Suchstichwort: Call Flow Designer App Schnipsel
 
  • Like
Reaktionen: patrickb
Mit C# in einer CFA bekommt man bei Abfrage von PhoneSystem.Root.GetTenant().GetOfficeHolidays(); ein array von Feiertagseinträgen ( OfficeHoliday[] ) je mit u.a. den Parametern Name, Day, Month, Year, TimeOfStartDate, DayEnd, MonthEnd, YearEnd, TimeOfEndDate, IsRecurrent und ID.
Ich habe HolidayPrompt (der Name der abzuspielenden Audio Datei) vergessen anzugeben.
 
  • Like
Reaktionen: patrickb
Hi, irgendwie komme ich damit nicht zurande. Er schmeißt mir immer nur den Array "TCX.Configuration.Interop.Wholiday[]" zurück und wenn ich den entsprechend auslesen will, sagt er mir, dass "Der Zugriff auf "Wholiday" ist aufgrund des Schutzgrads nicht möglich." ist.

Auch das ansprechen der Array-Inhalte über ihren Index läuft nicht, kommt einfach nur das "OfficeHoliday[...]" ist "Typ" und im angegebenen Kontext nicht gültig.

Ziel am Ende ist das ich quasi über DateTime.Now.ToString("yyyy-MM-dd"); den aktuellen Tag auslesen, dann mit der 3CX internen Feiertagsliste abgleichen lasse und sofern das auf "true" läuft - der Tag also ein Feiertag ist - den Namen des Feiertags zurückgegeben bekomme um den dann über einen Condition Baustein zu prüfen und entsprechend dann den CFD weiterlaufen zu lassen.

Soll halt alles ohne externe Connections laufen. Über ne externe MySQL DB Connection via CFA habe ich das schon am laufen. Soll aber halt nicht die Endlösung sein, da die Scripte im Falle eines Serverausfalls am DB Server dann ins Nirvana verlaufen würden - bzw. nur auf die Fallback Variante.
 
Zuletzt bearbeitet:
Gibts hier noch Ideen? Habe nochmal weiter rumprobiert, komme aber leider weiterhin zu keinem Ergebnis mit der 3CX internen Feiertagsliste.
 
Habe nochmal weiter rumprobiert, komme aber leider weiterhin zu keinem Ergebnis mit der 3CX internen Feiertagsliste.
Mit Powershell geht das völlig problemlos. Wenn das in C# Fehler auswirft, dann hat das etwas mit den strikteren Datenstrukturen und -typen zu tun. Da muss ich mal nachschauen und das gar nachbauen. Grad wenig Zeit dafür.
 
  • Like
Reaktionen: patrickb
Sooo wenn man mal die Ruhe und Zeit hat dann hat man auch Ideen wie man es noch anders Lösen kann - sogar noch cooler und flexibler als mit den Onboard Feiertagen und ohne Zugriff auf eine externe DB.

Ich nutze einfach die Global Propertys und lege mir dort zwei Strings an. Einen mit den Daten, einen mit den Namen der Feiertage. Dann lasse ich via C# Element beide Strings als Array einlesen und prüfe im Anschluss im ersten Array mit den Daten, ob das heutige Datum im Array steht. Wenn ja, speichere ich mir die Position im Array weg und frage den selben Index im zweiten Array an. Als Rückgabe gibt's den Namen des Feiertages, den ich dann via Condition im weiteren Verlauf der CFA überprüfen kann.

Die Strings für die Global Propertys kann man dann einmal pro Jahr selber neu erstellen oder (so der Plan) ich bastel mir ein weiteres Script, das mir die Feiertage (wie du oben beschrieben hast) ausrechnet und als String am 31.12. in die Global Propertys schreibt.

PS: Trotzdem würde mich der Zugriff auf die Daten der internen 3CX Feiertagsverwaltung interessieren. :)
 
Ich habe das eben probiert. Es ist genau so wie ich es schon geschrieben hatte.
Hi, irgendwie komme ich damit nicht zurande. Er schmeißt mir immer nur den Array "TCX.Configuration.Interop.Wholiday[]" zurück und wenn ich den entsprechend auslesen will, sagt er mir, dass "Der Zugriff auf "Wholiday" ist aufgrund des Schutzgrads nicht möglich." ist.
Wenn du einfach nur return PhoneSystem.Root.GetTenant().GetOfficeHolidays(); in dem C# Schnipsel stehen hast, dann passiert genau das was du beschreibst.
Ich hatte jedoch geschrieben:
Mit C# in einer CFA bekommt man bei Abfrage von PhoneSystem.Root.GetTenant().GetOfficeHolidays(); ein array
Das Array kann man mit normalen CFD Blöcken nicht auflösen. In dem Fall kommt vmtl. gar ein Zeiger zurück. Das nutzt dir für die weitere Verarbeitung mittels CFD Blöcken recht wenig, siehe deine Fehlermeldung oben. Das Array muss im C# Schnipsel aufgelöst werden.

An einzelne Werte kommt man dann z.B. mittels
PhoneSystem.Root.GetTenant().GetOfficeHolidays()[0].Name; .

Damit du weisst, was insgesamt dabei herauskommen kann, hier ein Beispiel eines C# Schnipsel zur Rückgabe aller Feiertagseinträge einer 3CX als einzelnen String, welcher ein semikolon- und kommasepariertes zweidimensionales Array mit den Daten hält:
C#:
string ret="";  // der Rueckgabewert
string tra=";"; // der Trennstring zwischen den einzelnen GetOfficeHolidays()
string trb=","; // der Trennstring zwischen den einzelnen Elementen von GetOfficeHolidays() / Wholiday struct
foreach(var b in PhoneSystem.Root.GetTenant().GetOfficeHolidays()) {
    if( ret.Count() > 0 ) {
        ret = ret + tra;
    }
    ret = ret + b.ID.ToString() + trb + b.Name + trb + b.Day.ToString() + trb + b.Month.ToString() + trb + b.Year.ToString() + trb + b.DayEnd.ToString() + trb + b.MonthEnd.ToString() + trb + b.YearEnd.ToString() + trb + b.TimeOfStartDate.ToString() + trb + b.TimeOfEndDate.ToString() + trb + b.IsRecurrent.ToString() + trb + b.HolidayPrompt;
}
return ret;
Das sieht recht umständlich aus, aber die struct TCX.Configuration.Interop.Wholiday lässt sich schlecht deserialisieren. Dann eben so wie im Beispiel.

Halten wir fest: damit lassen sich globale Feiertagseinträge einer 3CX abfragen. Alle die man individuell einträgt.

Das kann man so machen, muss man nicht. Jetzt willst du gar noch weitere, manuell zu pflegende globale Parameter einfügen. Damit wird es nicht einfacher.

Wenn du, so wie du vorhin hier geschrieben hast, ohnehin wirklich nur offizielle Feiertage in die Parameter bzw. in die 3CX einträgst (wie auch immer, vmtl. gar manuell), dann kannst du dir das doch (wie ganz zu Anfang dieses Thread geschrieben) ausrechnen lassen. Das funktioniert dann jedes Jahr, alle Jahre, ewig - so lange wie sich im entspr. Bundesland dahingehend nichts ändert. Berechne das gleitende Osterdatum, berechne evtl. noch das gleitende Datum vom Buß- und Bettag (dafür braucht man wiederum die Wochentagsberechnung) und der Rest ergibt sich. Das ist nicht kompliziert.

Suchstichwort: CFD Call Flow Designer App Schnipsel
 
Zuletzt bearbeitet:
  • Like
Reaktionen: patrickb und mbehrens
Jetzt habe ich 3 Varianten ^^ eine mit DB Anbindung. Eine mit den Daten aus der 3CX Feiertagsübersicht und eine mit nem flexiblen String den ich als Array lade. Nice!

Je nach Anwendungsfall matcht dann die Eine mehr, die Andere weniger. Danke auf jeden Fall!
 
Jetzt habe ich 3 Varianten ^^ eine mit DB Anbindung
Wie kommen die Daten da rein? Automatisch? Alles andere ist in deinem Fall nicht sinnvoll: das bedeutet immer manuellen Aufwand, Kontrolle und Fehler.
 
Wie kommen die Daten da rein? Automatisch? Alles andere ist in deinem Fall nicht sinnvoll: das bedeutet immer manuellen Aufwand, Kontrolle und Fehler.
1 x im Jahr. Die DB Variante ist aber von den Dreien so oder so die, die am fehleranfälligsten ist, da sie ja eine externe Verbindung zu einem anderen Server benötigt. Das Ding ist, dass das Konstrukt eine gewisse Individualität benötigt und daher eine manuelle Anpassung und Kontrolle sogar noch Vorteilhafter ist - in diesem Fall. (In den anderen baue ich es mit der automatischen Berechnung)

Aktuell nutze ich auf jeden Fall die Variante mit den 2 Strings die in zwei Arrays geladen werden. Zum erstellen der Strings habe ich mir jetzt ne Exceltabelle gebaut, die mir auf Basis einer Tabelle den korrekten String generiert, den ich dann nur noch in die Global Propertys einfügen muss. Zum Kopieren habe ich einfach einen Button mit ins Sheet gebaut, den klickst du an, fügst den kopierten String ein und - fertig. :)
 
Sagen wir mal so: es ist einfacher das nur einmal einzugeben und sich das ausrechnen zu lassen.

Eine möglicher globaler 3CX Parameter HOLIDAYS_DE_SN hätte dann evtl. folgenden Inhalt:
Code:
1.1., Neujahr; 1.4., April April, aprilscherz-faxverbunden.wav, 888; e-2, Karfreitag; e,  Ostersonntag; e+1, Ostermontag; 1.5., Tag der Arbeit; e+39, Christi Himmelfahrt; e+49, Pfingstsonntag; e+50, Pfingstmontag; 3.10., Tag der deutschen Einheit; 31.10., Reformationstag; b, Buß- und Bettag; 25.12., Erster Weihnachtsfeiertag; 26.12., Zweiter Weihnachtsfeiertag

Das ist so wie wir es gern mal machen: Parameterübergabe als String in einem quasi zweidimensionalen Array (getrennt durch ; und ,).

Die CFA bekommt den Parameter dynamisch, liest den Parameter aus, errechnet sich den Rest (gleitende Feiertage) und tut was da steht. Das ist ausbaufähig. Wenn es wirklich interessiert was dahintersteht, dann klick ich mal ein Beispiel zusammen. Ich habe die Routinen generell schon da.

Alternativ geht auch der Weg, sich das zyklisch per PS auszurechnen und in die 3CX Feiertage einzutragen. Aber das ist wieder außerhalb der 3CX, nicht im Backup drin und unflexibel. Dafür wird in der 3CX dann alles mit Feiertag Bordmitteln geregelt.
 
Zuletzt bearbeitet:
  • Like
Reaktionen: patrickb
Sagen wir mal so: es ist einfacher das nur einmal einzugeben und sich das ausrechnen zu lassen.

Eine möglicher globaler 3CX Parameter HOLIDAYS_DE_SN hätte dann evtl. folgenden Inhalt:
Code:
1.1., Neujahr; 1.4., April April, aprilscherz-faxverbunden.wav, 888; e-2, Karfreitag; e,  Ostersonntag; e+1, Ostermontag; 1.5., Tag der Arbeit; e+39, Christi Himmelfahrt; e+49, Pfingstsonntag; e+50, Pfingstmontag; 3.10., Tag der deutschen Einheit; 31.10., Reformationstag; b, Buß- und Bettag; 25.12., Erster Weihnachtsfeiertag; 26.12., Zweiter Weihnachtsfeiertag

Das ist so wie wir es gern mal machen: Parameterübergabe als String in einem quasi zweidimensionalen Array (getrennt durch ; und ,).

Die CFA bekommt den Parameter dynamisch, liest den Parameter aus, errechnet sich den Rest (gleitende Feiertage) und tut was da steht. Das ist ausbaufähig. Wenn es wirklich interessiert was dahintersteht, dann klick ich mal ein Beispiel zusammen. Ich habe die Routinen generell schon da.

Alternativ geht auch der Weg, sich das zyklisch per PS auszurechnen und in die 3CX Feiertage einzutragen. Aber das ist wieder außerhalb der 3CX, nicht im Backup drin und unflexibel. Dafür wird in der 3CX dann alles mit Feiertag Bordmitteln geregelt.
Ja so in etwa habe ich das auch. Halt aktuell nur in zwei Arrays. Wenn du Zeit hast bin ich durchaus interessiert.

Und auf Basis des Strings neu berechnen lassen ist auch ne Idee :)
 
So, hier sind die Perlen:

C#:
int d = (int)DateTime.Now.Day;
int m = (int)DateTime.Now.Month;
int y = (int)DateTime.Now.Year;

// leap year, = 1 if leap yeap, 0 if not; needs y
int ly = (4 - y % 4) / 4 - (100 - y % 100) / 100 + (400 - y % 400) / 400;

// day of week; needs d, m, y; 1=mon ... 7=sun
int dow = ((d + (26 * ((m + 9) % 12 + 1) - 2) / 10 + (y - ((22 - m) / 10 - 1)) % 100 + ((y - ((22 - m) / 10 - 1)) % 100 / 4) + ((y - ((22 - m) / 10 - 1)) / 400) - 2 * ((y - ((22 - m) / 10 - 1)) / 100) - 1) % 7 + 7) % 7 + 1;

// day of year; needs d, m, y; starts with 1  i.e. if 01.01.xxxx then d=1 and m=1 and doy = 1
int doy = ((m - 1) * 1529 - 100 * ((m + 7) / 10) + 25) / 50 + ((4 - y % 4) / 4 - (100 - y % 100) / 100 + (400 - y % 400) / 400) * ((m + 7) / 10) + d;

// easter day of year; returns day of year for easter sunday; respects leap year
int easterdoy = 59 + (21 + ((19 * (y % 19) + (15 + (3 * (y / 100) + 3) / 4 - (8 * (y / 100) + 13) / 25)) % 30) - ((((19 * (y % 19) + (15 + (3 * (y / 100) + 3) / 4 - (8 * (y / 100) + 13) / 25)) % 30) + (y % 19) / 11) / 29)) + (7 - ((21 + ((19 * (y % 19) + (15 + (3 * (y / 100) + 3) / 4 - (8 * (y / 100) + 13) / 25)) % 30) - ((((19 * (y % 19) + (15 + (3 * (y / 100) + 3) / 4 - (8 * (y / 100) + 13) / 25)) % 30) + (y % 19) / 11) / 29)) - (7 - (y + y / 4 + (2 - (3 * (y / 100) + 3) / 4)) % 7)) % 7) + ((4 - y % 4) / 4 - (100 - y % 100) / 100 + (400 - y % 400) / 400);

// prayer - buss und bettag; returns day of year, respects leap year, needs year
int bbdoy = 326 - (4 + ((46 + y % 100 + y % 100 / 4 + y / 400 - 2 * (y / 100) - 1) % 7 + 7) % 7) % 7 + (4 - y % 4) / 4 - (100 - y % 100) / 100 + (400 - y % 400) / 400;

// calc month from doy, needs doy and ly
int doy2m = (((doy - ly) * 50 + 74) / 1529) * (1 - ((366 - doy) / 335)) + 1;

// calc date from doy; respects leap year; needs doy, ly and doy2m; return int in form of <dd><mm>, i.e. 02.04. = 204, 31.12. = 3112
int doy2date = (doy - (12 - ((doy2m + 10) % 12)) / 12 * 31  - (1 - (12 - doy2m)         / 10) * ly - (12 - ((doy2m + 9) % 12)) / 12 * 59
                    - (12 - ((doy2m + 8) % 12))  / 12 * 90  - (12 - ((doy2m + 7) % 12)) / 12 * 120 - (12 - ((doy2m + 6) % 12)) / 12 * 151
                    - (12 - ((doy2m + 5) % 12))  / 12 * 181 - (12 - ((doy2m + 4) % 12)) / 12 * 212 - (12 - ((doy2m + 3) % 12)) / 12 * 243
                    - (12 - ((doy2m + 2) % 12))  / 12 * 273 - (12 - ((doy2m + 1) % 12)) / 12 * 304 - (12 - (doy2m % 12)) / 12 * 334) * 100 + doy2m;

string retval = "";
foreach( string holi in PhoneSystem.Root.GetParameterByName(holidayparamname).Value.Split(";"))
{
    string dholi = holi.Split(",")[0].Trim();
    string dholistr = holi.Substring(holi.IndexOf(",")+1).Trim();

    if (dholi.Length > 0 && dholi[0] == 'e')
    {
        if (dholi.Length == 1 && easterdoy == doy)
        {
            retval = dholistr;
        }

        else if (dholi.Length > 2 && dholi[1].Equals('+'))
        {
            int dholiadd = int.Parse(dholi[2..]);
            if (( easterdoy + dholiadd) == doy)
            {
                retval = dholistr;
            }
        }
        else if (dholi.Length > 2 && dholi[1].Equals('-'))
        {
            int dholisub = int.Parse(dholi[2..]);
            if ((easterdoy - dholisub) == doy)
            {
                retval = dholistr;
            }
        }
    }
    else if (dholi.Length > 0 && dholi[0] == 'b')
    {
            if (bbdoy == doy)
            {
                retval = dholistr;
            }
    }
    else if (dholi.Length > 0 )
    {
        int hd = int.Parse(dholi.Split(".")[0].Replace(" ", ""));
        int hm=0;
        if (dholi.Split(".").Length > 1)
        {
            hm = int.Parse(dholi.Split(".")[1].Replace(" ", ""));
        }
        else if (hd > 100)
        {
            hm = hd % 100;
            hd = hd / 100;
        }
        int hdoy = ((hm - 1) * 1529 - 100 * ((hm + 7) / 10) + 25) / 50 + ((4 - y % 4) / 4 - (100 - y % 100) / 100 + (400 - y % 400) / 400) * ((hm + 7) / 10) + hd;
        if ( hm > 0 && hd > 0 && hdoy == doy)
        {
            retval = dholistr;
        }
    }
}

// write to 3cxcallflow.log:
// File.AppendAllText(System.IO.Directory.GetCurrentDirectory()+"/Instance1/Data/Logs/3CXCallFlow.log", "\n##### CFA C# Log: |" + PhoneSystem.Root.GetParameterByName(holidayparamname).Value + "|\n");

return retval;

Der Routine wird ein Parameter mit Namen holidayparamname vom Typ String mitgegeben (siehe Beispiel unten). Dieser hält den Namen des globalen Parameter der 3CX in der letztendlich die Daten zur Auswertung stehen. Damit wird das C# Schnipsel variabel nutzbar. Die Auswertung erfolgt mit einfachen Konstrukten (einfache Zeichenkettenoperationen und Rechnungen mit Ganzzahlen), ist also auch auf andere Programmiersprachen übertragbar.

Fazit: wird dieses C# Schnipsel mit den richtigen Daten gefüttert und wird das Ergebnis richtig ausgewertet (siehe Beispiel unten), dann funktioniert das ewig - bis zur nächsten Kalender- oder Feiertagreform.

In dem variablen 3CX Parameter stehen die Feiertagdaten in folgender möglicher Form (aktuell 2 bis 4 mögliche Parameter, bei Bedarf ausbaufähig):
<Datum>,<Bezeichnung>[,Name einer Audio Datei][,Nummer zur Weiterleitung]

Die einzelnen Wert eines Eintrages werden mit einem Komma , separiert. Mögliche folgende Feiertag Datensätze werden mit einem Semikolon ; separiert (siehe Beispiel für HOLIDAYS_DE_SN unten). Das heisst: in den sonstigen Nutzdaten sollte kein Komma oder Semikolon verwendet werden. Das C# Schnipsel wertet pro Feiertag Datensatz nur den ersten Parameter (das angegebene Datum) aus, nichts anderes. Wenn das Datum mit dem aktuellen Tag übereinstimmt (es somit ein Feiertag ist), dann werden alle anderen Parameter des Feiertag Datensatzes zurückgegeben - egal welche und wie viele das sind. Die Komma und Angaben zu Name einer Audio Datei und Nummer zur Weiterleitugn kann bei Bedarf entfallen. Es ist dann die Aufgabe der ander CFD Codeblöcke diese auszuwerten, siehe Beispiel unten. Das Datum kann ohne Punkte angegeben werden (z.b. 0104 für den 1.4.), die Jahresangabe wird ignoriert. Wenn das Datum mit einem e (für easter, Ostern) beginnt, dann ist das ein gleitender Feiertag und das richtige Datum des jew. Jahres (evtl. ab- oder zuzüglich weiterer Tage) wird berechnet. Wenn das Datum mit einem b (für Buß- und Bettag) beginnt, dann ist das auch ein gleitender Feiertag und das richtige Datum des jew. Jahres wird berechnet. Stimmt das aktuelle Datum mit einer der (teils errechneten) Datumangaben im 3CX Parameter überein, so ist es an diesem Tag ein Feiertag und die restlichen Felddaten des Feiertag Eintrages (Bezeichnung, Name einer Audio Datei, Nummer.

Für den Freistaat Sachsen gibt es einen globalen 3CX Parameter HOLIDAYS_DE_SN mit dem Inhalt (in diesem Fall hier ohne jegliche Angaben von Audio Dateien oder Nummern für spezielle Weiterleitungen):
Code:
1.1., Neujahr; e-2, Karfreitag; e,  Ostersonntag; e+1, Ostermontag; 1.5., Tag der Arbeit; e+39, Christi Himmelfahrt; e+49, Pfingstsonntag; e+50, Pfingstmontag; 3.10., Tag der deutschen Einheit; 31.10., Reformationstag; b, Buß- und Bettag; 25.12., Erster Weihnachtsfeiertag; 26.12., Zweiter Weihnachtsfeiertag

Das komplette Funktionsbeispiel für den 3CX CFD habe ich vorhin extra noch für das Forum hier gebaut. Der hat noch einige wenige Bausteine mehr:
  1. es wird zuerst der globale 3CX Parameter HOLIDAYS_DE_SN als Vorgabe für dieses Beispiel gesetzt (auf das aktuelle Datum, zusammen mit ein klein wenig anderen Daten zur Illustration der Funktion), die C# Feiertagroutine wird somit immer ein Ergebnis liefern
  2. die oben besprochene Feiertagroutine als C# Code Schnipsel
  3. eine Auswertung der zurückgegebenen Parameter, hier wird bei Bedarf eine Audio Datei (die in der CFA / der 3CX vorhanden sein muss) abgespielt, der Anruf es wird auf eine optional angegebene Nummer weitergeleitet oder sonstiges

1682941283358.jpeg

Es können in diesem Beispiel - je nach Feiertag Eintrag im 3CX Parameter - in der Zeichenkette der Rückgabe mehrere Parameter (hier bis zu drei, durch Komma getrennt, ist ausbaufähig) zurückgegeben werden: Bezeichnung, Name einer Audio Datei, Nummer für eine Weiterleitung. Die Auswertung des vom C# Schnipsel übergebenen Rückgabewertes im CFD Block Condition erfolgt immer von links nach rechts, first match wins:
  1. ist die Länge des Rückgabewertes > 0 und es werden drei Parameter zurückgegeben (ist die Anzahl an Kommas , gleich 2: mit REPLACE_REG_EXP werden alle Zeichen außer den Kommas aus dem Rückgabewert entfernt und diese werden danach mit LEN gezählt), dann hole aus dem Rückgabewert den zweiten Parameter (den Namen der Audio Datei, es wird mittels zweier REPLACE_REG_EXP der erste und der letzte Parameter entfernt) und spiele diese ab, danach hole aus dem Rückgabewert den dritten Parameter (die Nummer der Weiterleitung, es wird mittels REPLACE_REG_EXP die ersten beiden Parameter entfernt) und leite den Anruf dort hin weiter
  2. ist die Länge des Rückgabewertes > 0 und es werden zwei Parameter zurückgegeben (ist die Anzahl an Kommas , gleich 1: mit REPLACE_REG_EXP werden alle Zeichen außer den Kommas aus dem Rückgabewert entfernt und diese werden danach mit LEN gezählt), dann hole aus dem Rückgabewert den zweiten Parameter (den Namen der Audio Datei, es wird mittels zweier REPLACE_REG_EXP der erste und der letzte Parameter entfernt) und spiele diese ab, danach leite den Anruf an eine fest vorgegebene Nummer / NSt. weiter
  3. ist die Länge des Rückgabewertes > 0, so wird nur ein Parameter zurückgegeben (die Bezeichnung des Feiertages, die Prüfung auf zwei oder ein Komma ist ja in den beiden Zweigen zuvor erfolgt), dann leite den Anruf an eine fest vorgegebene Nummer / NSt. weiter
  4. ist die Länge des Rückgabewertes == 0, dann ist heute kein Feiertag, dann leite den Anruf an eine fest vorgegebene Nummer / NSt. weiter

Die Formel in dow (Wochentagberechnung) und die in easterdoy (Osterdatumberechnung) habe ich mal irgendwann schamlos aus einem meiner früheren Tafelwerke kopiert und stark angepasst. Das sind vmtl. die Formeln von Zeller und von Gauss (nach dem Gregorianischem / Westkirchen Kalender). Alles andere (ly, doy, bbdoy, doy2m und doy2date) habe ich mir früher mal ausgedacht. Das geht sicher eleganter (und auch kürzer, insbes. in C#), aber das sind generische und sehr schlichte Formeln, einfache Funktionen, keine Routinen: kein if-then Sprünge, keine Schleifen, keine Tabellen, keine oder nur wenige Variablen in Abhängigkeit von anderen Berechnungen vorab, es werden nur Grundrechenarten (+, -, *, /, %) verwendet und das alles sind durchgängig Ganzzahlberechnungen (keine FPU, keine Rundungsfehler). Damit funktionieren diese Formeln auf allen Plattformen und in allen Programmiersprachen die mind. 16 bit Integer verarbeiten können (für die 8bitter ist eine kleine Anpassung bei der Division nötig): Assembler, Forth, C, C++, Perl, Php, Powershell u.v.a.m - so eben auch in C#. Die Formeln habe ich schon Jahrzehnte, da wird nichts mehr verändert. Die werden nur bei Bedarf in eine andere Programmiersprache kopiert und da läuft es wieder. Die kann sich jeder kopieren so wie er es braucht. Vielleicht hat oder kennt ja einer elegantere generische Lösungen dafür, dann kann er die ja hier drunter schreiben. Ich habe nie danach gesucht.

Suchstichwort: CFD Call Flow Designer App Schnipsel

p.s.: Das Schreiben des Textes hier hat einiges länger gedauert als das zusammenklicken des CFD Beispiels.
 

Anhänge

  • Feiertagumleitung.zip
    14 KB · Aufrufe: 24
Zuletzt bearbeitet:
Respekt, eichtig gut! Auch wie viel Mühe du dir damit gemacht hast es für uns alle zu dokumentieren. Ich liebe es wenn Menschen so eine Leidenschaft für eine Sache haben! Danke!
 
  • Like
Reaktionen: bitn2
Gibt es eine Möglichkeit den Namen eines Feiertags auszulesen?
falls das noch jemand fehlt:
C#:
// returns the name of the holiday, or an empty string if it is not a holiday time
foreach( OfficeHoliday holi in PhoneSystem.Root.GetTenant().GetOfficeHolidays()) {
    int holiys = (holi.IsRecurrent) ? DateTime.UtcNow.Year : holi.Year;
    int holiye = (holi.IsRecurrent) ? DateTime.UtcNow.Year : holi.YearEnd;
    long lholistartut = (new DateTimeOffset(new DateTime( holiys, holi.Month, holi.Day, holi.TimeOfStartDate.Hours, holi.TimeOfStartDate.Minutes, 0))).ToUnixTimeSeconds();
    long lholiendut = (new DateTimeOffset(new DateTime( holiye, holi.MonthEnd, holi.DayEnd, holi.TimeOfEndDate.Hours, holi.TimeOfEndDate.Minutes, 0))).ToUnixTimeSeconds() + 60;
    long lactut = ((DateTimeOffset)DateTime.UtcNow).ToUnixTimeSeconds();
    if( ( lholistartut <= lactut ) && ( lactut < lholiendut ) ) {
        return holi.Name;  // also possible: return holi.Name + "|" + holi.HolidayPrompt;
    }
} 
return "";

Ich hoffe das passt mit der Zeitzone anderswo, sowieso und überhaupt. Bei mir hier schon.
 
Zuletzt bearbeitet:
  • Like
Reaktionen: patrickb

Zurzeit aktive Besucher

Statistik des Forums

Themen
21.356
Beiträge
107.398
Mitglieder
70.512
Neuestes Mitglied
maxcolo
Holen Sie sich 3CX - völlig kostenlos!

Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX register cta
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.