Cuidado al usar Zend_Date

Categoría (PHP, Trabajo) by admin on 30-01-2010

Etiquetas : , , ,

En un proyecto, estaba utilizando Zend_Date para manejo de horas en diferentes zonas horarias, cuando lo estaba desarrollando empecé a tener un error porque olvidé que la fecha se actualiza cuando cambias un parámetro y el problema surge cuando cambias el mes o día y se encuentra con una fecha inexistente aunque en el código parezca correcta, por ejemplo, supongamos que estamos en el mes de febrero y queremos crear una fecha de marzo (asignaré la fecha para reproducir el error, aunque el error es cuando se utiliza la fecha actual)

include_once("Zend/Date.php");
$fecha_febrero = mktime(0, 0, 0, 2, 1, 2010);
$fecha = new Zend_Date($fecha_febrero);
$fecha->setDay(31);
$fecha->setMonth(3);
print "Fecha Marzo: ".date("d/m/Y", $fecha->getTimestamp());

Uno esperaría que el resultado fuera: 31/03/2010

Pero en su lugar mostrará 03/03/2010

Esto es porque al hacer $fecha->setDay(31) el sistema intenta crear la fecha: 31/02/2010 que no existe, por lo que “recorre” los días restantes para quedar en 03/03/2010, al asignar el mes, no tiene efecto.

La solución es simplemente hacerlo en orden inverso:

include_once("Zend/Date.php");
$fecha_febrero = mktime(0, 0, 0, 2, 1, 2010);
$fecha = new Zend_Date($fecha_febrero);
$fecha->setMonth(3);
$fecha->setDay(31);
print "Fecha Marzo: ".date("d/m/Y", $fecha->getTimestamp());

Eso parecería la solución ideal (y es la recomendada por la documentación), pero no es totalmente cierta, si por ejemplo estamos en enero 31 del 2010 e intentamos asignar una fecha de febrero, siempre obtendremos una fecha de marzo:

include_once 'Zend/Date.php';
$fecha_enero = mktime(0, 0, 0, 1, 31, 2010);
$fecha = new Zend_Date($fecha_enero);
$fecha->setMonth(2);
$fecha->setDay(10);
print "Fecha Febrero: ".date("d/m/Y", $fecha->getTimestamp());

Uno esperaría que mostrara la fecha:
10/02/2010

Pero en realidad muestra
10/03/2010

Esto porque cuando asignamos el mes, el sistema intenta crear la fecha 31/03/2010 que una vez más es incorrecta, por lo que crea la fecha 03/03/2010, pero al asignar la fecha, el resultado es un error en el mes.

Aunque esto no es un error, es muy peligroso porque uno puede suponer que la fecha es correcta porque…

Una hora perdida

Categoría (Trabajo) by admin on 25-11-2009

Etiquetas : , , ,

Mientras estaba haciendo un pequeño calendario que mostrara fechas con ligas a otras parte del sitio, pensé que la manera más fácil era evitar llamar a strototime:

strtotime("+1 days", $time)

y en su lugar utilizar directamente la suma de 86,400 segundos que es un día:

60 * 60 segundos = 3600 segundos (1 hora) * 24 = 86400

El calendario no tenía ningún problema hasta que noté que tenía repetido dos veces el día 1º de noviembre, los tiempos eran los siguientes (tiempo Unix):

1257051600: 2009-11-01 00:00:00
1257138000: 2009-11-01 23:00:00

Si hacen la suma, observarán que se sumó 86,400 segundos a una fecha y otra; pero el tiempo regresado por PHP (de hecho por el sistema Linux) es de 23 horas y no 24 horas.

Hice algunas pruebas en otros servidores y solo uno imprimió la fecha que esperaba (2009-11-02 00:00:00), la primera idea (por el cansancio) fue que era un error de PHP/Linux. Buscando un posible error, encontré algunas preguntas que como yo habían tenido un problema similar, pero mencionaban algo de la zona horaria, eso me recordó que el 1º de Noviembre en México atrasamos el reloj una hora por lo que en realidad el cálculo era correcto desde la perspectiva de Linux ya que estaba olvidando esa “hora perdida” en mis cálculos, el servidor que regresó bien la fecha estaba en otra zona horaria por lo que no compartían nuestro cambio de horario.

