15. ¿Qué día es?

 

15. ¿Qué Día Es? - Enseñando a tu Asistente a Decir la Fecha

Explicación para principiantes:
Ahora vamos a enseñarle a tu asistente una segunda habilidad importante: decir la fecha actual. Es como enseñarle a un niño no solo a decir la hora, sino también a saber en qué día y mes vive. ¡Tu asistente está volviéndose cada vez más útil!

Objetivo de esta lección:

  • Detectar cuando el usuario pregunta por la fecha

  • Obtener y formatear la fecha actual

  • Organizar mejor el código con funciones

  • Crear un bucle continuo para conversación

Analogía:
Tu asistente es ahora como un calendario parlante inteligente:

  • Escucha: "¿Qué día es hoy?"

  • Procesa: Mira el calendario

  • Responde: "Hoy es lunes, 23 de enero de 2024"


🔄 Paso 1: Reestructurar el Código para Mejor Organización

Problema del código anterior:

python

# ❌ CÓDIGO DESORGANIZADO - TODO EN EL MISMO LUGAR

while True:

    comando = escuchar()

    

    if 'hora' in comando:

        # Código para hora aquí (mezclado)

        hora = datetime.datetime.now().strftime("%H:%M")

        hablar(f"Son las {hora}")

    

    if 'día' in comando:  # ❌ Esto causa problemas si ambos if se ejecutan

        # Código para día aquí (mezclado)

        dia = datetime.datetime.now().strftime("%d")

        hablar(f"Es el día {dia}")

Solución: Funciones Separadas:

python

# ✅ CÓDIGO ORGANIZADO - FUNCIONES SEPARADAS

def dar_hora():

    """Función dedicada a dar la hora"""

    hora = datetime.datetime.now().strftime("%H:%M")

    hablar(f"Son las {hora}")


def dar_fecha():

    """Función dedicada a dar la fecha"""

    fecha = datetime.datetime.now().strftime("%d/%m/%Y")

    hablar(f"Hoy es {fecha}")


# Uso limpio:

while True:

    comando = escuchar()

    

    if 'hora' in comando:

        dar_hora()  # ¡Simple y claro!

    

    elif 'día' in comando:  # elif, no if separado

        dar_fecha()  # ¡Simple y claro!

¿Por qué usar elif en lugar de if?

python

# ❌ CON IFs SEPARADOS:

if 'hora' in comando:

    dar_hora()      # Se ejecuta si contiene "hora"

if 'día' in comando:

    dar_fecha()     # ¡Se ejecuta TAMBIÉN si contiene "hora" Y "día"!


# ✅ CON ELIF:

if 'hora' in comando:

    dar_hora()      # Solo se ejecuta esto

elif 'día' in comando:

    dar_fecha()     # Solo se ejecuta si NO contenía "hora"


🎯 Paso 2: Crear la Función dar_fecha() Mejorada

Versión Básica:

python

import datetime


def dar_fecha_basica():

    """Versión simple para dar la fecha"""

    fecha_actual = datetime.datetime.now()

    

    # Formato DD/MM/YYYY

    fecha_formateada = fecha_actual.strftime("%d/%m/%Y")

    

    hablar(f"La fecha actual es {fecha_formateada}")

Versión Mejorada (más natural):

python

def dar_fecha_natural():

    """Dice la fecha de forma más natural y completa"""

    ahora = datetime.datetime.now()

    

    # Diccionario de meses en español

    meses = {

        1: "enero", 2: "febrero", 3: "marzo", 4: "abril",

        5: "mayo", 6: "junio", 7: "julio", 8: "agosto",

        9: "septiembre", 10: "octubre", 11: "noviembre", 12: "diciembre"

    }

    

    # Diccionario de días de la semana

    dias_semana = {

        0: "lunes", 1: "martes", 2: "miércoles", 3: "jueves",

        4: "viernes", 5: "sábado", 6: "domingo"

    }

    

    # Obtener partes de la fecha

    dia_numero = ahora.day           # Día del mes (1-31)

    mes_numero = ahora.month         # Mes (1-12)

    año = ahora.year                 # Año (2024)

    dia_semana_num = ahora.weekday() # Día de semana (0=lunes)

    

    # Convertir a texto

    dia_semana = dias_semana[dia_semana_num]

    mes_nombre = meses[mes_numero]

    

    # Crear mensaje natural

    mensaje = f"Hoy es {dia_semana}, {dia_numero} de {mes_nombre} de {año}"

    

    print(f"📅 {mensaje}")

    hablar(mensaje)

    

    # Mostrar también formato numérico

    print(f"   📱 ({dia_numero:02d}/{mes_numero:02d}/{año})")


