Comment puis-je convertir une date Excel (sous forme de nombre) en une date appropriée en Python?
Vous pouvez utiliser xlrd .
Depuis sa documentation , vous pouvez lire que les dates sont toujours stockées sous forme de nombres; Cependant, vous pouvez utiliser xldate_as_Tuple
pour le convertir en une date python.
Remarque: la version sur PyPI semble plus à jour que celle disponible sur le site Web de xlrd.
Après les tests et quelques jours d'attente pour les commentaires, je vais svn-commit la toute nouvelle fonction suivante dans le module xldate de xlrd ... notez qu'elle ne sera pas disponible pour les intrans qui exécutent encore Python 2.1 ou 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)
)
Voici la version sans ceinture de sécurité, avec les doigts nus, à utiliser à vos risques:
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)
)
xlrd.xldate_as_Tuple
est agréable, mais il y a xlrd.xldate.xldate_as_datetime
qui convertit également en date/heure.
import xlrd
wb = xlrd.open_workbook(filename)
xlrd.xldate.xldate_as_datetime(41889, wb.datemode)
=> datetime.datetime(2014, 9, 7, 0, 0)
Veuillez vous référer à ce lien: Lecture de la date sous forme de chaîne non flottante d'Excel avec python xlrd
cela a fonctionné pour moi:
dans le coup cela le lien a:
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
Situation attendue
# Wrong output from cell_values()
42884.0
# Expected output
2017-5-29
Exemple: Soit valeurs_cellule (2,2) à partir du numéro de feuille 0 sera la date Ciblée
Obtenir les variables requises comme suit
workbook = xlrd.open_workbook("target.xlsx")
sheet = workbook.sheet_by_index(0)
wrongValue = sheet.cell_value(2,2)
Et utilisez xldate_as_Tuple
y, m, d, h, i, s = xlrd.xldate_as_Tuple(wrongValue, workbook.datemode)
print("{0} - {1} - {2}".format(y, m, d))
C'est ma solution
Si vous utilisez des pandas et que votre read_Excel lit dans Date mal formaté en chiffres Excel et doit récupérer les dates réelles derrière ...
Le lambda function
appliqué sur la colonne utilise xlrd pour récupérer la date de retour
import xlrd
df['possible_intdate'] = df['possible_intdate'].apply(lambda s: xlrd.xldate.xldate_as_datetime(s, 0))
>> df['possible_intdate']
dtype('<M8[ns]')
Excel stocke les dates et les heures sous forme de nombre représentant le nombre de jours depuis 1900-Jan-0. Si vous souhaitez obtenir les dates au format de date à l'aide de python, il vous suffit de soustraire 2 jours de la colonne des jours, comme indiqué ci-dessous:
Date = sheet.cell (1,0) .value-2 // en python
dans la colonne 1 de mon Excel, j'ai la commande de date et plus qui me donne les valeurs de date moins 2 jours, ce qui est identique à la date présente dans ma feuille Excel
Pour rapide et sale:
year, month, day, hour, minute, second = xlrd.xldate_as_Tuple(excelDate, wb.datemode)
whatYouWant = str(month)+'/'+str(day)+'/'+str(year)
Comme il est possible que vos fichiers Excel proviennent d’ordinateurs/de personnes différentes; il y a une chance que le formatage soit en désordre; alors soyez très prudent.
Je viens d'importer des données de 50 excentres numéros où les dates étaient saisies dans DD/MM/YYYY
ou DD-MM-YYYY
, mais la plupart des fichiers Excel stockés les ont conservés sous la forme MM/DD/YYYY
(probablement parce que les ordinateurs étaient configurés avec en-us
au lieu de en-gb
ou en-in
).
Encore plus irritant était le fait que les dates supérieures à 13/MM/YYYY
étaient encore au format DD/MM/YYYY
. Il y avait donc des variations dans les fichiers Excel.
La solution la plus fiable que j'ai trouvée consistait à définir manuellement la colonne Date sur chaque fichier Excel sur Texte brut. Utilisez ensuite ce code pour l'analyser:
if date_str_from_Excel:
try:
return datetime.strptime(date_str_from_Excel, '%d/%m/%Y')
except ValueError:
print("Unable to parse date")
Une combinaison de peuples post m'a donné la date et l'heure pour la conversion Excel. Je l'ai retourné comme une chaîne
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")