domingo, 11 de marzo de 2012

Marcar el día actual en el mensil

En esta entrada veremos qué modificaciones y agregados hay que hacer sobre el código de la versión 0.2 de index.php para que el mensil que se genera tenga resaltado, de alguna forma, el día que se está mostrando en la página.
Primero, si revisamos la entrada anterior, podemos ver cuáles son las líneas de ese código, que generan todos y cada uno de los días del mes en la tabla del mensil:
  • la línea 25 de la versión 0.2 de index.php imprime los días de la primera semana (en la explicación de la entrada anterior, está numerada como línea 10):
    • {echo "<td>".$a."</td>";}
  • y la línea 31, el resto (en la explicación de la entrada anterior, está numerada como línea 16):
    • echo "<td>".$i."</td>";
El primer cambio es agregar a la celda de la tabla con el número de día que coincida con el del día seleccionado (date("d",$_GET['fechaactual'])) una clase que llamaré diadelafecha.
De esta forma, la línea 25 será sustituida por:
  • { if ($a==date("d",$_GET['fechaactual']))
          { echo "<td class='diadelafecha'>".$a."</td>"; }
    else {
    echo "<td>".$a."</td>"; }
    }
Y la línea 31, por:
  • if ($i==date("d",$_GET['fechaactual']))
          { echo "<td class='diadelafecha'>".$i."</td>"; }
    else {
    echo "<td>".$i."</td>"; }
O sea, que le aplicará la clase diadelafecha solo a la celda que contenga un número igual al día que se está mostrando en la página.
Evidentemente, con sólo estos agregados, aún no se ve ningún cambio, si se ejecuta el script.

El segundo paso es adosarle una hoja de estilos (CSS) externa a index.php.
Para ello se debe agregar la siguiente línea:
<link href="estiloclcphp.css" rel="stylesheet" type="text/css"> en la sección head, o sea podría ser después de la etiqueta <title> de la línea 3.

Tampoco ahora vemos cambios al ejecutar el script, ya que en el primer paso de esta entrada le aplicamos una clase a una de las celdas de la tabla y en el segundo, le adosamos una hoja de estilos que va a definir como se tiene que comportar esa clase. Pero falta escribir la hoja de estilos propiamente dicha.
Para ello, en el mismo lugar que está guardado el archivo index.php hay que crear y guardar un documento de texto plano con el nombre estiloclcphp.css.
De momento, y a modo de prueba, el contenido de ese archivo podría ser:

td.diadelafecha { border: 1px solid #000; }

Lo que se logra con esta hoja de estilos es que todas las celdas (td) que tengan aplicada la clase diadelafecha, tengan un borde sólido de 1 pixel de grosor y de color negro (border: 1px solid #000).

Y ahora sí se ve el resultado. Al ejecutar el script, el día seleccionado en la página se ve en el mensil con un recuadro negro.
Por ejemplo, al ejecutar el script en el día de ayer, el resultado era:



En definitiva, con los cambios ingresados en esta entrada, el código de index.php queda así:
<!DOCTYPE html>
<head>
<title>CLCPHP - Calandario Lit&uacute;rgio Cat&oacute;lico En PHP</title>
<link href="estiloclcphp.css" rel="stylesheet" type="text/css">
</head>
<body>
<?php
include("funciones.php");
if(!isset($_GET['fechaactual'])) {
$_GET['fechaactual']=time();}
$ayer=mktime(0,0,0,date("m",$_GET['fechaactual']), date("d",$_GET['fechaactual'])-1,date("Y",$_GET['fechaactual']));
$manana=mktime(0,0,0,date("m",$_GET['fechaactual']), date("d",$_GET['fechaactual'])+1,date("Y",$_GET['fechaactual']));
echo "<h3>".traducir(date('l j \d\e F \d\e Y',$_GET['fechaactual']))."</h3>\n";
echo "<a href='index.php?fechaactual=".$ayer."'>&lt;&lt; D&iacute;a anterior</a> | ";
echo "<a href='index.php?fechaactual=".$manana."'>D&iacute;a posterior &gt;&gt;</a>";
echo "\n<table>\n";
echo "<tr><th colspan='7'>".ucfirst(traducir(date('F \d\e Y',$_GET['fechaactual'])))."</th></tr>\n";
echo "<tr><th>Do</th><th>Lu</th><th>Ma</th><th>Mi</th><th>Ju</th><th>Vi</th><th>Sa</th></tr>\n";
echo "<tr>";
$primerDiaMes=mktime(0,0,0,date("m",$_GET['fechaactual']), '1',date("Y",$_GET['fechaactual']));
for  ($i=1;$i<=date('w',$primerDiaMes);$i++)
 { echo "<td></td>"; }
$restoPrimeraSemana=8-$i;
for ($a=1;$a<=$restoPrimeraSemana;$a++)
  { if ($a== date("d",$_GET['fechaactual']))
      { echo "<td class='diadelafecha'>".$a."</td>"; }
    else { echo "<td>".$a."</td>"; }
   }
echo "</tr>\n<tr>";
$diasDelMes=date('t',$primerDiaMes);
$i=($i*-1) + 9;
$y=1;
for ($i;$i<=$diasDelMes;$i++)
 { if ($i==date("d",$_GET['fechaactual']))
      { echo "<td class='diadelafecha'>".$i."</td>"; }
   else { echo "<td>".$i."</td>"; }
  if (($y%7=="0") && ($i==$diasDelMes)) { }
  elseif (($y%7=="0") && ($i<$diasDelMes)) { echo "</tr>\n<tr>"; }
  $y++; 
  }
$y--;
$i--;
if (($y%7!="0") && ($i==$diasDelMes)) {
   $ultimoDiaMes=mktime(0,0,0,date("m",$_GET['fechaactual']), $diasDelMes,date("Y",$_GET['fechaactual']));
   $restoUltimaSemana= (date('w',$ultimoDiaMes) * -1) + 6;
   for  ($i=1;$i<=$restoUltimaSemana;$i++)
  { echo "<td></td>"; }
   }
echo "</tr>\n";
echo "</table>\n";
?>
</body>
</html>

domingo, 26 de febrero de 2012

Creación del mensil

En esta oportunidad voy a empezar a crear el código para que se muestre el mensil correspondiente a la fecha seleccionada.

Pero antes, algunas correcciones previas

En la línea 14 de la versión 0.1 de index.php, dice:
echo "<h3>".traducir(date('l d \d\e F \d\e Y',$_GET['fechaactual']))."</h3>";
Cambiando date('l d \d\e F...') por date('l j \d\e F...') se consigue que los números de día menores a 10 se muestren sin el cero de la izquierda.
También agregué la secuencia de caracteres de nueva línea (\n) en lugares específicos de las cadenas de código html, con el solo fin de que cuando se vea el código de la página desde el navegador, éste se muestre más prolijo y no todo de corrido.
Finalmente, borré las líneas 13 y 17 de la versión 0.1 de index.php, que lo que hacían era, respectivamente, abrir y cerrar una caja div para centrar la fecha del día seleccionado. Voy a dejar lo relacionado con la presentación para hacerlo más adelante, con hojas de estilo (CSS) externas.

El mensil

Ahora sí, vamos con el código para crear el mensil que incluye al día seleccionado.
El siguiente es el código que escribí luego de la línea 16 de la versión 0.1 de index.php:

echo "\n<table>\n";
echo "<tr><th colspan='7'>".ucfirst(traducir(date('F \d\e Y',$_GET['fechaactual'])))."</th></tr>\n";
echo "<tr><th>Do</th><th>Lu</th><th>Ma</th><th>Mi</th><th>Ju</th><th>Vi</th><th>Sa</th></tr>\n";
echo "<tr>";
$primerDiaMes=mktime(0,0,0,date("m",$_GET['fechaactual']), '1',date("Y",$_GET['fechaactual']));
for  ($i=1;$i<=date('w',$primerDiaMes);$i++)
 { echo "<td></td>"; }
$restoPrimeraSemana=8-$i;
for ($a=1;$a<=$restoPrimeraSemana;$a++)
   {echo "<td>".$a."</td>";}
echo "</tr>\n<tr>";
$diasDelMes=date('t',$primerDiaMes);
$i=($i*-1) + 9;
$y=1;
for ($i;$i<=$diasDelMes;$i++)
 { echo "<td>".$i."</td>";
  if (($y%7=="0") && ($i==$diasDelMes)) { }
  elseif (($y%7=="0") && ($i<$diasDelMes)) { echo "</tr>\n<tr>"; }
  $y++; 
  }
$y--;
$i--;
if (($y%7!="0") && ($i==$diasDelMes)) {
  $ultimoDiaMes=mktime(0,0,0,date("m",$_GET['fechaactual']), $diasDelMes,date("Y",$_GET['fechaactual']));
  $restoUltimaSemana= (date('w',$ultimoDiaMes) * -1) + 6;
  for  ($i=1;$i<=$restoUltimaSemana;$i++)
    { echo "<td></td>"; }
  }
echo "</tr>\n";
echo "</table>\n";


Aquí va la explicación del código:
  • La línea 1 abre la tabla. La etiqueta <table> queda rodeada por dos secuencias de caracteres de nueva línea (\n). De ahora en más, se verá varias veces, en las ocurrencias de código html, esta secuencia, con el solo fin de obtener un código más prolijo.
  • Con el código de la línea 2:
    • Se abre la primera fila (<tr>).
    • Se abre una celda de cabecera que ocupa 7 columnas de ancho (<th colspan='7'>).
    • Con la función date se obtiene el mes y el año ('F \d\e Y') de la fecha que se está consultando ($GET_['fechaactual']).
      Con la función traducir (anteriormente creada e incluida desde funciones.php) se traduce al español el nombre del mes.
      Con la función ucfirst se cambia la primera letra del mes a mayúsculas.
      Finalmente, se cierra la celda y la fila.
  • En la línea 3 se imprime el código html para crear la segunda fila, son sus 7 celdas de cabecera, con la primeras letras de cada día de la semana en cada una.
Al hacer una tabla con una semana por fila y siendo el domingo el primer día de la semana, un mes puede constar de 4 filas (solo en el caso de un mes de febrero no bisiesto cuyo primer día sea domingo), 5 filas (en una mayoría absoluta de los casos o de 6 filas).
  • La línea 4 abre la tercera fila (la primera fila -semana- del mes propiamente dicho).
  • En la línea 5 se define la variable $primerDiaMes, conteniendo el tiempo unix (mktime) del primer día ('1') del mes (date("m",$_GET['fechaactual'])) y año (date("Y",$_GET['fechaactual'])) seleccionados.
  • Las líneas 6 y 7 son un bucle for, que define un contador $i con valor "1", al que le va agregando uno ($i++) mientras $i sea menor o igual a date('w',$primerDiaMes) (o sea, el día de la semana correspondiente al primer día del mes, representado por "0" para el domingo, "1" para el lunes y así hasta "6" para el sábado). Por cada vez que la condición sea válida en el bucle, se imprime una celda vacía (<td></td>).
    O sea, si el primer día del mes es un domingo, el valor de date('w',$primerDiaMes) será "0" y como el contador $i comienza en "1", no se cumle la condición $i<=date('w',$primerDiaMes) y, por lo tanto, no se genera ninguna celda vacía.
    Por otra parte, si, por ejemplo, el primer día del mes es un jueves, el valor de date('w',$primerDiaMes) será "4" y como el contador $i comienza en "1", la condición $i<=date('w',$primerDiaMes) se dará 4 veces y, por ende, generará 4 celdas vacías (correspondientes al domingo, lunes, martes y miércoles de la primera semana).
  • En la línea 8 se define la variable $restoPrimeraSemana, cuyo conteniendo es el resultado de la resta 8-$i. El valor de esta variable se corresponderá con la cantidad de días en la primera semana del mes. Siguiendo con los ejemplos del punto anterior, si el primer día del mes es domingo, el valor de $i seguirá siendo "1", tal cual se definió en un principio, ya que la condición del bucle de la linea 6 no se cumplió y no le modificó el valor a $i. Entonces, el valor de $restoPrimeraSemana será "7" (el resultado de 8-1); esto es, la primera semana del mes tiene 7 días.
    Ahora, si el mes empieza en jueves, el valor de $i será "5" (ya que por cada una de las 4 veces que se cumplió la condición establecida en la línea 6, se le sumó "1" al valor original de $i) y el valor de $restoPrimeraSemana será "3" (el resultado de 8-5); o sea los tres días (jueves, viernes y sábado) que tendrá la primera semana del mes dado.
  • En las líneas 9 y 10 se define un nuevo bucle for, que define un contador $a con valor "1", al que le va agregando uno ($a++), mientras $a sea menor o igual a $restoPrimeraSemana (o sea, la cantidad de días de la primera semana del mes). Por cada vez que la condición sea válida en el bucle, se imprime una celda con el número correspondiente ("<td>".$a."</td>").
  • En la línea 11 se cierra la tercera fila (la de la primera semana, que se había abierto en la línea 4) con </td> y se abre la cuarte fila (la de la segunda semana) con <td>. Separados ambos por una secuencia de caracteres de nueva línea (\n), por el mismo motivo ya expuesto en la explilcación de la línea 1.
  • En la línea 12 se define la variable $diasDelMes que, mediante el uso de la función date con el carácter de formato 't', guarda el número de días del mes dado (en este caso el mes al que pertenece el tiempo unix almacenado en $primerDiaMes).
  • A continuación se necesita una variable que almacene el número del día del domingo con el que comienza la segunda semana del mes. Para ello, se utiliza el  valor previo de $i, que era:
    • "1" si el primer día del mes es domingo (en cuyo caso, el domingo siguiente, o sea, el primer día de la segunda semana, sería el "8").
    • "2" si el primer día del mes es lunes (entonces, el domingo siguiente es "7").
    • "3" si el primer día del mes es martes (entonces, el domingo siguiente es "6").
    • "4" si el primer día del mes es miércoles (entonces, el domingo siguiente es "5").
    • "5" si el primer día del mes es jueves (entonces, el domingo siguiente es "4").
    • "6" si el primer día del mes es viernes (entonces, el domingo siguiente es "3").
    • "7" si el primer día del mes es sábado (entonces el domingo siguiente es "2").
    Entonces, en la línea 13 se redefine el valor de $i, como el resultado de multiplicar el valor previo de $i por "-1" y sumarle "9" y obtener así el número del domingo con el que comienza la segunda semana.
  • En la línea 14 se define una variable $y con valor "1", para usar como una especie de contador en la línea 17.
  • Entre las líneas 15 y 20 se define un nuevo bucle for. En este caso, para el valor de $i definido en la línea 13, y mientras ese valor sea menor o igual a la cantidad de días del mes definidos en la línea 12 ($i<=$diasDelMes), le agrega "1" a $i.
    Lo primero que hace cuando se cumple la condición establecida es imprimir una celda con el valor de $i (línea 16).
    Luego, en la línea 17 verifica, con un if, si el valor de $y (el contador definido en la línea 14 y al que se le agrega "1" en la línea 19) es divisible entre 7 y si el valor de $i es IGUAL a $diasDelMes. Estas dos condiciones se cumplen sólo cuando el último día del mes es un sábado. Entonces, luego de ese último día se termina la tabla, sin necesidad de agregar celdas vacías. Así que, en caso que se cumplan las dos condiciones, no hace nada (por eso no hay nada entre los corchetes curvos).
    Si las condiciones de la línea 17 no se cumplen, en la línea 18, con un elseif verifica si el valor de $y es divisible entre 7 y si el valor de $i es MENOR a $diasDelMes. Estas dos condiciones sólo se cumplen cuando se llega a un sábado (el séptimo día de la semana, o sea, la séptima celda de la fila) que NO es el último día del mes. En caso que se den estas dos condiciones, imprime el cierre de esta fila y la apertura de la siguiente ("</tr>\n<tr>").
    Mientras no se den esas condiciones establecidas en las líneas 17 y 18, y mientras $i<=$diasDelMes seguirá imprimiendo celdas con el correspondiente número de día como muestra la línea 16 ("<td>".$i."</td>").
  • Con todo lo hecho hast a ahora, la tabla está prácticamente lista. Sólo falta crear las celdas vacías que sean necesarias para completar la última fila -semana- de la tabla. Para ello se utiliza un procedimiento análogo al utilizado para crear las celdas vacías en la primera semana del mes.
    Pero, primero, en las líneas 21 y 22 se le resta "1" a las variables $y y $i porque en los bucles que se las utilizó previamente se les sumaba 1 luego de verificar que se cumpliera la condición, por lo que ambas terminaron con el último valor utilizado +1.
  • En la línea 23 se verifica, con un if, si el valor de $y NO es divisible entre 7 y si el valor de $i es IGUAL a $diasDelMes. Estas dos condiciones se cumplen sólo cuando el último día del mes NO es un sábado. Por lo que sí es necesario agregar celdas vacías para completar la última fila. En caso que se cumplan las dos condiciones, se ejecuta el código de las líneas  24 a 27.
  • En la línea 24 se define la variable $ultimoDiaMes, conteniendo el tiempo unix (mktime) del último día ($diasDelMes) del mes (date("m",$_GET['fechaactual'])) y año (date("Y",$_GET['fechaactual'])) seleccionados.
  • En la línea 25 se define la variable $restoUltimaSemana que va a contener la candidad de celdas vacías que tiene que llevar la última fila. Para ello, con date('w',$ultimoDiaMes) obtiene un número que representa el día de la semana del último día del mes (representado por "0" para el domingo, "1" para el lunes y así hasta "6" para el sábado). A ese número, se lo multiplica por "-1" y se le suma "6". Y, por la misma razón expuesta en la explicación de la línea 13, se guarda la variable $restoUltimaSemana la candidad de celdas vacías que tiene que llevar la última fila. 
  • Las líneas 26 y 27 contienen el último bucle for, que define un contador $i con valor "1", al que le va agregando uno ($i++), mientras $i sea menor o igual a $restoUltimaSemana (o sea, la candidad de celdas vacías que tiene que llevar la última fila). Por cada vez que la condición sea válida en el bucle, se imprime una celda vacía ("<td></td>").
  • Por último, en la línea 29 se cierra la última fila ("</tr>") y en la 30 se cierra la tabla ("</table>").
Los cambios y agregados explicados en esta entrada dan como resultado la versión 0.2 de index.php, que, ejecutado el día de ayer, muestra lo siguiente en el navegador web:



Además, el código html5 generado por este script es válido, según http://html5.validator.nu/.

martes, 7 de febrero de 2012

Escribir código válido desde el principio

Antes de continuar agregando características al proyecto, y dado que ya cumple con la funcionalidad mínima indispensable para un calendario (mostrar la fecha del día y permitir cambiarse hacia otra), voy a incluir el código html necesario para generar código válido desde el principio.
Para ello, al script completado en la entrada anterior lo coloco rodeado de líneas de código html, como se ve a continuación:

<!DOCTYPE html>
<head>
<title>CLCPHP - Calandario Lit&uacute;rgio Cat&oacute;lico En PHP</title>
</head>
<body>
<?php
include("funciones.php");
if(!isset($_GET['fechaactual'])) {
$_GET['fechaactual']=time();}
$ayer=mktime(0,0,0,date("m",$_GET['fechaactual']), date("d",$_GET['fechaactual'])-1,date("Y",$_GET['fechaactual']));
$manana=mktime(0,0,0,date("m",$_GET['fechaactual']), date("d",$_GET['fechaactual'])+1,date("Y",$_GET['fechaactual']));
echo "<div style='text-align:center;'>";
echo "<h3>".traducir(date('l d \d\e F \d\e Y',$_GET['fechaactual']))."</h3>";
echo "<a href='index.php?fechaactual=".$ayer."'>&lt;&lt; D&iacute;a anterior</a> | ";
echo "<a href='index.php?fechaactual=".$manana."'>D&iacute;a posterior &gt;&gt;</a>";
echo "</div>";
?>
</body>
</html>

Luego, con el xampp corriendo, veo la página en un navegador web y, copio y pego el código que se genera (ver código fuente) en algún validador de html5, por ejemplo http://html5.validator.nu/.
Y el resultado es el siguiente:


sábado, 21 de enero de 2012

¡A navegar!

Con el script creado en la entrada anterior, sólo podemos saber la fecha del día de hoy, de ayer y de mañana.
Si quisiéramos hacer más "navegable" el script y que pudiéramos ir moviéndonos, de a un día, hacia adelante o atrás, podríamos escribir el siguiente script:

<?php
include("funciones.php");
if(!isset($_GET['fechaactual'])) {
$_GET['fechaactual']=time();}
$ayer=mktime(0,0,0,date("m",$_GET['fechaactual']), date("d",$_GET['fechaactual'])-1,date("Y",$_GET['fechaactual']));
$manana=mktime(0,0,0,date("m",$_GET['fechaactual']), date("d",$_GET['fechaactual'])+1,date("Y",$_GET['fechaactual']));
echo "<div style='text-align:center;'>";
echo "<h3>".traducir(date('l d \d\e F \d\e Y',$_GET['fechaactual']))."</h3>";
echo "<a href='index.php?fechaactual=".$ayer."'><< D&iacute;a anterior</a> | ";
echo "<a href='index.php?fechaactual=".$manana."'>D&iacute;a posterior>></a>";
echo "</div>";
?>


Ahora explico las líneas nuevas o diferentes con respecto al script de la entrada anterior:

  • En las líneas 3 agregué un if que pregunta si en la URL no (el signo ! indica negación) está definida (isset) la variable fechaactual
  • Si la respuesta el afirmativa, o sea, vía la URL no se recibió la variable fechaactual, entonces en la línea 4 defino dicha variable con el timestamp actual, o sea del momento en que se ejecuta el script.
  • Entre las líneas 5 y 6 definí las variables $ayer y $manana de forma similar a lo hecho en la entrada anterior, pero con el detalle que a cada ocurrencia de la función date le agregué el parámetro del timestamp guardado en  la variable fechaactual, de forma tal que $ayer y $manana hagan referencia al día actual guardado en  la variable fechaactual.
  • En la línea 8 también agregué a la  función date el parámetro del timestamp guardado en  la variable fechaactual, para que muestre la fecha seleccionada, formateada con la etiqueta <h3> .
  • En la línea 9 escribí un vínculo (etiqueta <a>) que llama a la misma página (index.php) pero agregándole un parámetro (después del signo ?) de nombre fechaactual con el contenido de la variable $ayer. De esta manera el vínculo apunta al día anterior al que se está mostrando.
  • Finalmente, la línea 10, hace básicamente lo mismo que la 9, pero el parámetro de nombre fechaactual contiene la variable $manana. De esta manera el vínculo apunta al día siguiente al que se está mostrando.

Lecturas recomendadas

sábado, 14 de enero de 2012

Mejor usar el español

El script creado en la entrada anterior devolvía las fechas del día actual, el anterior y el siguiente, pero tanto el día de la semana, como el mes, quedaban en inglés.
Para pasarlos al español se podría utilizar una función como la siguiente:

<?php
function traducir($fecha) {
if (strpos($fecha,"Monday")!==false) {
$fecha=preg_replace("/Monday/","Lunes",$fecha);
}
if (strpos($fecha,"Tuesday")!==false) {
$fecha=preg_replace("/Tuesday/","Martes",$fecha);
}
if (strpos($fecha,"Wednesday")!==false) {
$fecha=preg_replace("/Wednesday/","Miércoles",$fecha);
}
if (strpos($fecha,"Thursday")!==false) {
$fecha=preg_replace("/Thursday/","Jueves",$fecha);
}
if (strpos($fecha,"Friday")!==false) {
$fecha=preg_replace("/Friday/","Viernes",$fecha);
}
if (strpos($fecha,"Saturday")!==false) {
$fecha=preg_replace("/Saturday/","Sábado",$fecha);
}
if (strpos($fecha,"Sunday")!==false) {
$fecha=preg_replace("/Sunday/","Domingo",$fecha);
}
if (strpos($fecha,"January")!==false) {
$fecha=preg_replace("/January/","enero",$fecha);
}
if (strpos($fecha,"February")!==false) {
$fecha=preg_replace("/February/","febrero",$fecha);
}
if (strpos($fecha,"March")!==false) {
$fecha=preg_replace("/March/","marzo",$fecha);
}
if (strpos($fecha,"April")!==false) {
$fecha=preg_replace("/April/","abril",$fecha);
}
if (strpos($fecha,"May")!==false) {
$fecha=preg_replace("/May/","mayo",$fecha);
}
if (strpos($fecha,"June")!==false) {
$fecha=preg_replace("/June/","junio",$fecha);
}
if (strpos($fecha,"July")!==false) {
$fecha=preg_replace("/July/","julio",$fecha);
}
if (strpos($fecha,"August")!==false) {
$fecha=preg_replace("/August/","agosto",$fecha);
}
if (strpos($fecha,"September")!==false) {
$fecha=preg_replace("/September/","setiembre",$fecha);
}
if (strpos($fecha,"October")!==false) {
$fecha=preg_replace("/October/","octubre",$fecha);
}
if (strpos($fecha,"November")!==false) {
$fecha=preg_replace("/November/","noviembre",$fecha);
}
if (strpos($fecha,"December")!==false) {
$fecha=preg_replace("/December/","diciembre",$fecha);
}
return $fecha;
}
?>

Como se ve, el script precedente, declara una función de nombre traducir, a la que hay que pasarle un parámetro $fecha. Luego, busca con strpos, si en el contenido de $fecha está, por ejemplo, la palabra "Friday". En caso que la función no devuelva false, quiere decir que Friday sí está dentro de $fecha. Entonces, sustituye Friday por viernes con la función preg_replace. Y repite el mismo procedimiento con los nombres de los siete días de la semana y de los doce meses del año.
Para poder usar esta función se podría declararla dentro del mismo script de la entrada anterior o, mejor aún, declararlo en un script aparte y luego incluirlo. Para ello se debe guardar el script recién creado con un nombre, por ejemplo, funciones.php, y luego incluirlo en el script como se ve a continuación:

<?php
include("funciones.php");
$ayer=mktime(0,0,0,date("m"),date("d")-1,date("Y"));
$manana=mktime(0,0,0,date("m"),date("d")+1,date("Y"));
echo "<div style='text-align:center;'>";
echo "<h3>Hoy es ".traducir(date('l d \d\e F \d\e Y'))."</h3>";
echo "Ayer fue ".traducir(date('l d \d\e F \d\e Y',$ayer))."<br>";
echo "Ma&ntilde;ana ser&aacute; ".traducir(date('l d \d\e F \d\e Y',$manana))."</div>";
?>

Las diferencias con respecto al script de la entrada anterior son:

  • la inclusión (con la función include) del script funciones.php en la línea 2,
  • el llamado, o invocación, a la función traducir (declarada en el script funciones.php) en las líneas 6, 7 y 8.

Al ejecutar este script el 13 de enero de 2012, da el siguiente resultado:


Lecturas recomendadas

sábado, 7 de enero de 2012

¿Qué día fue ayer? ¿Y hoy? ¿Y mañana?

La función date() permite darle formato a una fecha u hora. Como parámetro de formato se le puede pasar más de una veintena de opciones. Por ejemplo, la "l" ("L" minúscula) muestra el día de la semana en texto completo. Opcionalmente se le puede pasar otro parámetro, el timestamp. En caso de no existir, toma el valor de time ().
Entonces, al ejecutar el siguiente script:
<?php
echo "Hoy es ".date("l");
?>
el viernes 6 de enero de 2012, el resultado sería:


Si se usa la función date() en combinación con la función mktime(), se pueden calcular fechas futuras o pasadas:

<?php
$ayer=mktime(0,0,0,date("m"),date("d")-1,date("Y"));
$manana=mktime(0,0,0,date("m"),date("d")+1,date("Y"));
echo "<div style='text-align:center;'>";
echo "<h3>Hoy es ".date('l d \d\e F \d\e Y')."</h3>";
echo "Ayer fue ".date('l d \d\e F \d\e Y',$ayer)."<br>";
echo "Ma&ntilde;ana ser&aacute; ".date('l d \d\e F \d\e Y',$manana)."</div>";
?>

Al ejecutar ese scritp el 6 de enero de 2012, el resultado es el siguiente:


Explico el script, línea por línea:
  1. Marca de apertura del script PHP
  2. Define la variable $ayer. La misma contiene la función mktime con los seis parámetros que recibe:
    1. hora
    2. minutos
    3. segundos
    4. mes
    5. día
    6. año
    Los tres primeros (hora, minutos, segundos) están en cero, pues no interesan para este script. Los demás llaman a la función date(), cada uno con un parámetro de formato distinto: "m" para el número del mes, "d" para el número del día y "Y" para el año con cuatro dígitos. Todos hacen referencia a la fecha en que se ejecuta el script, menos el día, ya que como dice date("d")-1, la variable $ayer guarda la información del día anterior al que se ejecuta el script.
  3. Es igual a la línea anterior, con la diferencia que como dice date("d")+1, la variable $manana guarda la información del día siguiente al que se ejecuta el script.
  4. Imprime en la pantalla una etiqueta HTML <div> para abrir una caja con un estilo en línea aplicado para que el texto que va a contener quede centrado.
  5. Imprime en la pantalla una etiqueta HTML de apertura de subtítulo <h3> y luego el texto Hoy es .
    Con el punto concatena el resultado de ejecutar la función date con los siguientes parámetros de formato:
    • l - para mostrar en forma textual en inglés el día de la semana.
    • d - para mostrar el número del día del mes.
    • \d\e - las barras invertidas son caracteres de escape, para conseguir que el caracter inmediatamente después de la barra no se procese y se muestre tal cual. Con esto se logra que en la pantalla se vea la palabra "de".
    • F - para mostrar el nombre del mes completo en inglés.
    • \d\e - lo mismo ya explicado dos líneas más arriba.
    • Y - para mostrar el año.
    Como no aplica un timestamp, usa el del momento en que se ejecuta el script
    Por último, concatena la etiqueta HTML de cierre del subtítulo </h3>.
  6. Hace algo muy similar a la línea anterior, pero, como le aplica un timestamp diferente, el resultado será otro. En este caso, el timestamp guardado en la variable $ayer que había sido definida en la línea 2.
  7. Lo mismo que la línea anterior, pero con la variable $manana definida en la línea 3.
  8. Marca de cierre del script PHP

Lecturas recomendadas

viernes, 30 de diciembre de 2011

Juegos con el tiempo (la función time())

La función time() devuelve, en tiempo unix,  la fecha del momento en que se ejecuta el script. El tiempo unix cuenta el tiempo, en segundos, a partir de las 0:00 horas (GMT) del 1 de enero de 1970 (algo más de un año antes de mi nacimiento).
Esto quiere decir que, el siguiente código php:

<?php
echo time ();
?>

devuelve, en el momento que estoy escribiendo esta entrada (23 de diciembre de 2011) lo siguiente:



Si a ese número, 1.324:641.094, lo guardamos en una variable, que llamaré $original, y con ella hacemos algunas divisiones, utilizando operadores aritméticos, podríamos convertir esa cantidad inimaginable de segundos, en algo más entendible:

<?php
$original=1324641094;
$uno=($original / 60);
$segundos=($original % 60);
$dos=($uno /  60);
$minutos=($uno % 60);
$tres=($dos / 24);
$horas=($dos % 24);
$cuatro=$tres-10;
$anios=floor($cuatro / 365);
$dias=($cuatro % 365);
$meses=floor($dias / 30);
$dias=($dias % 30);
echo $anios." a&ntilde;os, ".$meses." meses, ".$dias." d&iacute;as, ".$horas." horas, ".$minutos." minutos y ".$segundos." segundos.";
?>

El resultado de este script sería el siguiente:



Como ven, convierte esa cantidad de segundos transcurridos entre el 1 de enero de 1970 y el 23 de diciembre de 2011 en su equivalente en años, meses, días, etc.
Explico el script, línea por línea:
  1. Marca de apertura del script PHP
  2. Define la variable $original conteniendo el número 1324641094 que corresponde al total de segundos.
  3. Define la variable $uno conteniendo el resultado de dividir la variable $original entre 60, para obtener el total de minutos.
  4. Halla el resto de la división de la línea anterior, o sea los segundos que "sobran" y no completan el minuto. Este valor lo guarda en la variable $segundos, una de las que se va a imprimir en la línea 14.
  5. Define la variable $dos como el resultado de dividir $uno (el total de minutos) entre 60 para obtener el total de horas.
  6. Halla el resto de la división de la línea anterior, o sea los minutos que "sobran" y no completan la hora. Este valor lo guarda en la variable $minutos, otra de las que se va a imprimir en la línea 14.
  7. Define la variable $tres como el resultado de dividir $dos (el total de horas) entre 24 para obtener el total de días.
  8. Halla el resto de la división de la línea anterior, o sea las horas que "sobran" y no completan el día. Este valor lo guarda en la variable $horas, otra más de las que se van a imprimir en  la línea 14.
  9. Desde 1970 hasta la fecha, han habido 10 años bisiestos, o sea de 366 días. Así que para la operación a realizarse en la línea siguiente es necesario quitar de los días totales ($tres) esos 10 días (para poder considerar todos los años iguales, de 365 días). El resultado de esta resta se guarda en la variable $cuatro. Para usar este script a partir del 29 de febrero de 2012, serán 11 los años bisiestos, por lo que la resta el sustraendo pasará a ser 11.
  10. Define la variable $anios, como el resultado de dividir $cuatro (el total de días, menos los 29 de febrero) entre 365.
    La función floor redondea el resultado hacia abajo, ignorando los números después de la coma en el resultado de la división. Esta variable $anios, es una de las que se imprimen en la línea 14.
  11. Halla el resto de dividir $cuatro (la cantidad de días totales, menos los 10 días "extras" de los años bisiestos) entre 365 y guarda el resultado, o sea los días que "sobran" y no completan un año, en la variable $dias.
  12. Define la variable $meses, como el resultado de dividir $dias (los días "sobrantes") entre 30 (*).
    La función floor redondea el resultado hacia abajo, ignorando los números después de la coma en el resultado de la división. Esta variable $meses, es una de las que se imprimen en la línea 14.
  13. Halla el resto de la división de la línea anterior, o sea, los días que "sobran" y no completan el mes. Este valor lo guarda en la variable $dias, y le sobrescribe el valor que tenia previamente. Esta es la última de las variables que se van a imprimir en la línea 14.
  14. Finalmente, con echo, se procede a imprimir en la pantalla los contenidos de las variables evocadas y  concatenados con los textos que se muestran entre comillas, para dar el resultado que se ve en la captura de pantalla anterior.
  15. Marca de cierre del script PHP

El mismo resultado se obtendría escribiendo menos líneas, de la siguiente manera:

<?php
$original=1324641094;
$segundos=($original % 60);
$minutos=(($original / 60) % 60);
$horas=((($original / 60)/  60) % 24);
$anios=floor((((($original / 60)/  60) / 24)-10) / 365);
$meses=floor(((((($original / 60)/  60) / 24)-10) % 365)/ 30);
$dias=(((((($original / 60)/  60) / 24)-10) % 365) % 30);
echo $anios." a&ntilde;os, ".$meses." meses, ".$dias." d&iacute;as, ".$horas." horas, ".$minutos." minutos y ".$segundos." segundos.";
?>

Estos dos scripts devuelven siempre el mismo resultado, ya que parten de una variable  con contenido fijo. Si se modifica la línea en la que se define la primera varible (o sea $original=1324641094;) por $original=time(); el resultado del script es distinto cada vez que se ejecuta (ya que el contenido de $original cambiaría cada segundo). Hagan la prueba.

(*) El resultado no es exacto, ya que  se consideraron todos los meses como de 30 días.
Para obtener un resultado exacto (aunque sin horas, ni minutos, ni segundos),  se podría utilizar un script de Webtutoriales.com que, levemente modificado, da el siguiente resultado:


Las pequeñas modificaciones que le hice al código original son, por ejemplo, ingresarle las fechas que me interesan para este ejemplo (01/01/1970 y  23/11/2011) y cambiar la forma que se muestran los datos que devuelve el script para que se mostraran de forma similar a los scripts anteriores.

Como pueden ver, el error del script que hice yo a lo "bruto" es de unos 4 días con respecto al correcto script de Webtutoriales.com.