# Probar la función

dar_fecha_natural()

Salida esperada:

text

📅 Hoy es martes, 23 de enero de 2024

   📱 (23/01/2024)


🔧 Paso 3: El Importante .lower() - ¡No Te Olvides!

Problema común:

python

# ❌ SIN .lower() - PROBLEMAS DE DETECCIÓN

comando = escuchar()  # Usuario dice: "¿Qué DÍA es?"

# comando = "¿Qué DÍA es?" (con mayúsculas)


if 'día' in comando:  # 'día' ≠ 'DÍA' → NO se detecta

    dar_fecha()  # ¡Nunca se ejecuta!

Solución:

python

# ✅ CON .lower() - DETECCIÓN CONFiable

comando = escuchar().lower()  # Convertir TODO a minúsculas

# comando = "¿qué día es?" (todo minúsculas)


if 'día' in comando:  # 'día' in "¿qué día es?" → ✅ SÍ se detecta

    dar_fecha()  # ¡Se ejecuta correctamente!

Visualización de .lower():

text

Entrada original: "¿Qué DÍA es Hoy?"

↓ .lower()

"¿qué día es hoy?"  ← Todas las letras ahora son minúsculas

↓ Buscar "día"

"¿qué día es hoy?"  ← ¡Ahora SÍ encuentra "día"!

     ↑↑↑

Lugar correcto para poner .lower():

python

# Opción 1: Al recibir el comando (RECOMENDADO)

def escuchar():

    audio = listener.listen(source)

    texto = listener.recognize_google(audio, language='es-ES')

    return texto.lower()  # ← Convertir aquí


# Opción 2: Al procesar el comando

comando = escuchar().lower()  # ← Convertir aquí


# Opción 3: Dentro de la condición

if 'día' in comando.lower():  # ← Convertir aquí


🔄 Paso 4: Implementar el Bucle Infinito Correctamente

Estructura del bucle:

python

def main():

    """Función principal con bucle infinito"""

    

    # Configuración inicial

    bienvenida()

    

    # Bucle infinito para conversación continua

    while True:

        print("\n" + "=" * 40)

        print("Esperando tu comando...")

        print("=" * 40)

        

        # 1. Escuchar comando

        comando = escuchar().lower()  # ← .lower() aquí

        

        # 2. Si no se entendió, continuar

        if not comando:

            continue

        

        # 3. Procesar comando

        if 'hora' in comando:

            print("⏰ Detecté pregunta por la hora")

            dar_hora()

        

        elif 'día' in comando or 'fecha' in comando:

            print("📅 Detecté pregunta por la fecha")

            dar_fecha()

        

        elif 'adiós' in comando or 'salir' in comando:

            print("👋 Detecté comando de salida")

            despedirse()

            break  # ← Romper el bucle para salir

        

        else:

            print("❌ Comando no reconocido")

            hablar("No entendí ese comando. Puedes preguntar la hora o la fecha")

Diagrama del bucle:

text

┌─────────────────────────────────────┐

│        INICIO DEL BUCLE            │

├─────────────────────────────────────┤

│ 1. Escuchar comando                │

│ 2. Convertir a minúsculas          │

│ 3. ¿Comando vacío? → Volver a 1    │

├─────────────────────────────────────┤

│ 4. Procesar:                       │

│    • ¿Contiene "hora"? → dar_hora()│

│    • ¿Contiene "día"? → dar_fecha()│

│    • ¿Contiene "adiós"? → Salir    │

│    • ¿Ninguno? → Mensaje error     │

├─────────────────────────────────────┤

│ 5. Volver al paso 1 (a menos que   │

│    haya sido "adiós")              │

└─────────────────────────────────────┘


🚀 Paso 5: Código Completo del Asistente con Hora y Fecha

