Comparto esta idea con ustedes, por si a alguien le es útil (y de paso, por qué no, si alguien tiene una solución más elegante a mano y me ilumina).
Me han pedido (entre otras cosas) hallar cuántos de los trabajadores almacenados en una base de datos (PostgreSQL, por más señas) son menores de 40 años. Si voy a programar en PHP, que es lo que usamos acá, disponiendo de la fecha de nacimiento y conociendo la fecha corriente, se puede hallar la diferencia en años, meses y días usando soluciones como esta: $fecha1=new DateTime(primerafecha); $fecha2=new DateTime(segundafecha); $intervalo=$fecha2-> diff ($fecha1); $cinterv=$intervalo->format(‘%Y-%m-%d’); $c=split(“-“,$cinterv); $cdias=$c[2]; $cmeses=$c[1]; $canos=$c[0]; Donde $cdias, $cmeses y $canos son respectivamente las cantidades de días, meses y años entra las dos fechas. Lo interesante es que en esa base no se han almacenado la fechas de nacimiento, sino solamente el número del carnet de identidad. Esto complica el cuadro. Veamos: en el número del carnet de identidad los primeros 6 dígitos indican año, mes y día. Desconozco si alguno de los siguientes dígitos apunta inequívocamente a la fecha, así que debo basarme solamente en el dato de estos primeros 6. Por ejemplo, 551002 indica 1955 (no inequívocamente, si me baso solo en eso), el 10 señala a octubre y el 02 denota el día 2. El año se toma como 1955; ello es en el entendido de que el 55 inicial no se va a referir a 2055, que no hemos llegado todavía a esa fecha. Una solución “quick and dirty” (rápida y sucia) para determinar los menores de 40 pudiera ser: (Pongo solo la parte relevante del código) $jaro=round(date(‘Y’),0); $monato=round(date(‘m’),0); $tago=round(date(‘d’),0); $datos=pg_query($mibase,”select nombre as nombre,ape1 as ape1,nivel as nivel,ci as ci into talla_joven_fumero from datosgenerales where baja=’f’ and numero<5000 and (numero>8999 or numero<9700) and (($jaro -(1900+((substr(ci,1,2))::numeric))<40) or ($jaro -(1900 +((substr(ci,1,2))::numeric))=40 and (substr(ci,3,2)::numeric)>$monato) or ($jaro -(1900+((substr(ci,1,2))::numeric))=40 and (substr(ci,3,2)::numeric)=$monato and (substr(ci,5,2)::numeric)>$tago) ) order by ci”); El query $datos extrae el nombre, los dos apellidos, el nivel de escolaridad y el número de carnet de identidad de los trabajadores menores de 40 años desde una supuesta base datosgenerales e inserta los datos en otra, temporal, llamada talla_joven_fumero. Una vez que los tengo ahí, puedo determinar otras cosas que me piden (sexo, nivel de escolaridad) y que ahora no interesan. Explicando un poco: de la fecha actual (que la da la función date) extraigo año, mes y día porque me harán falta en el query. Redondeo para obtener valores enteros. Es imprescindible que el trabajador no haya sido baja (hay que guardar los datos de las bajas durante un tiempo), por tanto se requiere que el campo “baja”, que es booleano, tenga valor FALSE. El rejuego con el rango de números de trabajador se debe a que algunos rangos están destinados a otros menesteres. El número de identidad está almacenado como texto, de modo que al analizarlo le pedimos al PostgreSQL que cuando extraiga la subcadenas correspondientes al año, mes y día interprete el dato extraído como numérico, para poder sacar la cuenta. La especificación order by hace que el resultado que se inserta en la tabla temporal sea ordenado de mayor edad a menor edad. Ahora bien, esta solución exige varias suposiciones de partida. Debo conocer la fecha corriente (obvio) y en la cuenta sumo 1900 porque estoy asumiendo que si la edad mínima para trabajador son 17 años, aún no tengo en nómina trabajadores nacidos a partir del 2000. También asumo, obviamente, que ninguno de nuestros trabajadores nació en el siglo XIX… Entonces debo razonar que cuando pasen unos años no podré programar tan alegremente; en cuanto tenga el primer trabajador nacido a partir del 2000 ya no se podrá sumar siempre 1900 a los dos primeros dígitos del número del carnet de identidad, pues si bien es verdad que resultaría difícil asumir que una persona de 100 años se mantiene trabajando, ello no es imposible. .. tengo una vecina de 103 años muy coherente, que aún cose… Pero bueno. Debo asumir que a esas edades ya no está en nómina, o esto se complica. Así que una solución más completa, que no caduque en pocos años, debería razonar algo como esto: para fechas de cuatro dígitos (no espero vivir para ver las de 5, así que no me esfuerzo más), si los dos primeros dígitos del número de carnet de identidad son menores que los dos últimos dígitos del año corriente, le sumo los dos primeros dígitos del año corriente, terminando con 00 y convertido en número para hacer la cuenta; si no es así, o sea, son mayores, le resto una unidad a los primeros dos dígitos del año corriente, le empato al final 00 y lo convierto a número para hacer la suma. Si se les ocurre una solución mejor, ya saben donde escribirme… -- M.Sc. Alberto García Fumero Usuario Linux 97 138, registrado 10/12/1998 http://interese.cubava.cu Una conclusión es el punto en que usted se cansó de pensar. ______________________________________________________________________ Lista de correos del Grupo de Usuarios de Tecnologías Libres de Cuba. Gutl-l@jovenclub.cu https://listas.jovenclub.cu/cgi-bin/mailman/listinfo/gutl-l