Cambiar colores de un JComboBox

En el foro de java preguntaron solog java swingbre cómo cambiar los colores de un JComboBox. El asunto no era sencillo, buscando por google, encontré este enlace que es lo que respondí en el foro. Sin embargo no me convenció, me parecía demasiado complejo. Sobre todo no me gustaba el comentario «Es obligatorio que el Editable sea verdadero, de lo contrario, las modificaciones del renderizador y del editor no funcionarán».

Así que me puse a hacer pruebas por mi cuenta a ver si existía una forma de cambiar los colores de manera más sencilla. Y la hay, no fue fácil, pero conseguí hacerlo … con pegas, al final tuve que tirar del editable.

La parte del desplegable es fácil, es similar a un JList normal. De hecho, se cambia definiendo tu propio BasicComboBoxRenderer y sobreescribiendo un método igual que el de un ListCellRenderer

Pero el valor visible cuando el menú desplegable está oculto, eso es otro cantar. Casi todos los intentos y búsquedas en google fracasaban o me daban soluciones complejas, como la que quería evitar.

Pero enconré una forma, no fue fácil porque al final tuve que ir al código java, localizar dónde se hacía el dibujo de ese valor seleccionado y mirar la lógica. La clase  que hace el dibujo es BasicComboBoxUI propia de java y el método es paintCurrentValue(). Te pego aquí una foto con el trozo del código de interés

codigo de BasicComboBoxUI

La lógica de todo esto:

  1. Si el JComboBox tiene el foco y el desplegable no es visible, se usa el render que hayamos definido. Fíjate que se le pasa como posción en la lista un -1. Así que este caso podemos contemplarlo en el render que hayamos hecho para el desplegable.
  2. En caso contrario, lo mismo pero … se machaca el color del background con el valor por defecto del look and feel que tengamos. Así que en caso de que el JComboBox no tenga el foco o el desplegable esté visible, no nos hará ni caso al color de background que pongamos en el render. Vete tú a saber por qué han tomado esta decisión al hacer el código.
  3. En el punto 1 dijimos que no tendriamos problemas con el render. Pues si los tenemos, si vas al siguiente bloque de código, se vuelve a repetir la condición de si el JComboBox tiene el foco y el desplegable no es visible para cambiar el color usando los colores de selección de listBox, es decir, el Jlist. Así que en nuestro render, si nos pasan -1 como posición, debemos cambiar los colores de selección del JList que nos pasan como parámetro.
  4. Y el else de ese bloque, es decir, si el JComboBox no tiene el foco o el desplegable es visible, nos metemos en nuevo if-else, en función de si el combo esta enabled o disabled.
    1. En el primer caso, se usan los colores de defecto del JComboBox. Así que para este caso, tenemos que tener cambiados los colores de defecto.
    2. Y para el otro caso, combo disabled, hace una extrañas llamadas a DefaultLookup que tras mirar, no he visto forma fácil de meter mano. Acaban devolviendo colores por defecto. Así que la solución pasa por hacer una chapuza, justo la que quería evitar. Cuando deshabilitemos el combo, lo hacemos editable. El color del editor se puede cambiar fácilmente y como está deshabilitado, el usuario no podrá editar nada.

Me llama la atención lo complejo que han hecho esto los de java.

El código resultante de toda esta investigación está explicado en Cómo cambiar los colores de  un JComboBox.

 

 

Publicado en java | Etiquetado , , , | Deja un comentario

Jugando con Chat-GPT y Chat Bing

ChatGPT - Wikipedia, la enciclopedia libreCuando apareció todo esto de Chat-GPT y posteriormente, chat bing, no les hice mucho caso.

Por un lado, estaba un poco decepcionado con todas estas nuevas tecnologías de machine learning, deep learning y demás. Como está de moda desde hace ya bastantes años y en todos los ámbitos, parece que las cosas mejoran más poniéndoles nombres bonitos que haciendo cosas reales por debajo.

Por otro, ambas herramientas exigen que te registres y en el caso de Chat-GPT incluso que le des tu número de móvil. Así que directamente pasé de probarlo.

Pero un compi de trabajo estuvo probándolo y me habló maravillas, así que me decidí a jugar y al final, una sensación agridulce.