python

"""

ASISTENTE VIRTUAL COMPLETO CON HORA Y FECHA

Versión organizada y mejorada

"""


import speech_recognition as sr

import pyttsx3

import datetime


# ========== CONFIGURACIÓN INICIAL ==========

listener = sr.Recognizer()

engine = pyttsx3.init()


# Configurar voz en español

voces = engine.getProperty('voices')

for voz in voces:

    if 'spanish' in voz.name.lower() or 'español' in voz.name.lower():

        engine.setProperty('voice', voz.id)

        print(f"✅ Voz seleccionada: {voz.name}")

        break


engine.setProperty('rate', 180)

engine.setProperty('volume', 0.9)


# ========== FUNCIONES BÁSICAS ==========

def hablar(texto):

    """Hace que el asistente hable"""

    print(f"🤖: {texto}")

    engine.say(texto)

    engine.runAndWait()


def bienvenida():

    """Da la bienvenida al usuario"""

    hora_actual = datetime.datetime.now().hour

    

    if 5 <= hora_actual < 12:

        saludo = "Buenos días"

    elif 12 <= hora_actual < 19:

        saludo = "Buenas tardes"

    else:

        saludo = "Buenas noches"

    

    mensaje = f"{saludo}. Soy tu asistente virtual. Puedes preguntarme la hora o la fecha."

    hablar(mensaje)


def escuchar():

    """Escucha y convierte voz a texto"""

    try:

        with sr.Microphone() as source:

            print("\n🎤 Escuchando... (habla ahora)")

            listener.adjust_for_ambient_noise(source, duration=0.5)

            audio = listener.listen(source, phrase_time_limit=5)

            

            texto = listener.recognize_google(audio, language='es-ES')

            texto = texto.lower()  # ← ¡IMPORTANTE! Convertir a minúsculas

            

            print(f"👤 Tú: {texto}")

            return texto

    except sr.UnknownValueError:

        print("❌ No te entendí")

        return ""

    except sr.RequestError:

        print("❌ Error de conexión")

        return ""

    except Exception as e:

        print(f"❌ Error: {e}")

        return ""


# ========== FUNCIONES DE HORA Y FECHA ==========

def dar_hora():

    """Da la hora actual de forma natural"""

    ahora = datetime.datetime.now()

    hora = ahora.hour

    minutos = ahora.minute

    

    # Determinar período del día

    if 5 <= hora < 12:

        periodo = "de la mañana"

    elif 12 <= hora < 19:

        periodo = "de la tarde"

    else:

        periodo = "de la noche"

    

    # Convertir a formato de 12 horas

    if hora == 0:

        hora_12 = 12

    elif hora > 12:

        hora_12 = hora - 12

    else:

        hora_12 = hora

    

    # Formatear minutos de forma natural

    if minutos == 0:

        mensaje = f"Son las {hora_12} en punto {periodo}"

    elif minutos == 30:

        mensaje = f"Son las {hora_12} y media {periodo}"

    elif minutos == 15:

        mensaje = f"Son las {hora_12} y cuarto {periodo}"

    else:

        mensaje = f"Son las {hora_12} con {minutos} minutos {periodo}"

    

    # Mostrar también formato digital

    hora_digital = ahora.strftime("%H:%M")

    print(f"⏰ Hora digital: {hora_digital}")

    

    hablar(mensaje)


def dar_fecha():

    """Da la fecha actual de forma natural"""

    ahora = datetime.datetime.now()

    

    # Diccionarios para conversión

    meses = {

        1: "enero", 2: "febrero", 3: "marzo", 4: "abril",

        5: "mayo", 6: "junio", 7: "julio", 8: "agosto",

        9: "septiembre", 10: "octubre", 11: "noviembre", 12: "diciembre"

    }

    

    dias_semana = {

        0: "lunes", 1: "martes", 2: "miércoles", 3: "jueves",

        4: "viernes", 5: "sábado", 6: "domingo"

    }

    

    # Obtener partes de la fecha

    dia_numero = ahora.day

    mes_numero = ahora.month

    año = ahora.year

    dia_semana_num = ahora.weekday()

    

    # Convertir a texto

    dia_semana = dias_semana[dia_semana_num]

    mes_nombre = meses[mes_numero]

    

    # Crear mensajes diferentes según cómo pregunten

    mensaje_principal = f"Hoy es {dia_semana}, {dia_numero} de {mes_nombre} de {año}"

    mensaje_alternativo = f"Estamos a {dia_numero} de {mes_nombre} de {año}"

    

    # Mostrar formato numérico también

    fecha_digital = ahora.strftime("%d/%m/%Y")

    print(f"📅 Fecha digital: {fecha_digital}")

    

    # Decir la fecha

    hablar(mensaje_principal)


