Ankündigung

Einklappen
Keine Ankündigung bisher.

Zeitzonenvergleich DateTime

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Zeitzonenvergleich DateTime

    Ich möchte ermitteln ob ein DateTime-Objekt eine bestimmte Zeitzone hat. Dafür wollte ich zwei Objekte vom Typ DateTimeZone vergleichen.
    Laut Manual liefert der typeschwache Vergleich true wenn alle Eigenschaften gleich sind. Das folgende Beispiel sollte daher false liefern.
    Das Resultat ist aber true.

    PHP-Code:
    $tza = new DateTimeZone("America/New_York");
    $tzb = new DateTimeZone("Europe/Berlin");
    var_dump($tza == $tzb);  //true 
    Erstelle ich eigene Objekte, funktioniert ein Vergleich wie im Manual beschrieben:
    PHP-Code:
    class MyTimeZone{
      private 
    $timezone_type 3;
      private 
    $timezone;

      public function 
    __construct($tz ""){
        
    $this->timezone $tz;
      }
    }

    $tza = new MyTimeZone("America/New_York");
    $tzb = new MyTimeZone("Europe/Berlin");
    var_dump($tza == $tzb);  //false 
    Vermutlich wieder eine der vielen Eigenheiten wie sie auch bei DateTime zu finden sind.

    Bin jetzt am überlegen wie ich den Vergleich mache. Per getName() scheint mir nicht zuverlässig, per getOffset() auf den ersten Blick etwas umständlich.

    Gibt es bessere Ideen?


    PHP-Klassen auf github


  • #2
    DateTime ist ein Sonderfall. == liefert TRUE, wenn der Zeitpunkt identisch ist.

    Warum verwendest du nicht getTimezone(), wenn du die Zeitzone vergleichen möchtest.

    Kommentar


    • #3
      Das erste ist klar. Ich bin aber bereits beim Vergleich bei DateTimeZone, das von getTimeZone() geliefert wird !
      PHP-Klassen auf github

      Kommentar


      • #4
        Da es (in PHP) 3 Typen von Zeitzonen gibt (Offset (+01:00), politisch (CET), geographisch (Europe/Berlin)), wird das ziemlich schwierig werden.

        Kommentar


        • #5
          Bin jetzt am überlegen wie ich den Vergleich mache. Per getName() scheint mir nicht zuverlässig, per getOffset() auf den ersten Blick etwas umständlich.

          Gibt es bessere Ideen?
          Zur Not, serialize().
          PHP-Code:
          $tza = new DateTimeZone("America/New_York");
          $tzb = new DateTimeZone("Europe/Berlin");

          var_dump($tza == $tzb); // true
          var_dump(serialize($tza) == serialize($tzb)); // false 
          Doch nicht... Wenn man z.B. "europe/Berlin" eingibt wirds nicht korrigiert womit ich gerechnet hätte.
          PHP-Code:
          var_dump(mb_strtolower(serialize($tza)) === mb_strtolower(serialize($tzb))); 
          Relax, you're doing fine.
          RTFM | php.de Wissenssammlung | Datenbankindizes | Dateien in der DB?

          Kommentar


          • #6
            getName() & strtolower() ?

            Kommentar


            • #7
              Sowas hilft dir nicht?

              PHP-Code:
              $tzA = new DateTimeZone("America/New_York");
              $tzB = new DateTimeZone("Europe/Berlin");

              $dateA = new DateTime(''$tzA);
              $dateB = new DateTime(''$tzB);

              $tzA $dateA->getTimezone();
              $tzB $dateB->getTimezone();

              var_dump($tzA->getName());
              var_dump($tzB->getName());

              /*
              string(16) "America/New_York"
              string(13) "Europe/Berlin"
              */ 
              Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
              PHP.de Wissenssammlung | Kein Support per PN

              Kommentar


              • #8
                Noch etwas zum Hintergrund:
                Ich möchte im Rahmen eines Test's prüfen, ob ein DateTime-Objekt mit einer bestimmten Zeitzone auch so wie gewünscht erzeugt wurde. Beim einfachen Vergleich von DateTime-Objekten können diese ja auch mit unterschiedlichen Zeitzoneninformationen gleich sein.
                Beispiel:
                PHP-Code:
                $tza = new DateTimeZone("UTC");
                $tzb = new DateTimeZone("Europe/Berlin");

                $da = new DateTime('today 6:00',$tza);
                $db = new DateTime('today 8:00',$tzb);

                var_dump($da == $db);  //true 
                Variablen

                $tza: object(DateTimeZone)#2 (0) { }
                $tzb: object(DateTimeZone)#3 (0) { }
                $da: object(DateTime)#4 (3) { ["date"]=> string(19) "2019-07-11 06:00:00" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" }
                $db: object(DateTime)#5 (3) { ["date"]=> string(19) "2019-07-11 08:00:00" ["timezone_type"]=> int(3) ["timezone"]=> string(13) "Europe/Berlin" }

                getName() allein reicht mir nicht. VPh's Beitrag hat mich auf eine Idee gebracht:

                PHP-Code:
                $tza = new DateTimeZone("America/New_York");
                $tzb = new DateTimeZone("Europe/Berlin");
                $tzc = new DateTimeZone("America/New_York");

                var_dump($tza == $tzb); // true
                var_dump(json_encode($tza) == json_encode($tzb)); // false  
                var_dump(json_encode($tza) == json_encode($tzc)); // true 
                Funktioniert erstmal unter PHP 7.2.19. Per json_encode können auch DateTime-Objekte überprüft werden, ohne explizit die Zeitzone rausholen zu müssen.
                Muss mal schauen wie weit das noch bei den Alt-Versionen klappt.

                Vielen Dank für die Anregungen.
                PHP-Klassen auf github

                Kommentar


                • #9
                  Zusammenfassung

                  Müssen DateTime-Objekte überprüft werden (z.B. bei Unit-Test's) reicht es genau genommen nicht aus, diese mit einen anderen DateTime-Objekt zu vergleichen. Der typeschwache Vergleich von DateTime-Objekten liefert TRUE, wenn diese Objekte gleiche Zeitpunkte repräsentieren. So können auch DateTime-Objekte mit unterschiedlichen Zeiten/Timezonen ein "gleich" liefern. Um die Objekte bez. Zeit und Zeitzone zu überprüfen bietet sich an die Resultate vom json_encode der DateTime-Objekte zu vergleichen.

                  Der typeschwache Vergleich von Zeitzonenobjekten (DateTimeZone) liefert immer true, unabhängig vom Inhalt (Ein Bug oder gewollt?). Um diese Objekte zu überprüfen bietet sich für PHP Versionen ab 7 ebenfalls an json_encode zu nehmen. Bei mehrern alten PHP-Versionen funktioniert das nicht.

                  LG jspit



                  PHP-Klassen auf github

                  Kommentar


                  • #10
                    Zitat von jspit
                    Um diese Objekte zu überprüfen bietet sich für PHP Versionen ab 7 ebenfalls an json_encode zu nehmen. Bei mehrern alten PHP-Versionen funktioniert das nicht.

                    Unter 7 teilweise mit serialize() statt json_encode(). Zumindest ab 5.5.5

                    PHP-Code:
                    $tza = new DateTimeZone("America/New_York");
                    $tzb = new DateTimeZone("Europe/Berlin");
                    $tzc = new DateTimeZone("America/New_York");

                    var_dump($tza == $tzb);  
                    var_dump(serialize($tza) == serialize($tzb));  
                    var_dump(serialize($tza) == serialize($tzc)); 
                    PHP-Code:

                    /* PHP 7
                    bool(true)
                    bool(false)
                    bool(true)
                    */

                    /*
                    5.5.5
                    bool(true)
                    bool(false)
                    bool(true)
                    */

                    /*
                    5.4
                    bool(true)
                    bool(true)
                    bool(true)
                    */ 
                    Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
                    PHP.de Wissenssammlung | Kein Support per PN

                    Kommentar


                    • #11
                      Würde folgendes funktionieren?

                      PHP-Code:
                      function isEqualDateTimeZone(DateTimeZone $fooDateTimeZone $bar): bool {
                          
                      $now = new DateTime();
                          return 
                      $foo->getOffset($now) === $bar->getOffset($now);
                      }

                      $tza = new DateTimeZone("America/New_York");
                      $tzb = new DateTimeZone("Europe/Berlin");
                      var_dump(isEqualDateTimeZone($tza$tzb)); 

                      Kommentar


                      • #12
                        Ein gleicher Offset bedeutet nicht die gleiche Zeitzone. Es gibt mehrere Zeitzonen mit einem gleichen Offset, wobei der Offset auch abhängig vom Datum ist, das in $now steckt. Also je nach Zeitpunkt des Aufrufs liefert die Funktion ein anderes Ergebnis.

                        Kommentar


                        • #13
                          Ja. Diese nützliche Funktion liefert eine Aussage ob 2 Zeitzonen zum aktuellen Zeitpunkt unabhängig vom Typ die gleiche Zeitzone repräsentieren (genau genommen eben den selben Offset haben).

                          Beispiel:
                          PHP-Code:
                          function isEqualDateTimeZone(DateTimeZone $fooDateTimeZone $bar): bool {
                              
                          $now = new DateTime();
                              return 
                          $foo->getOffset($now) === $bar->getOffset($now);
                          }

                          $tza = new DateTimeZone("+200");
                          $tzb = new DateTimeZone("Europe/Berlin");

                          debug::write(
                            
                          isEqualDateTimeZone($tza$tzb),
                            
                          json_encode($tza) === json_encode($tzb),
                            
                          $tza,
                            
                          $tzb
                          ); 
                          Der Vergleich mit isEqualDateTimeZone() liefert jetzt zur Sommerzeit "true". Im Winter dagegen false.
                          Der Vergleich mit json_encode dagegen liefert immer false.
                          [16.07.2019 09:42:41,345](368k/395k) Debug::write "console.php" Line 13
                          0 boolean true
                          1 boolean false
                          2 object(DateTimeZone)(2) DateTimeZone::__set_state(array( 'timezone_type' => 1, 'timezone' => "+02:00", ))
                          3 object(DateTimeZone)(2) DateTimeZone::__set_state(array( 'timezone_type' => 3, 'timezone' => "Europe/Berlin", ))
                          Kommt halt darauf an was genau geprüft werden soll.

                          Edit: Antwort von hellbringer bei Erstfassung noch nicht gelesen.
                          PHP-Klassen auf github

                          Kommentar

                          Lädt...
                          X