miércoles, 12 de febrero de 2014

Operaciones con fechas y horas. Calendarios




Los módulos datetime y calendar amplían las posibilidades del módulo time que provee funciones para manipular expresiones de tiempo.

Al comienzo de un programa tendremos que importar estos módulos para tener acceso a un conjunto amplio de clases y funciones:

from datetime import datetime, date, time, timedelta
import calendar

Mostrar fecha y hora (datetime)


ahora = datetime.now()  # Obtiene fecha y hora actual
print("Fecha y Hora:", ahora)  # Muestra fecha y hora
print("Fecha y Hora UTC:",ahora.utcnow())  # Muestra fecha/hora UTC
print("Día:",ahora.day)  # Muestra día
print("Mes:",ahora.month)  # Muestra mes
print("Año:",ahora.year)  # Muestra año
print("Hora:", ahora.hour)  # Muestra hora
print("Minutos:",ahora.minute)  # Muestra minuto
print("Segundos:", ahora.second)  # Muestra segundo
print("Microsegundos:",ahora.microsecond)  # Muestra microsegundo

Comparando fechas y horas (datetime, date)


print("Horas:")
hora1 = time(10, 5, 0)  # Asigna 10h 5m 0s
print("\tHora1:", hora1)
hora2 = time(23, 15, 0)  # Asigna 23h 15m 0s
print("\tHora2:", hora2)

# Compara horas
print("\tHora1 < Hora2:", hora1 < hora2)  # True

print("Fechas:")
fecha1 = date.today()  # Asigna fecha actual
print("\tFecha1:", fecha1)

# Suma a la fecha actual 2 días
fecha2 = date.today() + timedelta(days=2)
print("\tFecha2:", fecha2)

# Compara fechas
print("\tFecha1 > Fecha2:", fecha1 > fecha2)  # False

Aplicando formatos a fechas y horas (Máscaras)


Las siguientes claves se combinan para aplicar formatos:

%a Nombre local abreviado de día de semana
%A Nombre local completo de día de semana
%b Nombre local abreviado de mes
%B Nombre local completo de mes
%c Representación local de fecha y hora
%d Día de mes [01,31]
%H Hora (horario 24 horas) [00,23]
%I Hora (horario 12 horas) [01,12]
%j Número de día del año [001,366]
%m Mes [01,12]
%M Minuto [00,59]
%p Etiqueta AM o PM
%S Segundo
%U Nº semana del año. Se considera al Domingo como primer día de semana [00,53]
%w Establece el primer día de semana [0(Domingo),1(Lunes)... 6].
%W Nº semana del año (Se considera al Lunes como primer día de semana) [00,53]
%x Fecha local
%X Hora local
%y Año en formato corto [00,99]
%Y Año en formato largo
%Z Nombre de Zona Horaria


Ejemplos:

# Asigna formato de ejemplo1
formato1 = "%a %b %d %H:%M:%S %Y"

# Asigna formato de ejemplo2
formato2 = "%d-%m-%y %I:%m %p"

hoy = datetime.today()  # Asigna fecha-hora

# Muestra fecha-hora según ISO 8601
print("Fecha en formato ISO 8601:", hoy)

# Aplica formato ejemplo1
cadena1 = hoy.strftime(formato1)  

# Aplica formato ejemplo2
cadena2 = hoy.strftime(formato2)  

# Muestra fecha-hora según ejemplo1
print("Formato1:", cadena1)

# Muestra fecha-hora según ejemplo2
print("Formato2:", cadena2)

Para convertir una cadena a objeto datetime


objeto_datetime = datetime.strptime(cadena1, formato1)
print("strptime:", fecha1.strftime(formato1))

Operaciones con fechas y horas


Se utiliza la función timedelta que permite operar con: microseconds, milliseconds, seconds, minutes, hours, days y weeks

hoy = date.today()  # Asigna fecha actual
ayer = hoy – timedelta(days=1)  # Resta a fecha actual 1 día
mañana = hoy + timedelta(days=1)  # Suma a fecha actual 1 día
diferencia_en_dias = mañana – hoy  # Resta las dos fechas

Otros ejemplos de operaciones con otras unidades de tiempo