def despedirse():

    """Función de despedida"""

    mensajes = [

        "¡Hasta luego! Que tengas un excelente día",

        "Adiós, ha sido un placer ayudarte",

        "Nos vemos pronto, que te vaya muy bien",

        "Hasta la próxima, cuídate mucho"

    ]

    

    import random

    mensaje = random.choice(mensajes)

    hablar(mensaje)


# ========== PROGRAMA PRINCIPAL ==========

def main():

    """Función principal con bucle infinito"""

    print("=" * 60)

    print("       ASISTENTE VIRTUAL - HORA Y FECHA")

    print("=" * 60)

    print("Comandos disponibles:")

    print("  • Pregunta por la hora (di 'hora' o 'qué hora es')")

    print("  • Pregunta por la fecha (di 'día' o 'qué día es')")

    print("  • Di 'adiós' o 'salir' para terminar")

    print("=" * 60)

    

    # Bienvenida inicial

    bienvenida()

    

    # Contador de interacciones

    interacciones = 0

    

    # BUCLE INFINITO PARA CONVERSACIÓN CONTINUA

    while True:

        interacciones += 1

        print(f"\n🔄 Interacción #{interacciones}")

        print("-" * 40)

        

        # 1. ESCUCHAR COMANDO (con .lower() para consistencia)

        comando = escuchar()  # Ya tiene .lower() dentro de escuchar()

        

        # 2. SI NO SE ENTENDIÓ, CONTINUAR

        if not comando:

            print("⚠️  No se detectó comando, intentando de nuevo...")

            continue

        

        # 3. PROCESAR COMANDO CON ELIF (NO if separados)

        if 'hora' in comando or 'horas' in comando:

            print("✅ Comando detectado: HORA")

            dar_hora()

        

        elif 'día' in comando or 'fecha' in comando or 'dias' in comando:

            print("✅ Comando detectado: FECHA")

            dar_fecha()

        

        elif any(palabra in comando for palabra in ['adiós', 'salir', 'chao', 'hasta luego']):

            print("✅ Comando detectado: SALIR")

            despedirse()

            break  # ← ROMPER EL BUCLE PARA SALIR

        

        # 4. COMANDO NO RECONOCIDO

        else:

            print("❌ Comando no reconocido")

            hablar("No entendí ese comando. Puedes preguntarme la hora, la fecha o despedirte")

            

            # Sugerir comandos

            print("\n💡 Prueba con:")

            print("   • '¿Qué hora es?'")

            print("   • '¿Qué día es hoy?'")

            print("   • 'Adiós' para terminar")

    

    # Mensaje final al salir del bucle

    print("\n" + "=" * 60)

    print("👋 Programa terminado. ¡Gracias por usar el asistente!")

    print("=" * 60)


# ========== EJECUCIÓN ==========

if __name__ == "__main__":

    try:

        main()

    except KeyboardInterrupt:

        print("\n\n⚠️  Programa interrumpido por el usuario (Ctrl+C)")

        hablar("Programa interrumpido. ¡Hasta pronto!")

    except Exception as e:

        print(f"\n❌ Error inesperado: {e}")


🎮 Paso 6: Ejercicios Prácticos y Mejoras

Ejercicio 1: Añadir Más Formas de Preguntar

python

# Mejora la detección para entender más variantes

def es_pregunta_hora(comando):

    """Detecta si están preguntando por la hora"""

    palabras_hora = [

        'hora', 'horita', 'reloj', 'tiempo actual',

        'qué hora', 'dime la hora', 'necesito la hora',

        'podrías decirme la hora', 'saber la hora'

    ]

    

    return any(palabra in comando for palabra in palabras_hora)


