Conversion d'une chaîne en Date et DateTime

292

Si j'ai une chaîne PHP au format mm-dd-YYYY(par exemple, 10-16-2003), comment puis-je la convertir correctement en a Datepuis DateTimeen a au format YYYY-mm-dd? La seule raison pour laquelle je demande les deux Dateet DateTimeparce que j'ai besoin d'un dans un endroit et l'autre dans un endroit différent.

Chris Pinski
la source

Réponses:

480

Utilisez strtotime()lors de votre premier rendez-vous puis date('Y-m-d')reconvertissez-le:

$time = strtotime('10/16/2003');

$newformat = date('Y-m-d',$time);

echo $newformat;
// 2003-10-16

Notez qu'il existe une différence entre l'utilisation d'une barre oblique /et d'un trait d'union -dans la strtotime()fonction. Pour citer de php.net:

Les dates aux formats m / d / y ou dmy sont désambiguïsées en regardant le séparateur entre les différents composants: si le séparateur est une barre oblique (/), alors le m / d / y américain est supposé; alors que si le séparateur est un tiret (-) ou un point (.), alors le format européen dmy est supposé.

Pour éviter toute ambiguïté potentielle, il est préférable d'utiliser les dates ISO 8601 (AAAA-MM-JJ) ou DateTime :: createFromFormat () lorsque cela est possible.

Ibu
la source
11
Ça ne marchera pas. PHP interprétera cette entrée comme DD-MM-YYYY.
Matthew
j'ai ajouté un peu plus d'explications à mon code, merci @konforce
Ibu
9
Lire la réponse suivante pour une meilleure solution
Manuel Bitto
@delive votre chaîne de date n'est probablement pas une date correcte.
Ibu
8
Cela ne fonctionne pas car cette réponse est trompeuse. strtotimeaccepte certains formats. Vous ne pouvez pas le nourrir quoi que ce soit. C'est pourquoi DateTime::createFromFormatdevrait être utilisé à la place de strtotime. Malheureusement, cette réponse a trop de votes positifs pour que quiconque y prête attention. C'est tout copier-coller de nos jours.
NB
432

Vous devez être prudent avec les formats m / d / Y et mdY. PHP considère /signifier m / d / Y et -signifier dmY. Je décrirais explicitement le format d'entrée dans ce cas:

$ymd = DateTime::createFromFormat('m-d-Y', '10-16-2003')->format('Y-m-d');

De cette façon, vous n'êtes pas aux caprices d'une certaine interprétation.

Matthieu
la source
37
Curieux de savoir pourquoi ce n'est pas la réponse acceptée ... C'est beaucoup plus flexible que de compter sur les caprices de la strtotime()fonction.
jzimmerman2011
9
Il est important de souligner que la classe php DateTime est disponible depuis PHP version 5.2 et createFromFormat depuis 5.3
Diego Nemo
14
Comme pour chaque fonction, vous devez vérifier si elle correspond à la version minimale que vous devez prendre en charge. Mais PHP 5.2 EOL était en janvier 2011. Personne ne devrait plus l'exécuter; la restauration de ces personnes leur permet simplement d'exécuter des logiciels obsolètes et non sécurisés.
Matthew
@Matthew oui, correct. Mais vous ne l'avez jamais fait, même aujourd'hui j'ai trouvé une version PHP4.1 toujours installée ...
Roland
29

Pour analyser la date, vous devez utiliser: DateTime :: createFromFormat ();

Ex:

$dateDE = "16/10/2013";
$dateUS = \DateTime::createFromFormat("d.m.Y", $dateDE)->format("m/d/Y");

Cependant, faites attention, car cela plantera avec:

PHP Fatal error: Call to a member function format() on a non-object 

Vous devez en fait vérifier que le formatage s'est bien passé, d'abord:

$dateDE = "16/10/2013";
$dateObj = \DateTime::createFromFormat("d.m.Y", $dateDE);
if (!$dateObj)
{
    throw new \UnexpectedValueException("Could not parse the date: $date");
}
$dateUS = $dateObj->format("m/d/Y");

Maintenant, au lieu de planter, vous obtiendrez une exception, que vous pouvez attraper, propager, etc.

$ dateDE a le mauvais format, il devrait être "16.10.2013";

user2707671
la source
Notez que la vérification de $ dateObj de cette façon garantirait seulement que le format correspond au masque, et non que la date est réellement valide. Par exemple, une date comme 99/99/2010 passerait cette vérification car elle correspond à m / d / Y mais ce n'est pas une date que vous souhaitez généralement autoriser. Cette réponse résout cette situation -> stackoverflow.com/a/10120725/995014
Kilian Perdomo Curbelo
22
$d = new DateTime('10-16-2003');