hoy_mas_1_millon_segundos = hoy + timedelta(seconds=1000000)
ahora = datetime.now() 
hora_actual = time(ahora.hour, ahora.minute, ahora.second)
mas_5m = ahora + timedelta(seconds=300)
mas_5m = time(mas_5m.hour, mas_5m.minute, mas_5m.second)
racion_de_5h = timedelta(hours=5)
mas_5h = ahora + racion_de_5h

print("Ayer:", ayer)
print("Hoy:", hoy)
print("Mañana:", mañana)
print("Diferencia en días entre mañana y hoy:", 
      diferencia_en_dias.days)
print("La fecha de hoy más 1 millón de segundos:", 
      hoy_mas_1_millon_segundos)
print("Hora actual:", hora_actual)
print("Hora actual + 5 minutos:", mas_5m)
print("Hora actual + 5 horas:", mas_5h)

Diferencia entre dos fechas (datetime)


# Asigna datetime de la fecha actual
fecha1 = datetime.now()

# Asigna datetime específica
fecha2 = datetime(1995, 11, 5, 0, 0, 0)
diferencia = fecha1 - fecha2
print("Fecha1:", fecha1)
print("Fecha2:", fecha2)
print("Diferencia:", diferencia)
print("Entre las 2 fechas hay ", 
      diferencia.days, 
      "días y ", 
      diferencia.seconds, 
      "seg.")

Diferencia entre dos fechas en días (datetime y strptime)


formato_fecha = "%d-%m-%Y"
fecha_inicial = datetime.strptime("01-10-2013", 
                                  formato_fecha)
fecha_final = datetime.strptime("25-12-2013", 
                                formato_fecha)
diferencia = fecha_final - fecha_inicial
print("Fecha inicial:", fecha_inicial)
print("Fecha final:", fecha_final)
print("Diferencia:", diferencia.days, "días")

Diferencia de dos fechas en días, introducidas por teclado


#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  diferencia-entre-fechas-teclado.py
#
#  Diferencia de dos fechas en días introducidas por teclado,
#  con control de errores.
#

from datetime import datetime

def main():
 # Establecer formato de las fechas a introducir: dd/mm/aaaa
 
 formato = "%d/%m/%Y"
 
 # Bucle 'sin fin' 
 
 while True:
  try:
   # Introducir fecha inicial utilizando el formato definido
   
   fecha_desde = input('Introducir fecha inicial (dd/mm/aaaa): ')   
   
   # Si no se introduce ningún valor se fuerza el final del bucle 
   
   if fecha_desde == "":
    break
   
   # Introducir fecha final utilizando el formato definido   
   
   fecha_hasta = input('Introducir fecha final   (dd/mm/aaaa): ') 

   # Si no se introduce ningún valor se fuerza el final del bucle 
   
   if fecha_hasta == "":
    break
   
   # Se evaluan las fechas según el formato dd/mm/aaaa
   # En caso de introducirse fechas incorrectas se capturará
   # la excepción o error
   
   fecha_desde = datetime.strptime(fecha_desde, formato)
   fecha_hasta = datetime.strptime(fecha_hasta, formato)
   
   # Se comprueba que fecha_hasta sea mayor o igual que fecha_desde
   
   if fecha_hasta >= fecha_desde:
    
    # Se cálcula diferencia en día y se muestra el resultado
    
    diferencia = fecha_hasta - fecha_desde
    print("Diferencia:", diferencia.days, "días")
    
   else:
    print("La fecha fecha final debe ser mayor o igual que la inicial")
   
  except:
   print('Error en la/s fecha/s. ¡Inténtalo de nuevo!')
   
 return 0

if __name__ == '__main__':
 main()

A partir de una hora se obtiene fracción del día


#!/usr/bin/env python
# -*- coding: utf-8 -*-

# A partir de una hora introducida por teclado se obtiene
# fracción del día, teniendo en cuenta que 24 horas = 86400 seg
# Formato de entrada: hh:mm:ss
# Valores Hora...: 0 a 23
# Valores Minuto.: 0 a 59
# Valores Segundo: 0 a 59

from datetime import datetime
formato = "%H:%M:%S"