Tras estar de charla con los chat, e incluso echando alguna mañana entera, me dejó bastante asombrado. Fuí a pillar, le pregunté por los sistemas VTS (Vessel Traffic Service) y en concreto, por iMARE, en el que trabajo en mi empresa. Lo conoce. Le pregunté por programación en Java, a mala leche, pidiéndole que usara la librería de Luciad Lightspeed, que también uso. Es una librería de pago de la que no hay demasiada info en internet. La conoce e incluso hace código usándola. E intenté que me explicara la mecánica cuántica de forma que yo la entendiera, eso no fue capaz, prueba clara de que soy muy «zote».

Y tras quedarme asombrado, busqué por google / youtube a ver si alguien me contaba las tripas de chat-gpt y me encontré este video

Y me llevé un chasco y a la vez me dejó más dudas. El video está bien explicado y cuenta cómo se entrenó y la algorítimica en que se basa chat-gpt. Si lo resumimos, dice que chat-gpt únicamente continua una conversación poniendo a continuación las palabras/frases que estadísticamente quedan mejor.

Así que el algoritmo, aunque implementado de una forma muy elaborada, es bien tonto, simple estadística de palabras y frases. Pero el resultado es asombroso. Cuando le pido que me haga un programa Java y mete la pata en algo, se lo comento y lo corrige, mejor o peor, pero lo corrige. Realmente asombroso si el algoritmo realmente es sólo lo que comenta el video. Por otro lado, si le digo que de un listado de protocolos militares de comunicación entre sistemas de mando y control, me da un listado de algunos de ellos (link 16, JTIDS/MIDS, etc) pero también me incluye el protocolo de vestimenta militar y de izado de bandera en determinados eventos. Esto sí que cuadra con un algoritmo que pone frases «aleatorias» cercanas a «protocolos militares».

Pero sí les he encontrado utilidad, aunque haya que verificar lo que te contestan.

chat bing es muy bueno para resumirte búsquedas de internet. Le preguntas algo que quieras saber y que habitualmente requiera algo de investigación por google y él te hace las búsquedas, te da un resumen y te pone enlaces. Puedes pedirle que vaya ampliando información. He estado una mañana con él discutiendo sobre las gas fee de los intercambios de criptomonedas.

chat-gpt sin embargo me parece mejor para escribir artículos o pedirle que te escriba textos o frases, parece que tiene más «inventiva» y es más extenso en sus explicaciones. De hecho, hay tres tutoriales de chuwiki escritos enteramente por chat-gpt: JSliderJColorChooser y XML+XSLT=HTML.

Y ambos son útiles para pedirles ayuda en cuanto a programación se refiere, ya que dan código y lo corrigen si se lo indicas. O incluso para traducirte textos entre idiomas, lo hace bastante mejor que google translator.

Por cierto, hablando de generar código con herramientas, un compi de trabajo me enseñó codegeex. Tiene plugin para IntelliJ idea y lo he estado probando. No me convenció mucho. Genera código, sí, a veces muy acertado rellenándote por completo un método simplemente poniendo el comentario de lo que quieres que haga, pero otras veces parece que molesta más que ayuda.

Publicado en machine learning | Etiquetado , , , | Deja un comentario

Moviendo dominios y subdominios

logo de ezoicGoogle Adsense da unos ingresos bastantes bajos en general, así que buscando alternativas, me dí de alta en Ezoic. Según vídeos de youtube y artículos varios, parece que en general da bastante más ingresos. Siempre hay detractores, comentan que el que no obtiene buenos ingresos en Google Adsense es porque no sabe configurar/colocar bien los anuncios, mientras que Ezoic es más «listo» y por tanto, más para «tontos». Ezoic o personal de Ezoic se encargan de poner los mejores anuncios o indicarte dónde ponerlos.

Para que Ezoic apruebe tu dominio, primero tiene que aprobarlo Google Adsense. No es necesario tener cuenta de Google Adsense, pero si pasa por las manos de google la validación. Y curiosamente, aunque mi sitio fue validado por adsense hace ya muchos años, no lo ha validado para Ezoic. Así que no puedo usar Ezoic de momento.

El motivo, es algo como «contenido de poco valor». Eso es muy amplio y la ayuda de Ezoic comenta muchas posibilidades. Desde una web con contenido cutre hasta cosas tan tontas como tener mal colocados los menús, siendo mal colocados que a la gente de google no les guste como están colocados.

