2009-07-10 32 views
44

¿Cómo puedo convertir una fecha de Excel (en formato de número) a una fecha adecuada en Python?¿Cómo leo una fecha en formato Excel en Python?

+0

favor aclarar: dar un ejemplo de "datos de Excel (en un formato de número) " –

+5

Internamente, Excel almacena las fechas como números flotantes, y usted puede distinguir de los números" normales "solo por el formato de la celda. –

+1

@Roberto Liffredo, sí, sé que Excel almacenó las fechas como números flotantes, necesito convertirlas a una fecha adecuada y es por eso que estoy haciendo esta pregunta. @eliben, consulte el comentario de Roberto – Grzenio

Respuesta

62

Puede usar xlrd.

De su documentation, puede leer que las fechas siempre se almacenan como números; sin embargo, puede usar xldate_as_tuple para convertirlo a una fecha python.

Nota: la versión en el PyPI parece más actualizada que la disponible en el sitio web de xlrd.

+0

@Roberto: gracias por el recordatorio sobre el sitio web. –

24

Después de la prueba y de unos días de espera la retroalimentación, me svn-commit la siguiente función completamente nueva en el módulo xldate de xlrd ... tenga en cuenta que no estará disponible para los incondicionales que aún ejecutan Python 2.1 o 2.2.

## 
# Convert an Excel number (presumed to represent a date, a datetime or a time) into 
# a Python datetime.datetime 
# @param xldate The Excel number 
# @param datemode 0: 1900-based, 1: 1904-based. 
# <br>WARNING: when using this function to 
# interpret the contents of a workbook, you should pass in the Book.datemode 
# attribute of that workbook. Whether 
# the workbook has ever been anywhere near a Macintosh is irrelevant. 
# @return a datetime.datetime object, to the nearest_second. 
# <br>Special case: if 0.0 <= xldate < 1.0, it is assumed to represent a time; 
# a datetime.time object will be returned. 
# <br>Note: 1904-01-01 is not regarded as a valid date in the datemode 1 system; its "serial number" 
# is zero. 
# @throws XLDateNegative xldate < 0.00 
# @throws XLDateAmbiguous The 1900 leap-year problem (datemode == 0 and 1.0 <= xldate < 61.0) 
# @throws XLDateTooLarge Gregorian year 10000 or later 
# @throws XLDateBadDatemode datemode arg is neither 0 nor 1 
# @throws XLDateError Covers the 4 specific errors 

def xldate_as_datetime(xldate, datemode): 
    if datemode not in (0, 1): 
     raise XLDateBadDatemode(datemode) 
    if xldate == 0.00: 
     return datetime.time(0, 0, 0) 
    if xldate < 0.00: 
     raise XLDateNegative(xldate) 
    xldays = int(xldate) 
    frac = xldate - xldays 
    seconds = int(round(frac * 86400.0)) 
    assert 0 <= seconds <= 86400 
    if seconds == 86400: 
     seconds = 0 
     xldays += 1 
    if xldays >= _XLDAYS_TOO_LARGE[datemode]: 
     raise XLDateTooLarge(xldate) 

    if xldays == 0: 
     # second = seconds % 60; minutes = seconds // 60 
     minutes, second = divmod(seconds, 60) 
     # minute = minutes % 60; hour = minutes // 60 
     hour, minute = divmod(minutes, 60) 
     return datetime.time(hour, minute, second) 

    if xldays < 61 and datemode == 0: 
     raise XLDateAmbiguous(xldate) 

    return (
     datetime.datetime.fromordinal(xldays + 693594 + 1462 * datemode) 
     + datetime.timedelta(seconds=seconds) 
     ) 
+2

Hola @JohnMachin siento revivir un hilo viejo, pero ¿has cometido esto? Estoy en Ubuntu y Python 2.7 y no está presente en la versión que estoy usando. –

+2

La función 'xldate_as_datetime' se agregó al módulo' xldate' a partir de la versión xlrd 0.9.3 (lanzada a PyPI en abril de 2014). –

+0

'xldate_as_datetime' es una opción mucho más limpia que' xldate_as_tuple' en mi opinión – Paco

21

Aquí está el puño limpio no-cinturones de seguridad utilizan-a-propio-riesgo versión:

import datetime 

def minimalist_xldate_as_datetime(xldate, datemode): 
    # datemode: 0 for 1900-based, 1 for 1904-based 
    return (
     datetime.datetime(1899, 12, 30) 
     + datetime.timedelta(days=xldate + 1462 * datemode) 
     ) 