while True:
 try:
  hhmmss = input('Introducir hora (hh:mm:ss): ')
  if hhmmss == "":
   break
  
  hhmmss = datetime.strptime(hhmmss, formato)
  horas = hhmmss.hour
  minutos = hhmmss.minute
  segundos = hhmmss.second
  hhmmss_seg = (horas * 60 * 60) + (minutos * 60) + segundos 
  resultado = float(hhmmss_seg / 86400)
  print("Resultado: ", resultado)
 
 except:
  print('Error en el formato de hora introducido.')
  print('-> Formato válido: hh:mm:ss  ¡Inténtalo de nuevo!')

Diferencia de dos fechas (date)


hoy = date.today()
navidad_año_proximo = date(2024, 12, 25)
faltan = navidad_año_proximo - hoy
print ("Hoy:", hoy)
print ("La navidad del 2024", navidad_año_proximo)
print ("Faltan", faltan.days, "días")

Expresar una fecha en formato largo


print("Hoy es...", datetime.ctime(fecha1))

A partir de una fecha se obtiene tupla con año, nº semana y día de semana


print("Fecha", fecha1, 
      "Año, nº sem., día sem.:", 
      datetime.isocalendar(fecha1))

A partir de una fecha se obtiene tupla con año, nº semana y día de semana


También, se muestra el día de la semana en letras (abreviado).

print("Desglose de la fecha", fecha2,":")
tupla_mensajes = ("Año", "Núm. semana", "Núm. día de semana")
tupla_valores = datetime.isocalendar(fecha2)
tupla_diassem = ("Lun", "Mar", "Mié", "Jue","Vie", "Sáb","Dom")
for mensaje,valor in zip(tupla_mensajes, tupla_valores):
 print(mensaje,"-->", valor)
 
print("Día de semana-->", tupla_diassem[tupla_valores[2]-1])

Obtener día de la semana por su número 


La función weekday() devuelve el número de día de la semana a que corresponda la fecha indicada, según los siguientes valores por día:  0-Lunes, 1-Martes, 2-Miércoles, 3-Jueves, 4-Viernes , 5-Sábado y 6-Domingo

dia_semana = datetime.weekday(fecha1)
print(fecha1, "->", dia_semana,"->", 
      tupla_diassem[dia_semana])

Obtener y contar los días que sean martes entre dos fechas


from datetime import datetime, timedelta

formato = "%d/%m/%Y"
contador = 0            
fechadesde = input('Fecha desde (dd/mm/aaaa): ')
fechahasta = input('Fecha hasta (dd/mm/aaaa): ')
if fechadesde == '' or fechahasta == '':
    exit()

try:                    
    fechadesde = datetime.strptime(fechadesde, formato)
    fechahasta = datetime.strptime(fechahasta, formato)    
    if fechadesde > fechahasta:
        print('Fecha desde debe ser menor o igual que hasta')
    
    while fechadesde <= fechahasta:
        if datetime.weekday(fechadesde) == 1: 
            contador +=1
            fechaactual = fechadesde.strftime(formato)
            print(contador, fechaactual, 'es martes')
        fechadesde = fechadesde + timedelta(days=1)
                
except:
    print('Fecha incorrecta')

Obtener día de la semana por su número


La función isoweekday() devuelve el número de día de la semana a que corresponda la fecha indicada, según los siguientes valores por día:  1-Lunes, 2-Martes, 3-Miércoles, 4-Jueves, 5-Viernes, 6-Sábado y 7-Domingo.

dia_semana = datetime.isoweekday(fecha1)
print(fecha1, "->", dia_semana,"->", 
      tupla_diassem[dia_semana-1])

Dado el ordinal se obtiene la fecha correspondiente


print("Si la fecha 01-01-0001 tiene el ordinal 1 entonces...")
for num in range(1,7):
    print("El día", 10 ** num , 
          "se corresponde con", 
          date.fromordinal(10 ** num))

Dada una fecha se obtiene un ordinal (01-01-0001 -> 1)


fecha3 = datetime(1, 1, 1, 0, 0, 0)
print("La fecha", fecha3, 
      "tiene el ordinal", 
      date.toordinal(fecha3))
print("La fecha", fecha1, 
      "tiene el ordinal", 
      date.toordinal(fecha1))

Obtener una tupla a partir de fecha-hora (datetime)


tupla_fechahora = fecha1.timetuple()
for elemento in tupla_fechahora:
 print(elemento)