El tiempo Unix correcto es: 1257141600 no es otra cosa que es el día (86400) más la hora “perdida” (3600), este tiempo lo obtuve llamando a strtotime en PHP en lugar de calcularlo por mi cuenta.

Moraleja: Manipular el tiempo Unix de forma directa agregando valores puede ser muy rápido y simplifica la implementación, pero si quieres hacer algo que no tenga errores utiliza siempre las funciones de tiempo de PHP/Linux.

Tip Rápido: Completación de código en Zend Studio

Categoría (PHP) by admin on 31-03-2009

Etiquetas : ,

Uso mucho el Zend Studio, aunque la primera versión fue desastrosa a partir de la 6.0.1 se han esmerado muchísimo; lo único malo que me he topado es que al hacer un proyecto Zend Framework se vuelve terriblemente lento y que tiene un poco de código extra poco necesario en su plantilla; aunque la ventaja es que ya trae ejemplos de Unit Test Case para los modelos (falta probarlos a detalle =P)

Usualmente al construir mis clases no pongo mucha documentación por función, por tanto Zend Studio no puede “determinar” qué tipo de variable regresa esa función. 

Para facilitar esto, lo que hago es simplemente agregar este pedazo de código:

    /**
     * @return Zend_Db_Adapter_Abstract
     */
	public static function getDB() {
             /* ... aqui va el código */
         }
 

Básicamente es el snippet de código para documentación pero usando solamente el tipo de objeto que regresa la función.
Con esto cuando utilices la función, Zend Studio podrá fácilmente mostrarte las propiedades y métodos del objeto.

TinyURL API – Snippet

Categoría (PHP) by admin on 23-03-2009

Etiquetas : ,

Aqui hay un snippet (pedazo de código) para utilizar el API de TinyURL (TinyAPI ;) ), básicamente es llamar a la siguiente dirección:

http://tinyurl.com/api-create.php?url= 

y agregar al final la URL que queremos “achicar” con TinyURL, la página regresará como único contenido la URL nueva, por ejemplo:
http://tinyurl.com/api-create.php?url=http://vida.danguer.com

Da como resultado:
http://tinyurl.com/dfz9c3

El snippet para PHP es el siguiente: 

function get_tinyurl($url) {
     $url = "http://tinyurl.com/api-create.php?url=".urlencode($url);
     return trim(file_get_contents($url));
}

 

Demasiado facil, no? solamente hay que invocarlo como:

get_tinyurl('http://vida.danguer.com')

y obtendremos la nueva URL.

Dumpear todas las bases de datos

Categoría (Trabajo) by admin on 19-02-2009

Etiquetas : ,

Recientemente tuve que “dumpear” todas las bases de datos de un servidor por lo que utilice un script muy simple para hacerlo:

USER=root;PASS=mi_pass;for database in `echo "SHOW DATABASES" | mysql --user=$USER --password=$PASS | sed '1d'`; do mysqldump --user=$USER --password=$PASS $database > $database.sql; tar jcvf $database.tar.bz2 $database.sql; rm $database.sql; done

Un poco más leible:

USER=root
PASS=mi_pass
for database in `echo "SHOW DATABASES" | mysql --user=$USER --password=$PASS | sed '1d'`
do
    mysqldump --user=$USER --password=$PASS $database > $database.sql
    tar jcvf $database.tar.bz2 $database.sql
    rm $database.sql
done

Básicamente manda todas las bases de datos y quita la linea inicial (que siempre es Databases) y por cada base de datos invoca mysqldump y por último lo comprime con bunzip2 para obtener un archivo muy pequeño y por supuesto elimina las “fuentes” de sql.

Auto inicio de dominios en Xen

Categoría (Linux, Trabajo) by admin on 09-01-2009

Etiquetas : ,

Algo muy útil es iniciar/apagar automáticamente dominios XEN cuando se reinicia o apaga el anfitrión (dom0), cuando se instala XEN, por defecto deberemos ver creado un directorio llamado /etc/xen/auto

