HansImGlück: PHP Datumsformat wandeln

Hallo,

in einer CSV steht das Datum in folgendem deutschen Format:

01-Nov-2019, 25-Okt-2019.

Ich muss das Datum jetzt in das Format "d.m.Y" wandeln. Bevor ich die Umwandlung durchführen kann, müssen die deutschen Kurzbezeichnungen ins englische übersetzt werden oder gibts ne PHP Funktion, die das auch mit den deutschen Kurzbezeichnungen hinbekommt?

Gruß Hans

  1. Hello,

    Hallo,

    in einer CSV steht das Datum in folgendem deutschen Format:

    01-Nov-2019, 25-Okt-2019.

    Ich muss das Datum jetzt in das Format "d.m.Y" wandeln. Bevor ich die Umwandlung durchführen kann, müssen die deutschen Kurzbezeichnungen ins englische übersetzt werden oder gibts ne PHP Funktion, die das auch mit den deutschen Kurzbezeichnungen hinbekommt?

    Das "Übersetzen" kannst Du mittels str_ireplace() erledigen lassen. Den Rest mit strtotime() und date().

    Beachte, dass bei den Zeitfunktionen die Zeitzoneneinstellungen des Scriptservers zugrunde liegen.

    Glück Auf
    Tom vom Berg

    --
    Es gibt nichts Gutes, außer man tut es!
    Das Leben selbst ist der Sinn.
  2. Aus dem Handbuch:

    <?php
    $date = DateTime::createFromFormat('j-M-Y', '15-Feb-2009');
    echo $date->format('Y-m-d');
    
    1. Leider hat setlocale() offenbar keinen Einfluss auf date_create_from_format(). Dann eben so:

      <?php
      $dates = [
      '28-Jan-2019',
      '28-Feb-2019',
      '28-Mär-2019',
      '28-Apr-2019',
      '28-Mai-2019',
      '28-Jun-2019',
      '28-Jul-2019',
      '28-Aug-2019',
      '28-Sep-2019',
      '28-Okt-2019',
      '28-Nov-2019',
      '28-Dez-2019'
      ];
      
      $s=['Mär', 'Mai', 'Okt', 'Dez'];
      $r=['Mar', 'May', 'Oct', 'Dec'];
      
      
      foreach ( $dates as $date ) {
      	$d = date_create_from_format(
      			'j-M-Y',
      			str_replace( $s, $r, $date )
      		);
      	echo date_format($d, 'd.m.Y') . "\n";
      }
      

      Test:

      28.01.2019
      28.02.2019
      28.03.2019
      28.04.2019
      28.05.2019
      28.06.2019
      28.07.2019
      28.08.2019
      28.09.2019
      28.10.2019
      28.11.2019
      28.12.2019
      

      Es gäbe freilich noch die Umwandlung über reine Textersetzung bzw. Arrayfunktionen wie $ar=implode('-', $date), dann Ersetzen der Monate und abschließendem Zusammenbau eines Strings. Aber wenn mit den Datumsangaben gerechnet werden muss ist obiges der "Königsweg".

      1. Hello,

        Änderungsvorschlag:

        <?php
        
        # [•••] 
        
            $dates = str_replace( $s, $r, $dates);
        
            foreach ( $dates as $date ) 
            {
                $d = date_create_from_format('j-M-Y', $date);
                echo date_format($d, 'd.m.Y') . PHP_EOL;
            }
        

        Man könnte auch array_map() verwenden.

        Es bleibt hier noch zu erwähnen, dass hier noch keinerlei Datenkontrolle und Fehlerbehandlung durchgeführt wurde, die man selbstverständlich in einem Produktivmodul benötigen würde! :-)

        Glück Auf
        Tom vom Berg

        --
        Es gibt nichts Gutes, außer man tut es!
        Das Leben selbst ist der Sinn.
        1. Es bleibt hier noch zu erwähnen, dass hier noch keinerlei Datenkontrolle und Fehlerbehandlung durchgeführt wurde, die man selbstverständlich in einem Produktivmodul benötigen würde! :-)

          Ich bin mir nur nicht ganz sicher, ob man das Beginnern so anbieten sollte, denn "Hilfe zur Selbsthilfe" heisst ja nicht, dass man die Hilfesuchenden verschreckt und für die anderen die eigentliche Hilfe in 100 Zeilen versteckt. (Für "maximal verschreckt" hätte ich jetzt noch Kommentare eingefügt, die Klasse isoliert und einen Unit-Test via Shell-Batch gebaut mit dem ich auch mehrere fatale Fehler abfangen und zeigen kann.

          <?php
          class date_create_from_german_d_M_Y {
          
              private static $defaultErrorType = E_USER_NOTICE;
          	private static $search  = ['Mär', 'Mai', 'Okt', 'Dez'];
          	private static $replace = ['Mar', 'May', 'Oct', 'Dec'];
          
          	function __construct( $string = FALSE, $errorType = '' ) {
          		if ( $string ) return getDateObject( $string, $this->userErrorType );
          	}
          	
          	public function getDateObject ( $string, $errorType = FALSE ) {
          		if ( FALSE === $errorType ) { 
          			$errorType = self::$defaultErrorType;
          		} else {
          			self::checkErrorType( $errorType );
          		}
          						
          		$d = date_create_from_format(
          			'j-M-Y',
          			str_replace( self::$search, self::$replace, $string )
          		);
          		if ( false === $d ) {
          			self::onError( $string, $errorType );
          			return FALSE;
          		}
          		return $d;
          	}
          	
          	private function onError( $string, $errorType = '' ) {
          		if ( '' === $errorType ) $errorType = self::$defaultErrorType;
          		trigger_error( __class__ . ':' . __function__ . ':'. " input '$string' is not definied.", $errorType );
          	}
          	
          	private function checkErrorType ( $errorType ) {
          		if ( in_array ($errorType, [ E_USER_NOTICE, E_USER_WARNING, E_USER_ERROR ] ) ) {
          			return true;
          		} else {
          			trigger_error( __class__ . ':' . __function__ . ':'. " Der Errortype darf nur [ E_USER_NOTICE, E_USER_WARNING, E_USER_ERROR ] sein. Gesetzt wurde '$errorType'", E_USER_ERROR );
          		}
          	}
          	
          }
          echo '---------------------------' .  PHP_EOL;
          echo 'TESTS:' .  PHP_EOL;
          
          $dates = [
          '28-Jan-2019',
          '28-Feb-2019',
          '28-Mär-2019',
          '28-Apr-2019',
          '28-Mai-2019',
          '28-Jun-2019',
          '28-Jul-2019',
          '28-Aug-2019',
          '28-Sep-2019',
          '28-Okt-2019',
          '28-Nov-2019',
          '28-Dec-2019'
          ];
          
          echo '---------------------------' .  PHP_EOL;
          echo 'Direkte Benutzung der Klasse' .  PHP_EOL;
          echo 'Erwartet: Fehlerfreie Ausgaben:' .  PHP_EOL;
          echo '---------------------------' .  PHP_EOL;
          foreach ( $dates as $date ) {
          	$date = date_create_from_german_d_M_Y::getDateObject( $date );
          	echo $date->format('Y-m-d') . PHP_EOL;
          }
          
          echo '---------------------------' .  PHP_EOL;
          echo "Benutzung eines Objektes ( WOHL schneller bei Massendaten )" .  PHP_EOL;
          echo "Erwartet: Fehlerfreie Ausgaben:" .  PHP_EOL;
          echo '---------------------------' .  PHP_EOL;
          $object = new date_create_from_german_d_M_Y();
          foreach ( $dates as $date ) {
          	$date = $object -> getDateObject( $date );
          	echo $date->format('Y-m-d') . PHP_EOL;
          }
          
          echo '---------------------------' .  PHP_EOL;
          echo "Erwartet: Fehler (Notiz):" .  PHP_EOL;
          echo '---------------------------' .  PHP_EOL;
          echo date_create_from_german_d_M_Y::getDateObject( '28-FOO-2019' ) .  PHP_EOL;
          
          echo '---------------------------' .  PHP_EOL;
          echo "Erwartet: Fehler (Notiz):" .  PHP_EOL;
          echo '---------------------------' .  PHP_EOL;
          echo date_create_from_german_d_M_Y::getDateObject( '28-FOO-2019', E_USER_NOTICE ) .  PHP_EOL;
          
          /*
          echo '---------------------------' .  PHP_EOL;
          echo "Erwartet: Fehler (Fatal):" .  PHP_EOL;
          echo '---------------------------' .  PHP_EOL;
          echo date_create_from_german_d_M_Y::getDateObject( '28-FOO-2019', E_USER_ERROR ) .  PHP_EOL;
          #*/
          
          echo '---------------------------' .  PHP_EOL;
          echo "Erwartet: Fehler (Fatal):" .  PHP_EOL;
          echo '---------------------------' .  PHP_EOL;
          echo date_create_from_german_d_M_Y::getDateObject( '28-FOO-2019', FALSCHER_WERT ) .  PHP_EOL;
          
  3. Hallo HansImGlück,

    Was ist mit strptime, strftime?

    Bis demnächst
    Matthias

    --
    Pantoffeltierchen haben keine Hobbys.
    ¯\_(ツ)_/¯
    1. Hallo Matthias,

      hab ich mir heute morgen angeschaut. Zum einen ist strptime betriebssystemabhängig und unter Windows gar nicht verfügbar (was ggf. stören kann, aber nicht muss).

      Zum zweiten habe ich strptime in der Sandkiste nicht zum Laufen bekommen, meine Einstellung von setlocale("de_DE") führte nicht dazu, dass Okt als Monat akzptiert wurde. Vielleicht ist das Locale dort nicht installiert, vielleicht gibt's ein anderes Problem, ich weiß es nicht und habe im Moment auch keinen Linux-Server im Zugriff, auf dem ich es testen könnte.

      Als alter Windows-Muckel hätte ich es mir also wohl eh per Regex gepolyfillt.

      Rolf

      --
      sumpsi - posui - clusi
  4. in einer CSV steht das Datum in folgendem deutschen Format:

    01-Nov-2019, 25-Okt-2019.

    Ich muss das Datum jetzt in das Format "d.m.Y" wandeln.

    Mal ganz generell gefragt:

    Hast Du denn Einfluss auf das Format? Es dürfte aus leicht begreiflichen Gründen sehr viel klüger sein, beim Export bzw. Erzeugen der CSV-Datei darauf zu achten, dass für ein Datum das allgemein verständlichere ISO-Format (eg. '2019-12-31') verwendet wird. Die Katze zu schleudern und in den Wäschetrockner zu packen nachdem man sie in der Maschine bei 60° mit gewaschen hat macht selbige zwar trocken - aber keineswegs wieder lebendig.

    "Schleuder und Wäschetrockner"

    <?php
    class date_create_from_locale_d_M_Y {
    
        private static $defaultErrorType = E_USER_NOTICE;
    	private $search ;
    	private $replace = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
    	protected $locale;
    	private $allLocales;
    
    	function __construct(
    		$locale = FALSE,
    		$errorType = ''
    	) {
    		$this->setLocale ( $locale );
    	}
    	
    	public function setLocale ($locale ) {
    		if ( FALSE === $locale) {
    			$this->locale =  'C';
    		} else { 
    			$this->locale = $locale;
    		}
    			
    		$oldLocale = $this->getCurrentLocale();
    		
    		setlocale( LC_ALL, $this->locale ) . PHP_EOL;
    		
    		$this -> search = [];
    		$dto = new DateTime();
    		for ( $i=1; $i<13; $i++ ) {
    			$dto->setDate('1970', $i , '1');
    			$this -> search[] = strftime( '%b', $dto->getTimestamp() );
    		}
    		setlocale( LC_ALL, $oldLocale );
    	}
    	
    	public function getDateObject ( $string, $errorType = FALSE ) {
    		if ( FALSE === $errorType ) { 
    			$errorType = self::$defaultErrorType;
    		} else {
    			$this->checkErrorType( $errorType );
    		}
    						
    		$d = date_create_from_format(
    			'j-M-Y',
    			str_replace( $this->search, $this->replace, $string )
    		);
    		if ( false === $d ) {
    			self::onError( $string, $errorType );
    			return FALSE;
    		}
    		return $d;
    	}
    	
    	public function getCurrentLocale() {
    		$arr=explode( ';', setlocale(LC_ALL, 0 ) );
    		return $arr[0];
    	}
    	
    	public function showMonts() {
    		echo implode(' ', $this->search ) . PHP_EOL;
    	}
    	
    	private function onError( $string, $errorType = '' ) {
    		if ( '' === $errorType ) $errorType = self::$defaultErrorType;
    		trigger_error( __class__ . ':' . __function__ . ':'. " input '$string' is not definied.", $errorType );
    	}
    	
    	private function checkErrorType ( $errorType ) {
    		if ( in_array ($errorType, [ E_USER_NOTICE, E_USER_WARNING, E_USER_ERROR ] ) ) {
    			return true;
    		} else {
    			trigger_error( __class__ . ':' . __function__ . ':'. " Der Errortype darf nur [ E_USER_NOTICE, E_USER_WARNING, E_USER_ERROR ] sein. Gesetzt wurde '$errorType'", E_USER_ERROR );
    		}
    	}
    	
    }
    
    ####################### Usage / Tests #####################
    
    echo 'TESTS:' .  PHP_EOL;
    
    foreach (
    		[
    			'C',
    			'de_DE.utf8',
    			'en_US.utf8',
    			'fr_FR.utf8',
    			'pl_PL.utf8',
    			'ru_RU.utf8',
    			'xh_ZA.utf8'
    		]
    	as $loc
    	) {
    		
    		$arr = explode( ';', setlocale( LC_ALL, 0 ) );
    		$oldLocale = $arr[0];
    		setlocale( LC_ALL, $loc ) . PHP_EOL;
    		$dto = new DateTime();
    		$months=[];
    		
    		
    		for ( $i=1; $i<13; $i++ ) {
    			$dto->setDate('1970', $i , '1');
    			$months[] = strftime( '%b', $dto->getTimestamp() );
    		}
    		setlocale( LC_ALL, $oldLocale );
            $dates=[];
            foreach ( $months as $m ) {
    			$dates[] = '28-' . $m . '-1970';
    		}
    		$object = new date_create_from_locale_d_M_Y('C');
    		$object -> setlocale($loc);
    
    		echo PHP_EOL;
    		echo '---------------------------' .  PHP_EOL;
    		echo $loc . ':' . PHP_EOL;
    		$object -> showMonts();
    		echo '---------------------------' .  PHP_EOL;
    
    		foreach ( $dates as $datum ) {
    			$date = $object -> getDateObject( $datum );
    			if ( $date ) echo $datum . "\t" . $date->format('Y-m-d') . PHP_EOL;
    		}
    		echo '---------------------------' .  PHP_EOL;	
    	}
    
    exit;