$timestamp = $d->getTimestamp(); // Unix timestamp
$formatted_date = $d->format('Y-m-d'); // 2003-10-16

Edit: vous pouvez également passer un constructeur DateTimeZone à DateTime () pour assurer la création de la date pour le fuseau horaire souhaité, pas celui par défaut du serveur.

NB
la source
6
Je crois que cela lèvera une exception car le mois 16 n'est pas valide.
Matthew
Il est important de souligner que la classe php DateTime est disponible depuis PHP version 5.2 et getTimestamp depuis 5.3
Diego Nemo
2

Pour la première date

$_firstDate = date("m-d-Y", strtotime($_yourDateString));

Pour une nouvelle date

$_newDate = date("Y-m-d",strtotime($_yourDateString));
Vi8L
la source
2

Si vous avez le format jj-mm-aaaa, alors en PHP, cela ne fonctionnera pas comme prévu. Dans le document PHP, ils ont ci-dessous la directive.

Les dates aux formats m / d / y ou dmy sont désambiguïsées en regardant le séparateur entre les différents composants: si le séparateur est une barre oblique (/), alors le m / d / y américain est supposé; alors que si le séparateur est un tiret (-) ou un point (.), alors le format européen dmy est supposé.

Donc, vous ne pouvez pas utiliser comme vous le souhaitez. Lorsque vous essayez d'utiliser le format jj / mm / aaaa avec cela, cela supprimera FAUX. Vous pouvez modifier les éléments suivants.

$date = "23/02/2013";
$timestamp = strtotime($date);
if ($timestamp === FALSE) {
  $timestamp = strtotime(str_replace('/', '-', $date));
}
echo $timestamp; // prints 1361577600
MAULIK MODI
la source
1

Comme nous avons la date "07 / Mai / 2018" et nous avons besoin de la date "2018-05-07" comme mysql compatible

if (!empty($date)) {
    $timestamp = strtotime($date);
    if ($timestamp === FALSE) {
         $timestamp = strtotime(str_replace('/', '-', $date));
     }
         $date = date('Y-m-d', $timestamp);
  }

Ça marche pour moi. prendre plaisir :)

Newton Singh
la source
0

Puisque personne ne l'a mentionné, voici une autre façon:

$date = date_create_from_format("m-d-Y", "10-16-2003")->format("Y-m-d");

Sodj
la source
0

Si vous souhaitez accepter des dates en utilisant la commande américaine (mois, date, année) pour les formats de style européen (en utilisant un tiret ou une période comme jour, mois, année) tout en acceptant d'autres formats , vous pouvez étendre la classe DateTime:

/**
 * Quietly convert European format to American format
 *
 * Accepts m-d-Y, m-d-y, m.d.Y, m.d.y, Y-m-d, Y.m.d
 * as well as all other built-in formats
 * 
 */
class CustomDateTime extends DateTime 
{
  public function __construct(string $time="now", DateTimeZone $timezone = null) 
  {
    // convert m-d-y or m.d.y to m/d/y to avoid PHP parsing as d-m-Y (substr avoids microtime error)
    $time = str_replace(['-','.'], '/', substr($time, 0, 10)) . substr($time, 10 );

    parent::__construct($time, $timezone);
  }
}

// usage:
$date = new CustomDateTime('7-24-2019');
print $date->format('Y-m-d');

// => '2019-07-24'

Ou, vous pouvez créer une fonction pour accepter mdY et afficher Ymd:

/**
 * Accept dates in various m, d, y formats and return as Y-m-d
 * 
 * Changes PHP's default behaviour for dates with dashes or dots.
 * Accepts:
 *   m-d-y, m-d-Y, Y-m-d,
 *   m.d.y, m.d.Y, Y.m.d,
 *   m/d/y, m/d/Y, Y/m/d,
 *   ... and all other formats natively supported 
 * 
 * Unsupported formats or invalid dates will generate an Exception
 * 
 * @see https://www.php.net/manual/en/datetime.formats.date.php PHP formats supported
 * @param  string $d various representations of date
 * @return string    Y-m-d or '----' for null or blank
 */
function asYmd($d) {
  if(is_null($d) || $d=='') { return '----'; }

  // convert m-d-y or m.d.y to m/d/y to avoid PHP parsing as d-m-Y
  $d = str_replace(['-','.'], '/', $d);

  return (new DateTime($d))->format('Y-m-d');
}

// usage:

<?= asYmd('7-24-2019') ?>

// or

<?php echo asYmd('7-24-2019'); ?>
Tim Morton
la source
0

pour créer la date à partir de n'importe quelle chaîne, utilisez:
$ date = DateTime :: createFromFormat ('dmy H: i', '01 -01-01 01:00 '); echo $ date-> format ('Ymd H: i');

Azouz Mohamadi
la source