Para los que tenemos que coordinar números de semana que provienen de fechas manejadas entre MySQL y PHP, a veces es un reto, especialmente cuando se trata de la última o primera semana de un año.
Cuál es el asunto? Dependiendo de cómo uno cuenta las semanas del año (por ejemplo iniciando en 0 o iniciando en 1) la semana del 31 de diciembre 2018 podría ser considerada como la última del año 2018 o la primera del 2019. Y por ende, podría ser la Semana 53 del 2018, la Semana 0 del 2019 o la Semana 1 del 2019. Adicionalmente, si uno requiere combinar el número de la semana con el año, podrían darse constelaciones extrañas:
- Ejemplo A: 31/12/2018
- Año de la fecha: 2018
- Número de la semana: primera semana del 2019 (Semana 0 o 1, dependiendo de la configuración del sistema)
- Año de la semana: 2019
- Ejemplo B: 02/01/2016
- Año de la fecha: 2016
- Número de la semana: última semana del 2015 (Semana 52 o 53, dependiendo de la configuración del sistema)
- Año de la semana: 2015
Yo me topé con este fenómeno durante el desarrollo de una interfaz para una base de datos y encontré la pista para mi solucioń en stackoverflow [1].
La interpretación depende de la configuración tanto de MySQL como de PHP en el servidor donde están instalados. Para MySQL, el valor predeterminado es definido por el valor de la propiedad default_week_format
en las variables del sistema [2].
En PHP, el número de la semana es definido e interpretado según ISO-8601 siempre, pero en MySQL la definición puede ser diferente y por ende, cuando haya que homologar información entre MySQL y PHP, pueden ocurrir conflictos. La ISO-8601 define el número de semana de la siguiente manera [3]:
- Las semanas del calendario tienen 7 días e inician los lunes.
- El número de semana 1 es aquella semana, que contiene el primer jueves del año.
En otras palabras: si el 01 de enero cae lunes, martes, miércoles o jueves, está en la semana 1. Si el 01 de enero cae viernes, sábado o domingo, pertenece a la semana 52 o 53 del año anterior.
Para lograr una consistencia entre MySQL, PHP y una fecha determinada, lo recomendable es utilizar la función YEARWEEK en MySQL [4] y date() en PHP [5] de la siguiente manera:
Ejemplos
Ejemplo A
En MySQL:
> SELECT YEARWEEK('2019-01-01', 3);
+---------------------------+
| YEARWEEK('2019-01-01', 3) |
+---------------------------+
| 201901 |
+---------------------------+
1 row in set (0.00 sec)
- Interpretación:
- Resultado: 201901 (Año 2019, Semana 01)
- El argumento 3 define el modo, donde se define el día lunes como primer día de la semana, que la primera semana del año inicia en 1 y la semana 1 es aquella semana que contiene 4 o más días en el año que corresponde [6].
Ingresando la misma fecha en PHP:
<?php
echo date('oW', '2019-01-01');
// muestra en pantalla: 201852
?>
- Interpretación:
- El argumento W indica el número de semana según ISO-6801 y el argumento o el año de la fecha señalada, tomando en consideración (y ajustando cuando sea necesario) el año de la semana calendario (en lugar del año de la fecha).
Ejemplo B
En MySQL:
> SELECT YEARWEEK('2016-01-02', 3);
+---------------------------+
| YEARWEEK('2016-01-02', 3) |
+---------------------------+
| 201553 |
+---------------------------+
1 row in set (0.00 sec)
En PHP:
<?php
echo date('oW', '2016-01-02');
// muestra en pantalla: 201553
?>
Ejemplo C
En MySQL:
> SELECT YEARWEEK('2018-12-31', 3);
+---------------------------+
| YEARWEEK('2018-12-31', 3) |
+---------------------------+
| 201901 |
+---------------------------+
1 row in set (0.00 sec)
En PHP:
<?php
echo date('oW', '2018-12-31);
// muestra en pantalla: 201901
?>
Fuentes
- [1] Reed, M. (2015). PHP date ('W') vs MySQL YEARWEEK(now()). Stack Overflow. https://stackoverflow.com/questions/15562270/php-datew-vs-mysql-yearweeknow
- [2] Oracle. (2019). MySQL Reference Manual: Server System Variables. https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_default_week_format
- [3] Wikipedia. (2019). ISO week date. https://en.wikipedia.org/wiki/ISO_week_date
- [4] Oracle. (2019). MySQL Reference Manual: Date and Time Functions. https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_yearweek
- [5] The PHP Group. PHP: date - Manual. https://secure.php.net/manual/de/function.date.php
- [6] Oracle. (2019). MySQL Reference Manual: Date and Time Funcionts, WEEK. https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_week
Créditos
- Zeller, S. (2018). A number one painted on a red garage door. [Imagen en línea]. Unsplash. https://unsplash.com/