Me entró la duda si estaban mirando el contenido de mi principal dominio, chuidiang.org, que hasta hoy mismo era la antigua web de C++ linux y Java que comencé hace muuuuchos años, de forma artesanal, html y css puro y duro hecho a manita. Y sí, aunque en su momento tuvo su éxito y lo sigue teniendo, es bastante cutre para los tiempos que corren hoy día.

Así que decidí mover el contenido principal a https://old.chuidiang.org/  y mover la wiki, más moderna, aunque sólo sea por usar un gestor de contenido (mediawiki), al dominio principal. Así que una tarde entretenida. Crear un subdominio old, mover todo el contenido del dominio principal al old, poner en el .htaccess todas las redirecciones 301 adecuadas para que google sepa del redireccionamiento, mover todo el contenido del subdominio chuwiki al dominio principal y nuevamente el .htaccess con redirecciones 301 desde chuwiki al dominio principal. Es decir, una tarde entretenida.

Ahora a volver a pedir a google, a través de ezoic, que validen el dominio y a ver qué pasa. Aunque quiero hacer de momento algún arreglo más en la página principal.

Publicado en web | Etiquetado , , , , , | Deja un comentario

Cálculos estadísticos en Python

pythonSiguiendo con mis aprendizajes y tutoriales de Python, me ha tocado la parte de cálculos estadísticos.

Me ha parecido bastante increible la cantidad de cálculos estadísticos que vienen por defecto con la instalación de python. No solo cálculos más o menos habituales como la media o la desviación estándar, sino todo tipo de cálculos estadísticos algo más avanzados: percentiles, distintos tipos de distribuciones e incluso interpolación lineal. Al escribir el tutorial he tenido que buscar muchos de los conceptos de estos cálculos que no conocía.

Como vengo de Java, me ha llamado la atención porque en Java no hay nada de esto, ni siquiera la media de una lista de números. No es complejo calcularla, pero tienes que hacerlo. Pero sí es más complejo de calcular cosas como los percentiles, distribuiciones o interpolación lineal. En java no te queda más remedio que currartelo o buscar alguna librería que lo haga.

Sé que el uso de Python ha crecido mucho últimamente, llegado a superar a Java. He leído por ahí que se debe sobre todo al tema de machine learning, porque las librerías que tiene python que son útiles para esta disciplina no las tienen otros lenguajes de programación. Lo que tiene de base para cálculos estadísticos, así como que de forma nativa trate con números complejos, parece dar la razón a este argumento. Y librerías adicionales como Numpy le dan más peso todavía.

Ahora sólo queda decidir el siguiente tema de python que estudiar y escribir.

Publicado en python | Etiquetado , | Deja un comentario

Aprendiendo Solidity

Solidity — documentación de Solidity - UNKNOWNAunque es poco conocido en general, sí es muy conocido dentro de los programadores de la blockchain de criptomonedas, del mundo de Ehterum en concreto. Es el lenguaje de programación Solidity.

Y precisamente como todo el tema de blockchain está muy de moda, maneja mucho dinero y este lenguaje de programación es relativamente nuevo y poco conocido, si estudias solidity dicen las malas lenguas que encuentras trabajo seguro con sueldos muy por encima de la media de lo que cobra un programador.

Así que me puse a investigar y juguetear. No es que quiera cambiar de trabajo, pero en este mundillo de la programación, nunca está de más actualizarse y aprender cosas nuevas. El lenguaje en sí no es complejo, en vez de clases tiene contract o contratos. Estos contract tienen constructores, variables y funciones (métodos). Hay herencia, etc, etc. Poca cosa que a un programador extrañe.

Sin embargo, sí hay conceptos, no de la sintaxis en sí, que llaman la atención y que hacen que programar correctamente pueda ser más complejo que en otros lenguajes.

El primero es que el contrato, una vez hecho, se sube a la blockchain. Esto cuesta dinero. Y la blockchain es inmutable, es decir, una vez subido nuestro código a la blockchain, si detectamos un bug, no podemos editarlo para corregirlo ni borrarlo para reemplazarlo por otro nuevo. No queda más remedio que corregirlo en nuestro fuente original, volver a subirlo pagando y tratar de eliminar todas las referencias al contrato antiguo en las aplicaciones públicas que tengamos. El código con errores sigue subido y «vivo» en la blockchain, público y accesible. Así que el proceso de depuración de nuestro código cobra especial importancia.