def es_pregunta_fecha(comando):

    """Detecta si están preguntando por la fecha"""

    palabras_fecha = [

        'día', 'fecha', 'calendario', 'hoy',

        'qué día', 'qué fecha', 'día de hoy',

        'en qué día estamos', 'fecha actual'

    ]

    

    return any(palabra in comando for palabra in palabras_fecha)

Ejercicio 2: Añadir Funcionalidad de Día de la Semana

python

def que_dia_es():

    """Responde específicamente al día de la semana"""

    ahora = datetime.datetime.now()

    

    dias_semana = {

        0: "lunes", 1: "martes", 2: "miércoles", 3: "jueves",

        4: "viernes", 5: "sábado", 6: "domingo"

    }

    

    dia_num = ahora.weekday()

    dia_nombre = dias_semana[dia_num]

    

    # Mensajes diferentes

    if dia_num in [0, 1, 2, 3]:  # Lunes a jueves

        mensaje = f"Hoy es {dia_nombre}, día de trabajo"

    elif dia_num == 4:  # Viernes

        mensaje = f"¡Hoy es {dia_nombre}! Casi fin de semana"

    else:  # Sábado o domingo

        mensaje = f"Hoy es {dia_nombre}, día de descanso"

    

    hablar(mensaje)


# En el main, añade:

elif 'día de la semana' in comando or 'qué día cae' in comando:

    que_dia_es()

Ejercicio 3: Mostrar Próximos Días Festivos

python

def proximos_festivos():

    """Dice los próximos días festivos (ejemplo básico)"""

    festivos = [

        "1 de enero: Año Nuevo",

        "6 de enero: Día de Reyes",

        "1 de mayo: Día del Trabajo",

        "15 de agosto: Asunción de la Virgen",

        "12 de octubre: Día de la Hispanidad",

        "1 de noviembre: Día de Todos los Santos",

        "6 de diciembre: Día de la Constitución",

        "8 de diciembre: Inmaculada Concepción",

        "25 de diciembre: Navidad"

    ]

    

    hablar("Estos son algunos días festivos importantes:")

    

    for festivo in festivos[:3]:  # Solo decir los primeros 3

        print(f"   • {festivo}")

        hablar(festivo)


📊 Diagrama de Flujo del Asistente Mejorado

text

┌─────────────────────────────────────────────┐

│            INICIO DEL PROGRAMA              │

├─────────────────────────────────────────────┤

│ 1. Configurar voz (español, velocidad)     │

│ 2. Dar bienvenida personalizada            │

├─────────────────────────────────────────────┤

│           BUCLE PRINCIPAL (while True)      │

├─────────────────────────────────────────────┤

│ 3. Escuchar comando → Convertir a minúsculas│

│    ↓                                        │

│ 4. ¿Comando vacío? → Volver a escuchar      │

│    ↓                                        │

│ 5. Procesar con ELIF:                       │

│    • ¿Contiene "hora"? → dar_hora()         │

│    • ¿Contiene "día/fecha"? → dar_fecha()   │

│    • ¿Contiene "adiós"? → despedirse()      │

│      y BREAK (romper bucle)                 │

│    • ¿Ninguno? → Mensaje de error           │

│    ↓                                        │

│ 6. Volver al paso 3 (excepto si fue "adiós")│

└─────────────────────────────────────────────┘


❓ Cuestionario de Repaso

Pregunta 1:

¿Por qué es importante usar elif en lugar de múltiples if separados?

  • A) Para que el programa sea más lento

  • B) Para evitar que se ejecuten múltiples funciones si el comando contiene varias palabras clave

  • C) Para obligar al usuario a hablar más claro

  • D) Para cambiar automáticamente el idioma

Respuesta correcta: B
Explicación: Si usas if separados y el usuario dice "qué hora y día es", se ejecutarían tanto dar_hora() como dar_fecha(). Con elif, solo se ejecuta la primera condición que sea verdadera.


Pregunta 2:

¿Dónde es el mejor lugar para poner .lower() al procesar comandos?

  • A) Solo al principio del programa

  • B) Dentro de la función escuchar() (al devolver el texto)

  • C) Nunca, porque pierde las mayúsculas

  • D) Solo cuando el usuario habla fuerte

