【问题标题】:How to convert a given ordinal number (from Excel) to a date如何将给定的序数(来自 Excel)转换为日期
【发布时间】:2015-06-05 21:13:27
【问题描述】:

我有一个值 38142 我需要使用 python 将其转换为日期格式。 如果在 excel 中使用此数字并在那时右键单击并格式化单元格,则该值将转换为 04/06/2004,我需要使用 python 获得相同的结果。我怎样才能做到这一点

【问题讨论】:

  • 这是一个奇怪的序数;你确定 04/06/2004 是正确的吗?如果值 38142 代表 ,那么这将是 1993/12/25 或 1993/10/27 的偏移量,具体取决于您对月份的解释。
  • Formula to convert date to number 建议它应该是自 1900/01/01 以来的天数,这就是 date.fromordinal() 所做的。但是那个数字少了一个数字。
  • 我的文件的值我不知道它的序号或我的客户说它的序号并告诉我“如果你想找到实际日期,只需在 Excel 中为给定值格式化单元格那个时候我得到了这个价值”@MartijnPieters
  • 是的,它确实是一个序数,但 Excel 中有一个错误,导致我对我最初的理论不以为然。

标签: python excel python-2.7 date


【解决方案1】:

Excel 中的偏移量是自 1900/01/01 以来的天数,1 是 1900 年 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 从 Lotus 1-2-3 继承了 leap year bug,并将 1900 年视为闰年。上面的代码为5960 返回datetime(1900, 2, 28, 0, 0) 来纠正这个问题,在[59.0 - 61.0) 范围内的小数值都是00:00:00.0 到23:59:59.999999 之间的时间天。

上面还支持用分数表示时间的序列,但由于 Excel 不支持微秒,所以这些被删除了。

【讨论】:

  • 太完美了,非常感谢@Martijn Pieters
  • @Krish:该漏洞被 Joel Spolsky 推广:My First BillG Review
  • 您确定纪元不是 1899 年 12 月 31 日吗? datetime(1899, 12, 31) + timedelta(ordinal - (ordinal > 59))
  • @J.F.Sebastian 我在这里坚持使用 Excel 文档;相对于 1900-01-01 减去 1 在这里没什么区别。
  • @FinanceGuyThatCantCode:_epoch 参数用于将值缓存为 局部变量,仅此而已。这有助于避免必须为每次调用创建它,或者必须查找全局(稍微慢一些)。
【解决方案2】:
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)

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

【讨论】:

    【解决方案3】:

    我会推荐以下内容:

    import pandas as pd
    
    def convert_excel_time(excel_time):
    
        return pd.to_datetime('1900-01-01') + pd.to_timedelta(excel_time,'D')
    

    或者

    import datetime
    
    def xldate_to_datetime(xldate):
        temp = datetime.datetime(1900, 1, 1)
        delta = datetime.timedelta(days=xldate)
        return temp+delta
    

    取自 https://gist.github.com/oag335/9959241

    【讨论】:

    • xldate_to_datetime(44000) 给出 2020-06-20 答案是 2020-06-18
    • @PoornaPrudhvi 是正确的;基准日期应为 1899-12-30。一天的偏移量,因为我们应该添加到 12 月 31 日,并且在接受的答案中提到闰年错误的另一天偏移量 b/c。
    【解决方案4】:

    我在尝试执行上述相同操作时遇到了这个问题,但针对 df.xml 中的整个列。我做了这个功能,它为我做了:

    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 的副本(不更改原始文件)。

    顺便说一句,部分受此启发 (https://gist.github.com/oag335/9959241)。

    【讨论】:

    • 非常感谢
    【解决方案5】:

    如果您正在使用 Pandas,这可能会很有用

        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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-22
      • 2019-08-23
      • 1970-01-01
      • 2018-04-16
      • 1970-01-01
      • 2012-11-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多