Convertendo string em Date e DateTime

292

Se eu tenho uma string PHP no formato de mm-dd-YYYY(por exemplo, 10-16-2003), como eu a converto corretamente em ae Dateentão a DateTimeno formato de YYYY-mm-dd? A única razão pela qual peço os dois Datee DateTimeé porque preciso de um em um local e o outro em um local diferente.

Chris Pinski
fonte

Respostas:

480

Use strtotime()no seu primeiro encontro e depois date('Y-m-d')converta-o novamente:

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

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

echo $newformat;
// 2003-10-16

Observe que há uma diferença entre o uso de barra /e hífen -na strtotime()função. Para citar php.net:

As datas nos formatos m / d / a ou dmy são desambiguadas observando o separador entre os vários componentes: se o separador for uma barra (/), será assumido o valor m / d / a americano; enquanto que se o separador for um hífen (-) ou um ponto (.), o formato dmy europeu é assumido.

Para evitar possíveis ambiguidades, é melhor usar datas ISO 8601 (AAAA-MM-DD) ou DateTime :: createFromFormat () quando possível.

Ibu
fonte
11
Isso não vai funcionar. O PHP interpretará essa entrada como DD-MM-AAAA.
Matthew
eu adicionei um pouco mais explicação para o meu código, graças @konforce
Ibu
9
Leia a próxima resposta para uma solução melhor
Manuel Bitto 14/06
@delive sua sequência de datas provavelmente não é uma data correta.
Ibu 05/04
8
Não funciona porque esta resposta é enganosa. strtotimeaceita determinados formatos. Você não pode alimentá-lo. É por isso que DateTime::createFromFormatdeve ser usado em vez de strtotime. Infelizmente, essa resposta tem muitos votos positivos para alguém prestar atenção. É tudo copiar e colar nos dias de hoje.
NB
432

Você precisa ter cuidado com os formatos m / d / Y e mdY. O PHP considera /m / d / Y e -dmY. Eu descreveria explicitamente o formato de entrada neste caso:

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

Dessa forma, você não está sob os caprichos de uma certa interpretação.

Mateus
fonte
37
Curioso para saber por que essa não é a resposta aceita ... Isso é muito mais flexível do que depender das peculiaridades da strtotime()função.
usar o seguinte código
9
É importante assinalar que php DateTime classe está disponível desde o PHP versão 5.2 e createFromFormat desde 5.3
Diego Nemo
14
Como em todas as funções, você deve verificar se ele atende à versão mínima que você deve suportar. Mas o PHP 5.2 EOL foi em janeiro de 2011. Ninguém deveria executá-lo mais; atender a essas pessoas apenas permite que elas executem software desatualizado e inseguro.
Matthew
@ Matthew sim, correto. Mas você nunca agora, até hoje eu encontrei uma versão PHP4.1 ainda instalado ...
Roland
29

Para analisar a data, você deve usar: DateTime :: createFromFormat ();

Ex:

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

No entanto, cuidado, porque isso irá falhar com:

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

Você realmente precisa verificar se a formatação correu bem, primeiro:

$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");

Agora, em vez de travar, você receberá uma exceção, que pode ser capturada, propagada etc.

$ dateDE tem o formato errado, deve ser "16.10.2013";

user2707671
fonte
Observe que marcar $ dateObj dessa maneira apenas garantiria que o formato corresponda à máscara, e não que a data seja realmente válida. Por exemplo, uma data como 99/99/2010 passaria nessa verificação, pois corresponde a m / d / A, mas não é uma data que você normalmente deseja permitir. Esta resposta resolve esta situação -> 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

Editar: você também pode passar um construtor DateTimeZone para DateTime () para garantir a criação da data para o fuso horário desejado, não o padrão do servidor.

NB
fonte
6
Acredito que isso gerará uma exceção porque o mês 16 é inválido.
Matthew
É importante assinalar que php DateTime classe está disponível desde o PHP versão 5.2 e getTimestamp desde 5.3
Diego Nemo
2

Pela primeira data

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

Para nova data

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

Se você tiver o formato dd-mm-aaaa, no PHP não funcionará conforme o esperado. No documento PHP, eles têm diretrizes abaixo.

As datas nos formatos m / d / a ou dmy são desambiguadas observando o separador entre os vários componentes: se o separador for uma barra (/), será assumido o valor m / d / a americano; enquanto que se o separador for um hífen (-) ou um ponto (.), o formato dmy europeu é assumido.

Então, você simplesmente não pode usar como quiser. Quando você tentar usar o formato dd / mm / aaaa com isso, ele removerá FALSE. Você pode ajustar o seguinte.

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

Como se tivéssemos a data "07 / maio / 2018" e precisamos da data "2018-05-07" como compatível com mysql

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

Funciona para mim. desfrutar :)

Newton Singh
fonte
0

Como ninguém mencionou isso, aqui está outra maneira:

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

Sodj
fonte
0

Se você deseja aceitar datas usando pedidos americanos (mês, data, ano) para formatos de estilo europeu (usando traço ou período como dia, mês, ano) enquanto ainda aceita outros formatos , você pode estender a 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, você pode criar uma função para aceitar mdY e gerar 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
fonte
0

para criar data a partir de qualquer string, use:
$ date = DateTime :: createFromFormat ('dmy H: i', '01-01-01 01:00 '); eco $ date-> formato ('Ymd H: i');

Azouz Mohamadi
fonte