Sí, es cierto que otras aplicaciones como las de bancos o en las que haya vida de personas en juego también requieren una depuración y testeo muy exhaustivo del código antes de ponerlo en producción. Pero en estos casos, si el código está en producción y detectas un bug, puedes retirarlo y reemplazarlo por código nuevo con el bug corregido. En la blockchain no es posible. Tu código erróneo sigue vivo y accesible para que alguien malintencionado pueda explotar ese bug.

Y el segundo punto llamativo. Nuestros contratos trabajan con la blockchain y guardan datos en la misma. Acceder a esos datos es gratis, pero modificarlos a añadirlos cuesta dinero, las tasas de las transacciones. Y si nuestro código se lía a hacer transacciones, la llamada a una función o método puede ser cara. Y el lenguaje no te deja claro, al menos para un novato que empieza, qué variables están en la blockchain por lo que cambiar su valor implica coste.

Y pongo un ejemplo tonto, un array declarado en el contrato se guarda en la blockchain. Si eliminamos un elemento del array y desplazamos los siguientes una posición antes por aquello de no dejarlos huecos, cada escritura en el array cuesta dinero. Así que la forma correcta es copiar el array en un array en memoria, modificarlo totalmente en memoria y luego, de una sola transacción, meterlo en la blockchain.

Así que en eso ando entretenido estos días, aprendiendo algo de solidity. El curso que estoy siguiendo es de zombies y gatitos 🙂

Publicado en varios | Etiquetado , , , | Deja un comentario

Ficheros en python

Aunque ya había mirado como leer y escribir ficheros en python hace tiempo, con el tema del curso de python con el que estoy entretenido en la chuwiki, lo he estado revisando. Y ¿cómo no?, he encontrado un par de cosas que me han llamado la atención sólo porque son diferentes en java.

La primera es cómo saber si hemos llegado al final del fichero cuando hacemos un bucle para leerlo. En java, el método readLine() devuelve un null y hay que poner un if del estilo

while (null != linea) {

}

En python, devuelve una cadena vacía. Esto es así porque el método readLine() de python devuelve los retornos de carro, así que una línea en blanco devolvería ‘\n’, mientras que en java devolvería una cadena vacía ». Y en python, para el bucle, tienes otra forma de hacerlo

while linea:

No hace falta compararlo con nada. Los condicionales de python son listos y si la cadena está vacía o es None, devuelve false. Aunque es diferente de java y me ha llamado la atención, este tipo de condicionales que dan false si la cadena está vacía o es None, no me ha llamado tanto la atención, puesto que javascript también funciona así.

Aquí sólo un apunte. En python me parece engorroso que al leer una línea me devuelva también el retorno de carro final. Java se lo come y no te lo devuelve. No sé qué es más útil, pero me da la impresión de que si la línea contiene campos que quieres extaer, estilo fichero CSV, el retorno de carro al final  vas a tener que eliminarlo con código.

Y lo segundo que me ha llamado mucho más la atención es que el descriptor de un fichero abierto de python es un iterator. Por lo que iterando sobre él vamos leyendo.  Podemos incluso meterlo en un bucle. En java, para leer un fichero hasta el final necesitamos algo tan engorroso coom esto

String linea = bufferedRead.readLine();
while (null!=linea) {
// tratar la línea
linea = bufferedReader.readLine();
}

es decir, dos lecturas, una antes de entrar en el bucle para tener la variable línea inicializada con la primera línea del fichero y luego, dentro del bucle, como última línea, otra lectura. Este tipo de estructuras siempre me ha parecido poco elegante por lo de hacer dos lecturas. Con un do-while tampoco podemos hacerlo con una lectura.

Sin embargo, en python, como el fichero abierto es un iterator, podemos hacer esto

f = open (‘fichero.txt’)
for linea in f:
# Tratar la línea.