Respuesta correcta: B
Explicación: Poner .lower() dentro de escuchar() asegura que TODO el texto recibido esté en minúsculas, haciendo las búsquedas consistentes sin necesidad de recordar convertirlo cada vez.


Pregunta 3:

¿Qué hace datetime.datetime.now().weekday()?

  • A) Devuelve el día del mes (1-31)

  • B) Devuelve el día de la semana (0=lunes, 6=domingo)

  • C) Devuelve la hora actual

  • D) Devuelve el número de semana del año

Respuesta correcta: B
Explicación: .weekday() devuelve un número del 0 al 6, donde 0 es lunes y 6 es domingo. Es útil para saber qué día de la semana es hoy.


Pregunta 4:

¿Cómo podemos hacer que el asistente diga "Hoy es lunes, 23 de enero de 2024" en lugar de solo "23/01/2024"?

  • A) Usando diccionarios para convertir números a nombres

  • B) Pidiendo al usuario que diga la fecha completa

  • C) Conectando a internet para obtener la fecha

  • D) Usando una librería especial de fechas

Respuesta correcta: A
Explicación: Creamos diccionarios como meses = {1: "enero", 2: "febrero"...} y dias_semana = {0: "lunes", 1: "martes"...} para convertir los números en nombres legibles.


Pregunta 5:

¿Qué hace la palabra clave break en nuestro bucle while True?

  • A) Pausa el programa por 1 segundo

  • B) Rompe (termina) el bucle infinito

  • C) Aumenta la velocidad del habla

  • D) Repite el último comando

Respuesta correcta: B
Explicación: break hace que el programa salga inmediatamente del bucle en el que está. En nuestro caso, sale del while True cuando el usuario dice "adiós".


Pregunta 6 (Bonus):

Si el usuario dice "¿Podrías decirme qué día y hora es?", ¿qué pasará con nuestro código actual?

  • A) Solo dirá la hora (porque "hora" aparece primero en el código)

  • B) Solo dirá la fecha (porque "día" aparece después)

  • C) Dirá ambas, hora y fecha

  • D) No dirá nada porque no entiende "y"

Respuesta correcta: A
Explicación: Nuestro código usa elif, por lo que cuando encuentra "hora" en el comando, ejecuta dar_hora() y NO revisa las demás condiciones. El elif de "día" nunca se evalúa.


🌟 ¡Tu Asistente Ahora es un Calendario Parlante!

Has aprendido a:

  1. ✅ Organizar el código con funciones separadas

  2. ✅ Detectar preguntas sobre la fecha

  3. ✅ Formatear fechas de forma natural

  4. ✅ Usar .lower() correctamente para detección confiable

  5. ✅ Implementar un bucle conversacional infinito

  6. ✅ Usar elif para evitar ejecuciones múltiples

Próximos pasos sugeridos:

  1. Añade más funcionalidades: clima, noticias, calculadora

  2. Mejora la detección: usa expresiones regulares para más precisión

  3. Añade memoria: que recuerde tu nombre entre sesiones

  4. Crea interfaz gráfica: con tkinter o PyQt

📌 Tarea práctica:

  1. Ejecuta el asistente completo

  2. Pregúntale la hora y fecha de diferentes formas

  3. Añade la funcionalidad de decir cuántos días faltan para el fin de semana

  4. Comparte en los comentarios qué otras preguntas sobre tiempo te gustaría que responda

🎉 ¡Tu asistente está volviéndose cada vez más inteligente!
En la próxima lección, enseñaremos a tu asistente a buscar información en internet.


https://www.youtube.com/watch?v=Pj9KbAKpQyk

https://www.youtube.com/watch?v=-0tIy8wWtzE

https://www.youtube.com/watch?v=YqSSId7xfwU

https://www.youtube.com/watch?v=MjK-j7YJ5YI


https://www.youtube.com/watch?v=l2G8-iQYfoA



https://www.youtube.com/watch?v=t-YO0XeHczU


Comentarios

Entradas más populares de este blog

1-7. Transforma tu audio a texto

10. Haz que tu asistente hable

8. NUEVO - Solución si tu micrófono no está captando tu audio