Convertir un ordinal en fecha-hora (fromtimestamp)


El ordinal 0 se corresponde con la fecha -> 1-1-1970 01:00:00

print("Ordinal 0 -> 1-1-1970 01:00:00")
ordinales_tiempo = (0, 1, 2, 60, 3600)
for elemento in ordinales_tiempo:
    print(elemento, "->" , datetime.fromtimestamp(elemento))

Obtener calendario del mes actual (calendar.month)


año = date.today().year 
mes = date.today().month
calendario_mes = calendar.month(año, mes)
print(calendario_mes)

Obtener calendario del mes actual (calendar.TextCalendar)


Se establece el lunes como primer día de la semana

calendario = calendar.TextCalendar(calendar.MONDAY)
calendario.prmonth(año, mes)

Obtener matriz con calendario de mes actual: (Calendar monthdayscalendar)


calendario = calendar.Calendar()
for elemento in calendario.monthdayscalendar(año, mes):
    print(elemento)

Obtener matriz de tuplas con calendario: (Calendar monthdays2calendar)


El primer valor de cada par es el número de día del mes y el segundo valor se corresponde con el número de día de la semana: 0:lunes, 1:martes, 2:miércoles, etc.

calendario = calendario.monthdays2calendar(año, mes)
for elemento in calendario:
    print(elemento)

Calendario completo del año 2018


Día de comienzo: Lunes

print(calendar.TextCalendar(calendar.MONDAY).formatyear(2018, 
                                                        2, 1, 1, 2))


Relacionado:

Ir al índice del tutorial de Python

8 comentarios:

Alejo Blake dijo...

Hola, está bastante bien su entrada, pero tengo una pregunta. Cómo puedo asignar a la fecha y hora actual por ejemplo el clima justo en ese momento?

Cordial saludo...

Pherkad dijo...

Alejo, no entiendo muy bien su comentario. Si lo que desea es acceder a información del tiempo (clima) que hacen pública algunas fuentes y mostrarla en un programa Python entonces le puede servir de ayuda el siguiente enlace: https://code.google.com/p/python-weather-api/ Muchas gracias

Giovanny Vizcaya dijo...

Buen día, ¿Como calculo la diferencia en días entre dos fechas ingresadas por teclado? ejemplo, desde hoy hasta el 15 de enero

Pherkad dijo...

Hola Giovanny, he incluido en la entrada un ejemplo que resuelve lo que preguntas en el comentario. Busca el apartado con el título "Diferencia de dos fechas en días, introducidas por teclado".

Lo más importante es comprobar que las fechas introducidas son correctas, es decir, deben ser reales e introducirse según un formato establecido (dd/mm/aaaa).

Para ello se utiliza el método datetime.strptime()

Espero que sea de utilidad. Saludos.

Alejo Blake dijo...

Hola de nuevo, cómo puedo convertir en fracción de día determinada hora, es decir, le pido al usuario que ingrese la hora y luego necesito transformar ese dato que me da el usuario a una fracción del día i.e. (hh/24)

gracias

Pherkad dijo...

Hola Alejo,
He incluido un ejemplo que resuelve lo que planteas en el comentario.
En resumen, el programa pide que se introduzca una hora (utilizando el formato hh:mm:ss). En caso de ser válido el dato se convierte a segundos y se divide por el número total de segundos que tiene un día: 86400.
Busca en la entrada el ejemplo titulado: "A partir de una hora se obtiene fracción del día".
Espero que sea de utilidad.

Gracias por el comentario.

Nancy dijo...

Hola que tal yo quisiera saber si es posible contar o mejor aun imprimir todos los martes(en fechas) que se encuentran entre una fecha y otra, si es así que métodos debería emplear?

Pherkad dijo...

Hola Nancy
He incluido un ejemplo que obtiene y cuenta los días que sean martes entre dos fechas.

Localiza en la entrada el ejemplo titulado "Obtener y contar los días que sean martes entre dos fechas".

En este caso se utiliza la función weekday() que devuelve el número de día de semana dada una fecha, teniendo en cuenta que el lunes se corresponde con el valor 0, el martes con 1, etc. También, puedes utilizar la función isoweekday() que hace lo mismo pero comenzando a numerar los días desde el valor 1.

Saludos