Mucho más claro. Funciona igual con ficheros de texto o binarios. Si lo abres como texto devuelve líneas, si lo tratas como binario devuelve bytes. Y ni siquiera hace falta la comparación para saber si hemos llegado a final de fichero.

Punto para python 🙂

ACTUALIZACION: Tras el comentario de GreenEyed, actualizo el post. No es necesario poner dos líneas de lectura en el código java «tradicional», basta con meterlo todo en el paréntesis del while

String line;
while ( (line = bufferedReader.readLine()) != null) {
// tratar línea
}

y a partir de java 8 hay más opciones para leer el fichero como se ve en el enlace que pone en el comentario.

Publicado en java, python | Etiquetado , , | 2 comentarios

Anti spam en mediawiki

Desde hace mucho tengo en marcha una wiki de programación que es una instalación de mediawiki. La idea original, como toda wiki que se precie, es que la gente pudiera colaborar, añadiendo o corrigiendo artículos, comentando en la pestaña discusión, etc, etc.

Pero el spam empezó a hacer de las suyas. Tuve primero que obligar al registro de usuarios para poder crear/modificar y luego tuve incluso que quitar la posibilidad de auto-registrarse como usuario. Había diariamente, incluso a pesar de la obligación de registrarse como usuario, varias páginas de spam muevas. Y pasaba todos los días un rato borrando estas páginas.

Hace unos días decidí volver a meter mano a esto. Estaba bastante seguro que una herramienta como mediawiki tenía que tener mecanismos antispam. Y efectivamente, encontré esta guía de combate contra el spam. Esa guía comenta que hay un  montón de posibilidades y que se pueden poner más o menos todas, pero que se puede reducir drásticamente con solo tres o cuatro plugins.

Dicho y hecho, me entretuve instando esos plugins y configurándolos. Hasta ahora, un mes después, y con posibilidad de modificar sin necesidad de registrarse como usuario, cero spam. A ver si sigue así.

Los cuatro plugins son los siguientes:

  • StopForumSpam. Este plugin abre la posibilidad de descargarse una lista de IPs que habitualmente se usan para publicar spam en webs de terceros, como mi wiki. La lista se actualiza periódicamente, por lo que tienes que descargarla periódicamente. Pero en tu servidor web puedes automatizar este proceso con un script y despreocuparte.
  • ConfirmEdit. Se configura para que si un usuario no registrado modifica algo, tenga que rellenar un captcha antes de salvar las modificaciones. En mi caso puse preguntas a las que hay que dar una respuesta. Aquí tienes cómo hacer correctamente las preguntas antispam.
  • QuestyCaptcha, forma parte de ConfirmEdit. Permite que ConfirmEdit pueda hacer preguntas como las que he mencionado en el punto anterior y ante qué acciones concretas debe pedirlas (creación, edición, si se añaden URLs, etc).
  • wgDnsBlackListUrls no lo he configurado. Una lista negra de DNS que suelen usarse para spam. Hay también una base de datos con un listado de estas DNS.

Lo único de momento que no puede hacerse sin registrarse como usuario es la creación de páginas nuevas. Si se pueden modificar o discutir. Si veo que va bien todo esto, habilitaré esos permisos también.

Publicado en web | Etiquetado , , , | Deja un comentario

Comparación de constructores en Java y en Python

En el curso de python me he liado a explicar cómo construcir excepciones propias de la aplicación. Para ello hay que hereadar de la clase Exception. La clase Exception tiene un constructor que admite n parámetros cualesquiera y se los guarda. Es una forma de guardar información adicional al levantar una excepción.

Pues me encontré una sorpresa. Cree mi propia excepción heredando de Exception de la forma más simple posible

class MyException(Exception):
pass

y resulta que sólo con eso puedo hacer cosas como

error = MyException(param1, param2, param3,…)

es decir, puedo añadir los parámetros que quiera usando el constructor de la clase padre.

Como vengo de Java, donde esto no es así, me llamó poderosamente la atención y me puse a investigar.

En Java sólo puedes llamar a constructores que hayas declarado explicitamente en la clase hija, o al constructor por defecto sin parámetros si no has declarado ninguno. Esto es así porque Java obliga a llamar a un constructor de la clase hija y este a su vez y de forma automática llama a un constructor de la clase padre. Al de defecto si no le hemos indicado explícitamente que haga otra cosa

