Uso de fechas con strtotime en PHP. Cuidado con el error al añadir o restar meses


En un proyecto tuve que crear un php que fuera llamado desde un cron del servidor, para borrar las entradas del mes actual menos 2.
Resulta que hice las pruebas un 31/05/2023. Mi sorpresa fue que cuando hacía
$variable = date( ‘Y-m’, strtotime( ‘-1 month’ ) );
echo “Valor:” . $variable;
me devolvía un valor que no correspondía
Valor: 2023-05
Se comportaba de una manera rara. Después de mirar y mirar mi código (síndrome del impostor como siempre) pase a mirar por internet y al final encontré en bugs de PHP el aviso. Finalmente lo conseguí, e intenté añadir una nota en la documentación de PHP. No sé si lo pondrán o no, pero espero que el código le sirva a alguien. https://www.php.net/manual/en/function.strtotime.php#128580 en https://www.php.net/manual/en/function.strtotime.php

Lo más importante:

Como aplicar strtotime a una fecha dada. Pongo varias formas para que encunetren este codigo. “php add fixed date value to strtotime”, “php Add strtotime to the given date”, “aplicar strtotime a una fecha fija”, “PHP How add strtotime from specific date”, “Como añadir strtotime a una fecha específica”

$dt1 = strtotime(“2023-01-30”);
echo “\n\nToday is: ” . date( ‘Y-m-d’, $dt1 );

$variable = strtotime(“yesterday”, $dt1);
echo “\nYesterday: ” . date(“Y-m-d”, $variable );

Imprimirá:
Today is: 2023-01-30
Yesterday: 2023-01-29

Para obtener la fecha de unos meses hacia adelante o hacia atrás hay que usar esto. Si no podemos tener problemas por valores extraños o no esperados.

$dt1 = strtotime("2023-02-28");
$month = strtotime("last day of last month", $dt1);
echo "\n\nToday is: " . date( 'Y-m-d', $dt1 );
echo  "\nLast day of last month: " . date("Y-m-d", $month);

// Print:
// Today is: 2023-02-28
// Last day of last month: 2023-01-31

$dt1 = strtotime("2023-02-28");
$month = strtotime("first day of 2 months ago", $dt1);
echo "\n\nToday is: " . date( 'Y-m-d', $dt1 );
echo  "\nFirst day of 2 months ago: " . date("Y-m-d", $month);

// Print:
// Today is: 2023-02-28
// First day of 2 months ago: 2022-12-01

Este es el código que puse en la documentación de PHP:

/*
This is the link to the relative formats that can be used in this function. It's not easy to find in the documentation.

https://www.php.net/manual/en/datetime.formats.relative.php

Here some examples:
*/
<?php 
$today = date( 'Y-m-d', strtotime( 'today' ) );
echo "Today: " . $today;

// Print: Today: 2023-06-01

//Basic Example 
$tomorrow = date( 'Y-m-d', strtotime( 'tomorrow' ) );
echo "\n\nTomorrow: " . $tomorrow;

// Print: Tomorrow: 2023-06-02

$yesterday = date( 'Y-m-d', strtotime( 'yesterday' ) );
echo "\n\nYesterday: " . $yesterday;

// Print: Yesterday: 2023-05-31

// Add o subtract Month
$variable = date( 'Y-m-d', strtotime( '+1 month' ) );
echo "\n\nAdd one month: " . $variable;

// Print: Add one month: 2023-07-01

$variable = date( 'Y-m-d', strtotime( '-1 month' ) );
echo "\n\nSubstract one month: " . $variable;

// Print: Substract one month: 2023-05-01

// More complex formats:
// ERROR / BUG: If today is the last day of the month. This examples can be one error or bug. 
// If you are looking el first day of previous or next month you dont must use last Relative Format. 
// You must use 'first day of 2 months ago' or 'first day of previous month'
// See you: 
// https://bugs.php.net/bug.php?id=22486
// https://bugs.php.net/bug.php?id=44073
// strtotime("+1 Month")
// produces the wrong result on the 31st day of the month.
// on January 31, date("m",strtotime("+1 Month")) will return 03 instead of 02

// Another example:
$dt1 = strtotime("2023-01-30");
$month = strtotime("+1 month", $dt1);
echo "\n\nToday is: " . date( 'Y-m-d', $dt1 );
echo  "\nBUG add month: " . date("Y-m-d", $month);

// Print:
// Today is: 2023-01-30
// BUG add month: 2023-03-02

$dt1 = strtotime("2023-02-28");
$month = strtotime("-1 month", $dt1);
echo "\n\nToday is: " . date( 'Y-m-d', $dt1 );
echo  "\nBUG substract month: " . date("Y-m-d", $month);

// Print:
// Today is: 2023-02-28
// BUG substract month: 2023-01-28

$dt1 = strtotime("2023-01-30");
$month = strtotime("first day of next month", $dt1);
echo "\n\nToday is: " . date( 'Y-m-d', $dt1 );
echo  "\nFirst day of next month: " . date("Y-m-d", $month);

// Print:
// Today is: 2023-01-30
// First day of next month: 2023-02-01

$dt1 = strtotime("2023-02-28");
$month = strtotime("last day of last month", $dt1);
echo "\n\nToday is: " . date( 'Y-m-d', $dt1 );
echo  "\nLast day of last month: " . date("Y-m-d", $month);

// Print:
// Today is: 2023-02-28
// Last day of last month: 2023-01-31

$dt1 = strtotime("2023-02-28");
$month = strtotime("first day of 2 months ago", $dt1);
echo "\n\nToday is: " . date( 'Y-m-d', $dt1 );
echo  "\nFirst day of 2 months ago: " . date("Y-m-d", $month);

// Print:
// Today is: 2023-02-28
// First day of 2 months ago: 2022-12-01

?>
,

cesar
Resumen de privacidad

Esta web utiliza cookies para que podamos ofrecerte la mejor experiencia de usuario posible. La información de las cookies se almacena en tu navegador y realiza funciones tales como reconocerte cuando vuelves a nuestra web o ayudar a nuestro equipo a comprender qué secciones de la web encuentras más interesantes y útiles.