En este directorio el script /etc/init.d/xendomains buscará las configuraciones de las máquinas virtuales a iniciar/detener estos pueden ser vínculos simbólicos a las verdaderas configuraciones.

Para que todo esto suceda en primer lugar debes de tener el script /etc/init.d/xendomains que se instala junto con /etc/init.d/xend

También debes haber habilitado el inicio de este script con el siguiente comando:

update-rc.d xendomains defaults 21 20

 
El script /etc/init.d/xendomains necesita del archivo de configuración: /etc/sysconfig/xendomains

En este verás una línea que contiene:

XENDOMAINS_AUTO=/etc/xen/auto

Con esto definimos el directorio donde se buscarán los dominios que se auto iniciarán

Obtener video FLV de YouTube

Categoría (PHP) by admin on 09-01-2009

Etiquetas : , ,

Esta es la nueva manera de obtener el video de YouTube, los parámetros para get_video.php quedan iguales (video_id y t), pero t cambia y ahora no se obtiene al cargar el video, se tiene que llamar a otra URL para obtener esa información.

El método es muy fácil, los pasos son:

  1. Llamar a: 
    http://www.youtube.com/get_video_info.php?video_id=VIDEOID
    Donde VIDEOID es el id del video que vamos a obtener el archivo FLV (las ligas de YouTube para ver el video son como: http://www.youtube.com/v/VIDEOID)
    Tomaremos por ejemplo este:
    http://www.youtube.com/get_video_info.php?video_id=HDi9OeJqwG4 
  2. El resultado será en texto y tendrá muchas variables como:
    status=ok&title=Rob+Dougan+-+Furious+Angels&muted=0&avg_rating=4.8496592845&creator=eitch&length_seconds=237&vq=None&fmt_map=&token=OEgsToPDskKxBcum6P4BEStM-z3qkYZW&thumbnail_url=http%3A%2F%2Fi1.ytimg.com%2Fvi%2FHDi9OeJqwG4%2Fdefault.jpg&allow_ratings=True&plid=AARgErHUJPLX2RPWAAAAoABoIAE&track_embed=1
  3. De aqui solamente necesitamos obtener el parámetro token y pasarlo al ya conocido get_video.php:
    http://www.youtube.com/get_video.php?video_id=HDi9OeJqwG4&t=OEgsToPDskKxBcum6P4BEStM-z3qkYZW

Con esto ya obtendremos el FLV deseado, en PHP la rutina sería la siguiente:

<?php
//video id por defecto
$video_id = 'HDi9OeJqwG4';

if (isset($_REQUEST['video_id']))
        $video_id = trim($_REQUEST['video_id']);

//obtener informacion
$url_info = 'http://www.youtube.com/get_video_info.php?video_id='.$video_id;
$info = file_get_contents($url_info);

$vars = array();
parse_str($info, $vars);

$url_flv = 'http://www.youtube.com/get_video.php?video_id='.$video_id.'&t='.$var
s['token'];

print 'Archivo FLV: '.$url_flv;
?>

Con esto obtenemos la URL del archivo FLV.

Es importante notar que en Flex/Flash no se podrá cargar diréctamente get_video_info.php por la política del crossdomain de YouTube así que hay que utilizar un proxy.

El demo lo pueden probar desde:
http://demo.livesourcing.com/blog_vida/articulos/DanguerArticle_Youtube/?video_id=VIDEOID
Donde VIDEOID es el id del video de YouTube de su preferencia =)

El código fuente lo pueden descargar de:
http://demo.livesourcing.com/blog_vida/articulos/DanguerArticle_Youtube.tar.gz
 

 

 

 

Preguntas a ayudantes de Reyes Magos

Categoría (Vida) by admin on 07-01-2009

Etiquetas : ,