En Python la resolución de constructores no es así. Si tu instancias una clase hija con un constructor (unos parámetros concretos), Python busca ese constructor en la clase hija. Si lo hay lo llama y no va a llamar de forma automática al de la clase padre. Si no lo hay en la clase hija, busca ese constructor en la clase padre (o en las clases padre en determinado orden, porque Python admite herencia múltiple) y si lo encuentra lo llama.

Así que en Python es perfectamente posible construir una clase hija sin que se llame a ningún constructor de la clase padre o que se se instancia una clase hija sin que se llame a ningún constructor de la clase hija.

En Java esto es más rígido. Si instancias una clase hija, obligatoriamente se tiene que llamar a un constructor de la clase hija y este llamará de forma automática a un constructor de la clase padre.

Sin embargo, para métodos normales y atributos el comportamiento de ambos lenguajes es más similar. Si en una instancia de una clase hija llamas a un método, ambos lenguajes buscan el método en la clase hija y lo llaman si existe. Si no existe, lo buscan en la clase padre y lo llaman si existe.

La diferencia entre ambos lenguajes es solo en los constructores. Java obliga a una llamada en cascada de constructores hijo, padre, abuelo… mientras que Python los trata como si fueran métodos normales.

Publicado en java, python | Etiquetado , , , | Deja un comentario

Bases de datos en python

En el curso de Python le ha tocado al tema de base de datos. La verdad es que no tengo muy claro que orden seguir con el curso, pero le ha tocado esto 😛

Lo primero que me ha llamado la atención es que Python viene, con la instalación estándar, con la base de datos SQLite embebida. Esto me ha venido estupendo porque en el curso. Me ahorro indicar que hay que instalarse una base de datos u otra para poder seguir los ejemplos. Como Python viene con SQLite, pues simplemente usar esa en los ejemplos y cualquiera puede seguirlos sin necesidad de instalarse nada adicional.

El siguiente punto que me ha llamado la atención es el tema de cómo se implementan los módulos de base de datos. En java existen una serie de clases e interfaces predefinidos, lo que se llama la JDBC (Java Database Connectivity). En Python intentan lo mismo, es la Python Database Specification PEP 249. Pero se queda un poco cojo por las características del lenguaje. En Java, al ser de tipado estático, puede «obligar» a que los driver de conexión de base de datos cumplan más o menos a rajatabla la especificación JDBC. En Python, puesto que es de tipado dinámico, la especificación se queda en una especie de descripción de qué métodos y clases tienen que implementar los módulos de conexión a base de datos, pero no puede «obligar» tanto como lo hace java. Esto hace que sí, que quizás todos los módulos cumplen la especificación, más o menos, pero no tienes tantas garantías de que el código sea reutilizable si cambias de base de datos.

Otro punto que me ha llamado la atención y este sí es a favor de Python, es la facilidad de todo esto. Apenas hay un par de clases en la especificación con unos cuantos métodos de los cuales realmente con tres o cuatro podemos hacer prácticamente todo. La JDBC de Java es bastante más compleja.

Y finalmente otro punto, que no sé qué pensar, es el tema de fechas, horas y timestamps. Java tiene soporte para ello, tienen tipos propios java.sql.Date, java.sql.Time y java.sql.Timestamp, que se usan en JDBC y se convierten correctamente a los tipos Date, Time y Timestamp de las columnas de base de datos. Python, hasta donde he visto, no tiene este soporte. Para manejar fechas y horas, debemos hacer las conversiones a los String en los formatos que los soportan las bases de datos. No es costoso, pero no sé si es cómodo.

Publicado en java, python | Etiquetado , , , | Deja un comentario

Python timezone. Módulo pytz

Estaba entretenido mirando todo el tema de datetime en python y me puse a mirar todo el tema de husos horarios o timezone. Como todos sabemos, cada país tiene una hora de su padre y de su madre, según el huso o zona horaria en la que esté.

En el 99% de las aplicaciones de escritorio, sean en python o no, esto no suele dar mayores problemas. La aplicación solo corre en un ordenador y la hora es la del ordenador en el timezone que le toque.

