RaketenLocalisator: PHP: strftime ist DEPRECATED, Lösungsversuch?

Ich habe gerade festgestellt, dass strftime() in PHP 8.1 als DEPRECATED angemeckert wird und in PHP 9.0 entfallen soll.

1. Frage:

Hat/Kennt jemand eine bessere (PHP-Native) Lösung als ich für das Problem?

Mein Ansatz:

Da ich strftime nutze um ein Datum mit Angabe des Wochentages bzw. Monats (also %a (Wochentagskürzel), %A (Wochentagsname), %b (Monatskürzel), %B (Monatsname) ) in der eingestellten Sprache des Benutzers zu liefern habe ich mich mal rangesetzt und einen "importer" geschrieben, der bei installiertem Debian-Paket locales-all die Wochentagsnamen und Monatsnamen für alle möglichen Sprachen und Codierungen ausliest. Das Ergebnis sieht, auf deutsch und russisch beschränkt, sodann in JSON ausgegeben, wie folgt aus:

     "de_DE.utf8": {
        "Monday": "Montag",
        "Tuesday": "Dienstag",
        "Wednesday": "Mittwoch",
        "Thursday": "Donnerstag",
        "Friday": "Freitag",
        "Saturday": "Samstag",
        "Sunday": "Sonntag",
        "Mon": "Mo",
        "Tue": "Di",
        "Wed": "Mi",
        "Thu": "Do",
        "Fri": "Fr",
        "Sat": "Sa",
        "Sun": "So",
        "January": "Januar",
        "February": "Februar",
        "March": "M\u00e4rz",
        "April": "April",
        "May": "Mai",
        "June": "Juni",
        "July": "Juli",
        "August": "August",
        "September": "September",
        "October": "Oktober",
        "November": "November",
        "December": "Dezember",
        "Jan": "Jan",
        "Feb": "Feb",
        "Mar": "M\u00e4r",
        "Apr": "Apr",
        "Jun": "Jun",
        "Jul": "Jul",
        "Aug": "Aug",
        "Sep": "Sep",
        "Oct": "Okt",
        "Nov": "Nov",
        "Dec": "Dez"
    },
    "ce_RU": {
        "Monday": "\u041e\u0440\u0448\u043e\u0442\u0430\u043d \u0434\u0435",
        "Tuesday": "\u0428\u0438\u043d\u0430\u0440\u0438\u043d \u0434\u0435",
        "Wednesday": "\u041a\u0445\u0430\u0430\u0440\u0438\u043d \u0434\u0435",
        "Thursday": "\u0415\u0430\u0440\u0438\u043d \u0434\u0435",
        "Friday": "\u041f\u04c0\u0435\u0440\u0430\u0441\u043a\u0430\u043d \u0434\u0435",
        "Saturday": "\u0428\u043e\u0442 \u0434\u0435",
        "Sunday": "\u041a\u04c0\u0438\u0440\u0430\u043d\u0430\u043d \u0434\u0435",
        "Mon": "\u041e\u0440",
        "Tue": "\u0428\u0438",
        "Wed": "\u041a\u0445",
        "Thu": "\u0415\u0430",
        "Fri": "\u041f\u04c0",
        "Sat": "\u0428\u043e",
        "Sun": "\u041a\u04c0",
        "January": "\u042f\u043d\u0432\u0430\u0440\u044c",
        "February": "\u0424\u0435\u0432\u0440\u0430\u043b\u044c",
        "March": "\u041c\u0430\u0440\u0442",
        "April": "\u0410\u043f\u0440\u0435\u043b\u044c",
        "May": "\u043c\u0430\u0439",
        "June": "\u0418\u044e\u043d\u044c",
        "July": "\u0418\u044e\u043b\u044c",
        "August": "\u0410\u0432\u0433\u0443\u0441\u0442",
        "September": "\u0421\u0435\u043d\u0442\u044f\u0431\u0440\u044c",
        "October": "\u041e\u043a\u0442\u044f\u0431\u0440\u044c",
        "November": "\u041d\u043e\u044f\u0431\u0440\u044c",
        "December": "\u0414\u0435\u043a\u0430\u0431\u0440\u044c",
        "Jan": "\u044f\u043d\u0432",
        "Feb": "\u0444\u0435\u0432",
        "Mar": "\u043c\u0430\u0440",
        "Apr": "\u0430\u043f\u0440",
        "Jun": "\u0438\u044e\u043d",
        "Jul": "\u0438\u044e\u043b",
        "Aug": "\u0430\u0432\u0433",
        "Sep": "\u0441\u0435\u043d",
        "Oct": "\u043e\u043a\u0442",
        "Nov": "\u043d\u043e\u044f",
        "Dec": "\u0434\u0435\u043a"
    },