Estas son algunas de las preguntas que les hacen a los ayudantes de Reyes Mago (yo por ejemplo :P ) al vender juguetes

  • ¿Esta muñeca es de carne y hueso?
    Para referirse a muñecas “tipo Barbie” y que muevan las extremidades, pero dan ganas de decirle que “si, las compramos a unos reductores de cuerpo de África”
  •  Después de que enseñas un juguete que tiene luces, se mueve y hace sonidos no falta el que te pregunta inocentemente: ¿Usa pilas?
    No que va,  es un organismo carbónico que fue diseñado genéticamente para realizar ese comportamiento, hay granjas de estos seres
  • Después de mostrar un juguete que hace las mil maravillas (se mueve, “esquiva obstáculos”, tiene sonido, luces, a veces salta, control remoto, etc, etc, etc) te llegan a preguntar: ¿Solamente eso hace?
    Para responder: “Si también plancha la ropa, pasea al perro, navega por internet, y todo lo que necesites”
  • Cuando enseñas helicópteros o aviones cuyo costo es menor a los 100 pesos, te preguntan: ¿Y no vuelan?….  Si claro puede llevar 10 pasajeros y hacer viajes internacionales

Pero no sólo se limita a eso, en la tienda de mis padres una vez preguntaron: “¿Y si contiene todos los países?” refiriéndose a un globo terráqueo sacapuntas de 10 pesos y de unos 10 centímetros de diámetro.

 

Tip: Usando rsync para transferencias rápidas entre linux

Categoría (Trabajo) by admin on 26-11-2008

Etiquetas : , ,

Usualmente uso el famosímo scp para transferir archivos, el problema es que al parecer scp es muy lento cuando se trata de muchos archivos pequeños. 

rsync es un comando para hacer réplicas de un directorio a otro lugar, lo que hace es checar el comparar los directorios y copiar todos los archivos que hayan sido modificados, que sean nuevos o incluso que hayan sido elminados para hacer una copia exacta.

La gran ventaja de rsync es que aparte de crear una réplica, es sorprendentemente rápido, en especial con archivos pequeños.

El uso es muy simple:

rsync -az -e ssh FUENTE usuario@servidor:DESTINO

Eso es todo, para que funcione ambos servidores deben tener el programa rsync instalado, FUENTE es el directorio local a copiar (o puede ser un archivo), DESTINO es el directorio del servidor remoto a donde se copiará.

La opción -az envia la información compresa y -e ssh indica que hay que usar el programa ssh para transferir los archivos (con esto se puede enviar también mediante ftp, etc)

Otra opción que uso mucho es --delete, de esta manera rsync también borrará los archivos “extra” para que la copia sea exacta. Hay que tener cuidado, porque en algo descuidado se pueden borrar los archivos locales (inversión de parámetros)… algo que me pasó una vez, pero tenía respaldo =).

 

 

Eso pasa por no darle navidad a su cartero

Categoría (Vida) by admin on 24-11-2008

Etiquetas : , ,

Es de todos sabido que el grandioso servicio postal mexicano es muuuuy lento, lamentablemente muchas veces no lo puedes evitar, a mi me llegan revistas de ACM y otras subscripciones por este medio.

Hay veces que quisiera contratar otras subscripciones (de revistas de Estados Unidos principalmente) pero la verdad es que llegan con algunos meses de atraso (un mes despúes se puede considerar como que se esmeraron) y llegan dos de tres o una de dos =(

Pues la semana pasada tocaron a la casa y cuando pregunté, me dijeron “correo”, me dije internamente; caray pues tal vez quieren que firme algo. Cuando estaba por abrir recordé que en esos días era el “día del cartero” y dije, seguramente me van a pedir “aguinaldo”

Como buen profeta, para eso me estaba esperando, y para entregarme un recibo de telmex (para que no se viera tan “interesado”). Saludo muy cordial y sin hablar mucho me dice: “lo molesto con lo de la bonificación”. Me dije internamente “y eso que es ‘voluntaria’”, le di algo del cambio que tenía (no mucho, no poco ;) ) y se fue.

Lo bueno ha sido que en esta semana han llegado muchísima correspondencia, de hecho me acaba de llegar una revista de ACM de Noviembre, antes de cumplir un mes de enviada >=), realmente eso es sorprendente, espero que el cartero no se olvide que le di bonificación para que al menos un par de meses no se me pierda o retrase la correspondencia =).

Por cierto el título es de un capítulo de los Simpsons (Mama Simpson) donde pasa algo similar ;)