Pero si es una web que se va a publicar en internet que se vaya a ver en varios paises o es una aplicación de escritorio más compleja que se pueda instalar en clientes de varios paises y que vayan contra una base de datos o servidor centralizado, pues es importante tener en cuenta todo esto para presentar a cada usuario su hora correcta en función de su huso horario.

En python he visto una cosa que en parte me ha gustado. Y es que los módulos por defecto de python, como datetime, sólo entienden de hora local y de hora UTC / GMT. No entienden de horas de otros paises de una forma fácil. Siempre tenemos la opción de decir GMT+2 o GMT-4, pero desde luego eso obliga a saber ese incremento respeto a GMT para un país concreto. Y si encima vamos con horarios de verano e invierno, más lio, porque ese incremento cambia según la fecha del año.

¿Por qué digo que me ha gustado esto que aparentemente es una pega?. Porque como he comentado, el 99% de los casos no necesitamos más. La hora local va que chuta.

¿Y si queremos saber las horas de otros paises?. Hay varios módulos, algunos ya instalados en python, como zoneinfo, que de alguna forma ayudan. Pero en una investigación superficial, no me he matado mirando, no los he visto suficientemente cómodos y completos. Pero sí me ha gustado el módulo adicional pytz, abreviatura de Python Timezone.

La instalación es sencilla, python viene con un programa de nombre pip que permite instalar módulos externos desde internet. Este simple comando debería hacer el trabajo.

pyp install pytz

Si todo va bien, se habrá instalado. Luego basta usarlo en cuaqluier función de datetime que admita como parámetro un timezone. Por ejemplo (en azul la salida de los comandos)

>>> datetime.now(pytz.timezone(‘America/New_York’))
datetime.datetime(2022, 7, 30, 2, 43, 56, 551152, tzinfo=<DstTzInfo ‘America/New_York’ EDT-1 day, 20:00:00 DST>)

>>> datetime.now(pytz.timezone(‘Europe/Madrid’))
datetime.datetime(2022, 7, 30, 8, 44, 2, 924587, tzinfo=<DstTzInfo ‘Europe/Madrid’ CEST+2:00:00 DST>)

>>> datetime.now(pytz.timezone(‘CET’))
datetime.datetime(2022, 7, 30, 8, 44, 13, 512663, tzinfo=<DstTzInfo ‘CET’ CEST+2:00:00 DST>)

>>> datetime.now(pytz.timezone(‘Zulu’))
datetime.datetime(2022, 7, 30, 6, 44, 18, 40771, tzinfo=<StaticTzInfo ‘Zulu’>)

Ahí tenemos cuatro ejemplos para obtener la hora actual en New York, en Madrid, en CET (Central European Time, que coincide con la de Madrid) y en hora Zulu (similar a GMT y UTC).

O podemos convertir fechas de un país a otro

>>> zulu = datetime(2022,7,4,5,6,7,123456,pytz.timezone(‘Zulu’))
>>> zulu
datetime.datetime(2022, 7, 4, 5, 6, 7, 123456, tzinfo=<StaticTzInfo ‘Zulu’>)

>>> madrid = zulu.astimezone(pytz.timezone(‘Europe/Madrid’))
>>> madrid
datetime.datetime(2022, 7, 4, 7, 6, 7, 123456, tzinfo=<DstTzInfo ‘Europe/Madrid’ CEST+2:00:00 DST>)

Aquí obtenemos una fecha/hora concreto con timezone Zulu y luego averiguamos qué hora era en Madrid en esa hora Zulu, usando la función datetime.astimezone()

A partir de un timestamp también es sencillo

>>> timestamp = datetime.now().timestamp()
>>> datetime.fromtimestamp(timestamp)
datetime.datetime(2022, 7, 30, 9, 5, 36, 831705)

>>> datetime.fromtimestamp(timestamp, pytz.timezone(‘America/New_York’))
datetime.datetime(2022, 7, 30, 3, 5, 36, 831705, tzinfo=<DstTzInfo ‘America/New_York’ EDT-1 day, 20:00:00 DST>)

La función datetime.fromtimestamp() presupone hora local si no le ponemos parámetro, pero si le ponemos un timezone de parámetro, nos muestra el datetime en ese país.

Para saber qué timezone hay disponibles, la llamada pytz.all_timezones nos da un listado de todas las disponibles.

Publicado en python | Etiquetado , , , , | Deja un comentario