PHP Criando DateTime sem a porção horas

$datetime_without_hours = \DateTime::createFromFormat('!Y-m-d', '1970-08-25');
// 1970-08-25 00:00:00.000000

$datetime_with_hours = \DateTime::createFromFormat('Y-m-d', '1970-08-25');
// 1970-08-25 05:07:32.000000

$datetime_with_hours->setTime(0,0);
// 1970-08-25 00:00:00.000000

Esta semana mesmo eu estive trabalhando num projeto onde tive que incorporar diversos campos de data num integração de sistemas com PHP.

Decidi que enviar os campos com o tipo DateTime para garantir que o aplicativo que recebia a informação pudesse utilizar as datas de forma segura, mas acabei me deparando com a questão de introspecção de horas para uma informação genuinamente Date.

$datetime_with_hours = \DateTime::createFromFormat('Y-m-d', '1970-08-25');
// 1970-08-26 05:07:32.000000

Na primeira tentativa utilizei a máscara Y-m-d simples e verifiquei que a porção Horas:Minutos:Segundos foi inserida na composição da data. O PHP utilizou o Time corrente do Server e incorporou na data.

Depois de uma rápida pesquisa na internet identifiquei que este é o comportado esperado da função. Para evitar a porção horas na composição da data podemos fazer o uso da exclamação na máscara durante a criação do DateTime.

Mas atenção, a inclusão da exclamação na máscara !Y-m-d fará com que apenas um reset da data e hora corrente seja executado antes do datetime ser criado. No entanto, todos os elementos explicitamente definidos na máscara serão tomados em consideração no momento da criação do objeto datetime.

$datetime_with_hours = \DateTime::createFromFormat('!Y-m-d H:i:s', '1970-08-25 13:14:15');
// 1970-08-25 13:14:15.000000

E caso você já possua um objeto que tenha sido criado com a porção horas na composição, você pode resetar este conteúdo para algo qualquer inclusive a nossa desejada hora ZERO, conforme demonstrado abaixo.

$datetime_with_hours = \DateTime::createFromFormat('Y-m-d', '1970-08-25');
// 1970-08-25 05:07:32.000000

$datetime_with_hours->setTime(0,0);
// 1970-08-25 00:00:00.000000

Também, se a data a ser criada seja algo próxima da data corrente você pode utilizar parâmetros no construtor do objeto DateTime para criar o objeto já sem a porção horas.

$datetime_without_hours = new \DateTime("midnight");
// 2021-11-13 00:00:00.000000

$datetime_without_hours = new \DateTime("today");
// 2021-11-13 00:00:00.000000

$datetime_without_hours = new \DateTime("yesterday");
// 2021-11-12 00:00:00.000000

$datetime_without_hours = new \DateTime("tomorrow");
// 2021-11-14 00:00:00.000000

E aí? Curtiu estes recursos para criação de datas?