+4

Para las fechas Excel basadas en 1900 esto dará fechas '' incorrectas '' para las fechas Excel antes del 1 de marzo de 1900. Esto se debe a un error en Excel que lo hace (incorrectamente) creo que 1900 fue un año bisiesto. Consulte [artículo de Microsoft KB] (http://support.microsoft.com/kb/214326) – Ben

+2

y, además, para la suposición muy poco científica de que, por alguna razón, el comienzo del año en 1900 corresponde a un 1 . Como si fuera la Edad Media y no entendimos el concepto de 0; anima a Microsoft. – AER

0

Para una rápida y sucia:

year, month, day, hour, minute, second = xlrd.xldate_as_tuple(excelDate, wb.datemode) 
whatYouWant = str(month)+'/'+str(day)+'/'+str(year) 
4

Por favor refiérase a este enlace : Reading date as a string not float from excel using python xlrd

funcionó para mí:

en tiro esto el enlace tiene:

import datetime, xlrd 
book = xlrd.open_workbook("myfile.xls") 
sh = book.sheet_by_index(0) 
a1 = sh.cell_value(rowx=0, colx=0) 
a1_as_datetime = datetime.datetime(*xlrd.xldate_as_tuple(a1, book.datemode)) 
print 'datetime: %s' % a1_as_datetime 
+2

thx para copiar mi respuesta;) – jojo

+0

espero no haber hecho algo mal aquí, solo quiero dar una dirección a la respuesta correcta aquí. –

+0

¡Sin preocupaciones! Probablemente hubiera sido más adecuado poner un enlace a la pregunta duplicada como un comentario sobre esta pregunta, pero ponerlo como respuesta es, al menos para mí, también está bien. – jojo

17

xlrd.xldate_as_tuple es agradable, pero no hay xlrd.xldate.xldate_as_datetime que convierte a la fecha y hora también.

import xlrd 
wb = xlrd.open_workbook(filename) 
xlrd.xldate.xldate_as_datetime(41889, wb.datemode) 
=> datetime.datetime(2014, 9, 7, 0, 0) 
0

Una combinación de publicaciones de personas me dio la fecha y la hora para la conversión de Excel. Hice devolverlo como una cadena

def xldate_to_datetime(xldate): 
    tempDate = datetime.datetime(1900, 1, 1) 
    deltaDays = datetime.timedelta(days=int(xldate)) 
    secs = (int((xldate%1)*86400)-60) 
    detlaSeconds = datetime.timedelta(seconds=secs) 
    TheTime = (tempDate + deltaDays + detlaSeconds) 
    return TheTime.strftime("%Y-%m-%d %H:%M:%S") 
-1

Al convertir un archivo de Excel a CSV la fecha/hora de células se ve así:

foo, 16.03.2016 10:38, bar,

para convertir el valor de texto de fecha y hora a la fecha y hora de objetos pitón hacer esto:

from datetime import datetime 

date_object = datetime.strptime('3/16/2016 10:38', '%m/%d/%Y %H:%M') # excel format (CSV file) 

de impresión date_object volverá 2005-06-01 13:33:00

+0

OP quiere respuesta para xlrd, ya que xlrd regresa en flotación –

1

En caso de que esté usando pandas y sus lecturas de lectura_excel en formato de fecha como números de Excel incorrectamente, y necesita recuperar las fechas reales detrás de ...

El lambda function aplicada sobre la columna utiliza XLRD para recuperar la fecha de regreso

import xlrd 
df['possible_intdate'] = df['possible_intdate'].apply(lambda s: xlrd.xldate.xldate_as_datetime(s, 0)) 


>> df['possible_intdate'] 

    dtype('<M8[ns]') 
0

esperado situación

# Wrong output from cell_values() 
42884.0 

# Expected output 
2017-5-29 

Ejemplo: Supongamos cell_values ​​(2,2) de número de hoja será la fecha segmentada

obtener las variables necesarias como la siguiente

workbook = xlrd.open_workbook("target.xlsx") 

sheet = workbook.sheet_by_index(0) 

wrongValue = sheet.cell_value(2,2) 

y hacer uso de xldate_as_tuple

y, m, d, h, i, s = xlrd.xldate_as_tuple(wrongValue, workbook.datemode) 
print("{0} - {1} - {2}".format(y, m, d)) 

Esa es mi solución

Cuestiones relacionadas