Comparar periodos en Laravel: la clase Period con Carbon y sus tests
Hola, bienvenido. Para comparar periodos en Laravel, por ejemplo los últimos 30 días frente a los 30 anteriores, lo más limpio es un objeto que guarde el inicio y el fin como CarbonImmutable y sepa calcular su periodo anterior de la misma duración. En esta lección vamos a escribir esa clase, Period, junto con los periodos predefinidos del filtro del dashboard y una etiqueta en español, y la vamos a probar con Pest sin tocar la base de datos.
Por qué un objeto y no 2 fechas sueltas
El filtro de la página, cada widget y el informe en PDF necesitan exactamente lo mismo: desde cuándo, hasta cuándo, cuál es el periodo anterior con el que se comparan y cómo se escribe ese periodo para que lo lea una persona. Si cada uno lo calcula por su cuenta con 2 fechas, tarde o temprano se descuadran: un widget cuenta los 30 días hasta el día actual y otro hasta el anterior, el periodo anterior se calcula con subMonth() en un sitio y con subDays(30) en otro, o un rango termina a las 00:00 del último día y deja fuera todos sus pedidos. Y el cliente ve en el PDF unos ingresos distintos de los del panel.
Con un objeto, esas reglas se escriben una vez y se prueban una vez. Las de Period son estas:
- Empieza a las 00:00:00 del primer día y termina a las 23:59:59 del último, siempre.
- Si las 2 fechas llegan al revés, se ordenan.
- El periodo anterior dura los mismos días y termina el día antes de que empiece este.
- Sabe escribirse en español: "Del 1 al 30 de septiembre de 2026".
Alrededor de Period va un enum, PeriodPreset, con las opciones del filtro (hoy, 7 días, 30 días, este mes, este trimestre y un rango personalizado), que convierte cada opción en su Period. El formulario del filtro lo crearemos en la lección 6; aquí dejamos listas las piezas que va a usar.
Si lo que buscas es filtrar una consulta por un rango de fechas desde un controlador, lo tienes en Filtrar por rango de fechas en Laravel (se abre en una pestaña nueva). Aquí vamos un paso más allá con la misma idea: el rango pasa a ser una clase propia con sus tests, y el whereBetween llegará en la lección 5 como un scope del modelo Order.
- 02La clase Period
- 03Los periodos del filtro: PeriodPreset
- 04Tests de Period sin base de datos
- 05El circuito de calidad y el commit