{"id":78,"date":"2015-11-03T22:47:10","date_gmt":"2015-11-03T21:47:10","guid":{"rendered":"http:\/\/lab.fawno.com\/?p=78"},"modified":"2022-03-07T01:17:53","modified_gmt":"2022-03-07T00:17:53","slug":"","status":"publish","type":"post","link":"https:\/\/lab.fawno.com\/en\/2015\/11\/03\/calculos-con-fechas-en-php\/","title":{"rendered":"","raw":""},"content":{"rendered":"","protected":false,"raw":""},"excerpt":{"rendered":"","protected":false,"raw":""},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_typography_data":[],"_editorskit_blocks_typography":"","_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","_es_post_content":"\n
Estoy realmente cansado de ver por ah\u00ed c\u00e1lculos con fechas que est\u00e1n mal hechos.<\/p>\n\n\n\n
Tradicionalmente si se quiere a\u00f1adir un d\u00eda a una fecha dada se hace lo siguiente:<\/p>\n\n\n\n
$date2 = $date1 + 86400;<\/pre>\n\n\n\nB\u00e1sicamente a una fecha en formato UNIX<\/a> ($date1<\/em>) a\u00f1adimos los 86400 segundos que tiene un d\u00eda. Esto es correcto salvo que estemos en una zona horaria con cambio de hora (DST<\/a>), por eso ES INCORRECTO<\/strong>.<\/p>\n\n\n\n
Para a\u00f1adir un intervalo cualquiera a una fecha lo CORRECTO es hacer lo siguiente:<\/p>\n\n\n\n
$date2 = strtotime('+1day', $date1);<\/pre>\n\n\n\n\n\nUtilizamos la funci\u00f3n strtotime<\/a><\/em> que convierte cualquier cadena de texto en un timestamp (tiempo UNIX). La \u00fanica pega es que s\u00f3lo entiende cadenas en ingl\u00e9s, por lo dem\u00e1s es muy \u00fatil:\n\n<\/p>\n\n\n\n
ini_set('date.timezone', 'Europe\/Madrid');\n\n$dst1 = strtotime('last sunday of march');\n$dst2 = strtotime('last sunday of october');<\/pre>\n\n\n\nEn el ejemplo que antecede estas l\u00edneas he definido la zona horaria de Madrid que se rige por DST que comienza el \u00faltimo domingo de marzo y termina el \u00faltimo domingo de octubre, despu\u00e9s calculo dichas fechas dici\u00e9ndole precisamente eso a strtotime<\/em>.<\/p>\n\n\n\n
Para calcular la diferencia entre dos fechas puede tentarnos hallar directamente la diferencia entre sus timestamps, por lo que tendr\u00edamos los segundos entre una fecha y otra... otra vez INCORRECTO<\/strong>. Para calcular diferencias entre fechas tenemos la funci\u00f3n date_diff<\/em><\/a> que es un alias de DateTime::diff<\/em><\/a>.<\/p>\n\n\n\n
Un ejemplo completo:<\/p>\n\n\n\n
<?php\n\tini_set('date.timezone', 'Europe\/Madrid');\n\n\tdefine('HT',\t\"\\x09\");\t\/\/ \\x09\t\\t\tHorizontal Tab\n\tdefine('LF',\t\"\\x0A\");\t\/\/ \\x0A\t\\n\tLine feed\n\n\t\/\/ Calculamos el inicio del DST: \u00faltimo domingo de marzo (2015-03-29 00:00:00 para 2015).\n\t$date10 = strtotime('last sunday of march');\n\techo strftime('$date10 = strtotime(\"last sunday of march\"); => %Y-%m-%d %H:%M:%S', $date10), LF;\n\t\/\/ A\u00f1adimos un d\u00eda a $date10 de la manera correcta (2015-03-30 00:00:00 para 2015).\n\t$date11 = strtotime('+1day', $date10);\n\techo strftime('$date11 = strtotime(\"+1day\", $date10); => %Y-%m-%d %H:%M:%S', $date11), LF;\n\t\/\/ A\u00f1adimos un d\u00eda a $date10 de la manera incorrecta (2015-03-30 01:00:00 para 2015).\n\t$date12 = $date10 + 86400;\n\techo strftime('$date12 = $date10 + 86400; => %Y-%m-%d %H:%M:%S', $date12), LF;\n\n\techo LF;\n\n\t\/\/ Calculamos el final del DST: \u00faltimo domingo de octubre (2015-10-25 00:00:00 para 2015).\n\t$date20 = strtotime('last sunday of october');\n\techo strftime('$date20 = strtotime(\"last sunday of october\"); => %Y-%m-%d %H:%M:%S', $date20), LF;\n\t\/\/ A\u00f1adimos un d\u00eda a $date20 de la manera correcta (2015-10-26 00:00:00 para 2015).\n\t$date21 = strtotime('+1day', $date20);\n\techo strftime('$date21 = strtotime(\"+1day\", $date20); => %Y-%m-%d %H:%M:%S', $date21), LF;\n\t\/\/ A\u00f1adimos un d\u00eda a $date20 de la manera incorrecta (2015-10-25 23:00:00 para 2015).\n\t$date22 = $date20 + 86400;\n\techo strftime('$date22 = $date20 + 86400; => %Y-%m-%d %H:%M:%S', $date22), LF;\n\n\techo LF;\n\n\t\/\/ Calculamos la diferencia entre fechas de manera incorrecta, nos dar\u00e1 82800 segundos (23 horas) para el inicio del DST.\n\t$date_diff12 = $date11 - $date10;\n\techo '$date_diff12 = $date11 - $date10; => ', $date_diff12, ' segundos = ' , $date_diff12 \/ 3600, ' horas', LF;\n\t\/\/ Calculamos la diferencia entre fechas de manera correcta, nos dar\u00e1 un d\u00eda exacto.\n\t$date_diff11 = date_diff(new DateTime(date('Y-m-d H:i:s', $date10)), new DateTime(date('Y-m-d H:i:s', $date11)))->format('%R %y a\u00f1os, %m meses, %d d\u00edas, %h horas, %i minutos, %s segundos');\n\techo '$date_diff11 = date_diff(new DateTime(date(\"Y-m-d H:i:s\", $date10)), new DateTime(date(\"Y-m-d H:i:s\", $date11))); => ', $date_diff11, LF;\n\n\techo LF;\n\n\t\/\/ Calculamos la diferencia entre fechas de manera incorrecta, nos dar\u00e1 90000 segundos (25 horas) para el final del DST.\n\t$date_diff22 = $date21 - $date20;\n\techo '$date_diff22 = $date21 - $date20; => ', $date_diff22, ' segundos = ' , $date_diff22 \/ 3600, ' horas', LF;\n\t\/\/ Calculamos la diferencia entre fechas de manera correcta, nos dar\u00e1 un d\u00eda exacto.\n\t$date_diff21 = date_diff(new DateTime(date('Y-m-d H:i:s', $date20)), new DateTime(date('Y-m-d H:i:s', $date21)))->format('%R %y a\u00f1os, %m meses, %d d\u00edas, %h horas, %i minutos, %s segundos');\n\techo '$date_diff21 = date_diff(new DateTime(date(\"Y-m-d H:i:s\", $date20)), new DateTime(date(\"Y-m-d H:i:s\", $date21))); => ', $date_diff21, LF;\n<\/pre>\n\n\n\n