Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何将给定序号(从Excel)转换为日期_Python_Excel_Python 2.7_Date - Fatal编程技术网

Python 如何将给定序号(从Excel)转换为日期

Python 如何将给定序号(从Excel)转换为日期,python,excel,python-2.7,date,Python,Excel,Python 2.7,Date,我有一个值38142,我需要使用python将其转换为日期格式。 如果在excel中使用此数字,然后右键单击并格式化单元格,此时该值将转换为04/06/2004,我需要使用python获得相同的结果。如何实现这一点Excel中的偏移量是自1900/01/01以来的天数,1是1900年1月1日,因此将天数作为时间增量添加到1899/12/31: from datetime import datetime, timedelta def from_excel_ordinal(ordinal, _ep

我有一个值38142,我需要使用python将其转换为日期格式。
如果在excel中使用此数字,然后右键单击并格式化单元格,此时该值将转换为04/06/2004,我需要使用python获得相同的结果。如何实现这一点

Excel中的偏移量是自1900/01/01以来的天数,
1
是1900年1月1日,因此将天数作为时间增量添加到1899/12/31:

from datetime import datetime, timedelta

def from_excel_ordinal(ordinal, _epoch0=datetime(1899, 12, 31)):
    if ordinal >= 60:
        ordinal -= 1  # Excel leap year bug, 1900 is not a leap year!
    return (_epoch0 + timedelta(days=ordinal)).replace(microsecond=0)
对于1900/02/28之后的任何日期,您必须将序号调整一天;Excel从Lotus1-2-3继承了一个新概念,并将1900视为闰年。上面的代码返回
59
60
datetime(1900,2,28,0,0)
,以更正此错误,小数点在[59.0-61.0]范围内,都是当天00:00:00.0和23:59:59.99999之间的时间

上面的代码还支持用分数表示时间的序列,但由于Excel不支持微秒,因此会删除这些序列

from datetime import datetime, timedelta

def from_excel_ordinal(ordinal, epoch=datetime(1900, 1, 1)):
    # Adapted from above, thanks to @Martijn Pieters 

    if ordinal > 59:
        ordinal -= 1  # Excel leap year bug, 1900 is not a leap year!
    inDays = int(ordinal)
    frac = ordinal - inDays
    inSecs = int(round(frac * 86400.0))

    return epoch + timedelta(days=inDays - 1, seconds=inSecs) # epoch is day 1

excelDT = 42548.75001           # Float representation of 27/06/2016  6:00:01 PM in Excel format  
pyDT = from_excel_ordinal(excelDT)

上述答案仅适用于日期值,但我在这里扩展了上述解决方案,以包括时间并返回日期时间值。

我将推荐以下内容:

import pandas as pd

def convert_excel_time(excel_time):

    return pd.to_datetime('1900-01-01') + pd.to_timedelta(excel_time,'D')

摘自

我在尝试执行上述操作时遇到了这个问题,但针对df中的整个列。我创建了这个函数,它为我做到了:

import pandas as pd    
from datetime import datetime, timedelta
import copy as cp

def xlDateConv(df, *cols):      
    tempDt = []
    fin = cp.deepcopy(df)
    for col in [*cols]:
        for i in range(len(fin[col])):
            tempDate = datetime(1900, 1, 1)
            delta = timedelta(float(fin[col][i]))
            tempDt.append(pd.to_datetime(tempDate+delta))

        fin[col] = tempDt
        tempDt = []
    return fin
请注意,您需要将每个列(作为字符串)作为一个参数键入,这很可能会得到改进(例如,列列表作为输入)。此外,它还返回原始df的副本(不更改原始df)


顺便说一句,部分灵感来自此()。

如果您正在与熊猫合作,这可能会很有用

    import xlrd
    import datetime as dt
    
    def from_excel_datetime(x):
        return dt.datetime(*xlrd.xldate_as_tuple(x, datemode=0))
    
    df['date'] = df.excel_date.map(from_excel_datetime)
如果日期延迟了4年,您可以尝试使用datemode 1


:param datemode:0:1900为基础,1:1904为基础。

这是一个奇怪的顺序;你确定04/06/2004是正确的吗?如果值38142代表天,那么它将是1993/12/25或1993/10/27的偏移量,这取决于你对月份的理解。建议它应该是自1900/01/01以来的天数,这就是
date.fromordinal()
有。但该数字缺少一个数字。我的文件有一个值,我不知道它的序号与否。我的客户说它的序号,并告诉我“如果你想找到实际日期,只需在excel中对给定值进行格式化,我就得到了这个值”@martijnpieters是的,这确实是一个序数,但Excel中有一个错误,使我对我最初的理论大打折扣。相关的,老问题:太好了,非常感谢@MartijnPieters@Krish:这个错误是由Joel Spolsky推广的:你确定纪元不是1899年12月31日吗?
datetime(1899,12,31)+timedelta(序数-(序数>59)
@J.F.Sebastian我在这里坚持使用Excel文档;在这里减去一个相对于1900-01-01的值没有什么区别。@FinanceGuyThatCantCode:the
\u epoch
参数用于将值缓存为局部变量,仅此而已。这有助于避免为每次调用创建它,或查找全局变量(稍微慢一点)。非常感谢这个xldate-to-datetime(44000)给出了2020-06-20,答案是2020-06-18
    import xlrd
    import datetime as dt
    
    def from_excel_datetime(x):
        return dt.datetime(*xlrd.xldate_as_tuple(x, datemode=0))
    
    df['date'] = df.excel_date.map(from_excel_datetime)