Nach dem Import könnte man mit echo $arr['de_DE.utf-8']['Monday'] also den 'Montag' erhalten. Das Zeug soll, so die Idee, in einem Objekt gekapselt werden.

Die Dateigröße beträgt mit serialice() ein knappes halbes Megabyte, mit json_encode($data, JSON_INVALID_UTF8_IGNORE | JSON_PRETTY_PRINT ) etwas mehr als ein halbes Megabyte. Das erscheint mir als „zu viel Holz um ein Täubchen zu braten“. (Die Idee, eine Datenbank zu nutzen fällt in eben die gleiche Kategorie, da z.B. sqlite3-libs nicht überall installiert sind.)

Die Datenmenge könnte man beschänken, in dem man die '@euro'-Varianten weglässt. (Natürlich auch das Pretty-Print) Die andere Idee wäre, ein Objekt zu schreiben und die Sprachen/Kodierungen in jeweils einer Datei abzulegen (statt alle in einer) und nur bei Bedarf zu importieren.

Fragen:

2.) Wie würdet ihr das exportieren?

3.) Welche Optionen für json_encode() muss ich doch gleich setzen, damit ich das Zeug auch in JS, PHP und Python3 einwandfrei einlesen kann?

  1. Hallo RaketenLocalisator,

    hab gerade nicht viel Zeit, was ist mit DateTime::format?

    Rolf

    --
    sumpsi - posui - obstruxi
    1. hab gerade nicht viel Zeit, was ist mit DateTime::format?

      Das will leider nicht „übersetzen“.

      <?php
      $loc = setlocale(LC_ALL, 'de_DE.UTF-8' );
      echo $loc;
      echo PHP_EOL;
      $date = new DateTime('2024-01-01');
      echo $date->format('l');
      echo PHP_EOL;
      echo strftime('%A', $date->getTimestamp() );
      echo PHP_EOL;
      
      de_DE.UTF-8
      Monday
      Montag
      
  2. Tach!

    Ich habe gerade festgestellt, dass strftime() in PHP 8.1 als DEPRECATED angemeckert wird und in PHP 9.0 entfallen soll.

    Hat/Kennt jemand eine bessere (PHP-Native) Lösung als ich für das Problem?

    Im Migration-Guide 8.0.x zu 8.1.x sind Alternativen gelistet.

    [...] "importer" geschrieben, der bei installiertem Debian-Paket locales-all die Wochentagsnamen und Monatsnamen für alle möglichen Sprachen und Codierungen ausliest.

    Wenn es etwas systemunabhängiges sein soll und die Intl-Extension nicht infrage kommt, kann man sich das CLDR-Projekt anschauen.

    dedlfix.

    1. und die Intl-Extension nicht infrage kommt,

      Sowas käme gern in Frage, wenn es denn dazu auch eine Dokumention gäbe, die mir erklärt, wie man z.B. den Wochentag zu einem Datum/Zeitpunkt ausgibt.

      Ich finde da nur Links, die mir sonstwas erklären.

      Bis hier her bin ich gekommen.

      <?php
      $fmt = datefmt_create(
          'de-DE',
          IntlDateFormatter::FULL,
          IntlDateFormatter::FULL,
          'Europe/Berlin',
          IntlDateFormatter::GREGORIAN,
          'WAS_ZUM_TEUFEL_MUSS_HIER_HIN'
      );
      echo 'Heute ist ' . datefmt_format($fmt, time() );
      

      Mein Problem ist die Stelle an der 'WAS_ZUM_TEUFEL_MUSS_HIER_HIN' steht.

      1. Hallo,

        Mein Problem ist die Stelle an der 'WAS_ZUM_TEUFEL_MUSS_HIER_HIN' steht.

        Die entsprechende Seite ist im Handbuch bei der Beschreibung des pattern-Parameters verlinkt.

        Gruß
        Tobias

        1. Ja. Hatte es gerade hier gefunden.

          https://unicode-org.github.io/icu/userguide/format_parse/datetime/

          Gott im Himmel!

          1. Mit den Tabellen aus https://unicode-org.github.io/icu/userguide/format_parse/datetime/ ergibt sich:

            <?php
            $fmt = datefmt_create(
                'de-DE',
                IntlDateFormatter::FULL,
                IntlDateFormatter::FULL,
                'Europe/Berlin',
                IntlDateFormatter::GREGORIAN,
                'cccc'
            );
            echo 'Heute ist ' . datefmt_format($fmt, time() ) . '.';
            
            Heute ist Samstag.
            

            Und trotzdem ist die Dokumentation einfach nur schlecht. Sowas sollte nicht auf Drittquellen verweisen in denen man dann auch noch weiter suchen muss.

            1. Hallo RaketenDokumentationsfinder,

              naja, sie greifen halt auf eine Library von ICU zurück. International Components for Unicode.

              Die ICU-Doku ist sehr umfangreich und die Lib ist nicht im Schlafzustand, deswegen ist es schon nachvollziehbar, dass sie sie nicht einfach abschreiben wollen. Vielleicht dürfen sie auch nicht, aus Copyright-Gründen.

              Aber schon komisch, dass JavaScript mit den Intl-Objekten offenbar ebenfalls die ICU-Lib nutzt, zumindest sind viele Parameter recht ähnlich, aber JavaScript keine freien Patterns zulässt. Zumindest dokumentiert Mozilla nicht, wie das gehen könnte.

              Rolf

              --
              sumpsi - posui - obstruxi
  3. Wer sowas auch braucht (weil er die intl-Funktionen nicht benutzen kann oder will, kann sich ja mal den Fortschritt - derzeit die generierten Daten - anschauen:

    https://code.fastix.org/Projekte/PHP%3Ainternationalisierte%20Zeitangaben%20ohne%20strftime%20oder%20Intl-Extension/

    Den ersten Ansatz habe ich verwerfen müssen, weil es bei den Strings hinsichtlich kurzer und langer Monatsnamen ein Problem mit dem „May“ gab, der nunmal in beiden Varianten englischen Varianten kurz ist.

    Wer damit „bauen“ will: Bei Verwendung der Dateien für „af_ZA.utf8“ (Das ist irgendwo in Südafrika gebräuchlich, ) liefern die importierten Arrays etwas wie

    $arr[0][7] und $arr[0][0] → "Son"
    $arr[1][7] und $arr[1][0] → "Sonndag".
    $arr[2][12] → "Des"
    $arr[3][12] → "Desember"
    
    1. Wer sowas auch braucht (weil er die intl-Funktionen nicht benutzen kann oder will, kann sich ja mal den Fortschritt - derzeit die generierten Daten - anschauen:

      https://code.fastix.org/Projekte/PHP%3Ainternationalisierte%20Zeitangaben%20ohne%20strftime%20oder%20Intl-Extension/

      Fertig. Die Klasse steht. Taste [F5] drücken.