【问题标题】:python: convert pywintyptes.datetime to datetime.datetimepython:将 pywintypes.datetime 转换为 datetime.datetime
【发布时间】:2016-08-18 22:12:51
【问题描述】:

我正在使用 pywin32 读取/写入 Excel 文件。我在 Excel 中有一些日期,以 yyyy-mm-dd hh:mm:ss 格式存储。我想将它们作为 datetime.datetime 对象导入 Python。这是我开始的代码行:

prior_datetime = datetime.strptime(excel_ws.Cells(2, 4).Value, '%Y-%m-%d %H:%M:%S')

那没用。我得到了错误:

strptime() argument 1 must be str, not pywintypes.datetime

我尝试将其转换为字符串,如下所示:

prior_datetime = datetime.strptime(str(excel_ws.Cells(2, 4).Value), '%Y-%m-%d %H:%M:%S')

那也没用。我得到了错误:

ValueError: unconverted data remains: +00:00

然后我尝试了一些不同的东西:

prior_datetime = datetime.fromtimestamp(int(excel_ws.Cells(2, 4).Value))

仍然没有运气。错误:

TypeError: a float is required.

投射到浮点数没有帮助。也不是整数。 (嘿,此时我已经绝望了。)

我可能找错了地方,但我很难找到任何关于 pywin32 或 pywintypes 或 pywintypes.datetime 的好的文档。

有什么帮助吗?

【问题讨论】:

  • 你能告诉我们这个字符串是什么样子的吗? str(excel_ws.Cells(2, 4).Value)
  • 你考虑过使用openpyxl吗?它不需要安装或自动化的 Excel 版本,并为您处理将带有日期的单元格转换为本机 python 日期时间...
  • 当然。我刚刚提交了一份打印声明,这就是它的样子:2016-04-01 17:29:25+00:00 现在我觉得不早点这样做很愚蠢。如果它总是在最后添加一个“+00:00”,显然我可以使用一个简单的拼接来得到我需要的东西。但是,我仍然想知道是否有更好的方法来处理这个问题。
  • 我没有,乔恩。不需要安装 Excel 的好处对我来说并没有多大用处,因为我已经安装了 Excel,每天都在使用它,等等。但是,如果 PyWin32 继续因缺乏文档而激怒我,我可能很快就会检查出来。 (在此之前我使用的是 xlrd 和 xlwt,但 xlwt 无法处理 .xlsx,我想:当我可以使用 PyWin32 时,为什么还要使用 xlrd 和 PyWin32?所以这就是我现在所处的位置。)
  • 没有 windows 框,但这是我能找到的最接近的东西。我知道它使用pywintypes.Time 而不是.datetime 但值得一试。 timgolden.me.uk/python/win32_how_do_i/…

标签: python excel pywin32


【解决方案1】:

所以问题是+00:00 时区偏移。 Looking into this there's not an out of the box solution for Python

datetime.datetime.strptime("2016-04-01 17:29:25+00:00", '%Y-%m-%d %H:%M:%S %z')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/_strptime.py", line 324, in _strptime
    (bad_directive, format))
ValueError: 'z' is a bad directive in format '%Y-%m-%d %H:%M:%S %z'

一个创可贴的解决方案是去掉时区,但这感觉很恶心。

datetime.datetime.strptime("2016-04-01 17:29:25+00:00".rstrip("+00:00"), '%Y-%m-%d %H:%M:%S')
datetime.datetime(2016, 4, 1, 17, 29, 25)

环顾四周(如果您可以使用第三方库)dateutil 解决了这个问题,并且使用起来比datetime.strptime 更好。

在命令行上

pip install python-dateutil

代码

>>> import dateutil.parser                                                      
>>> dateutil.parser.parse("2016-04-01 17:29:25+00:00")
datetime.datetime(2016, 4, 1, 17, 29, 25, tzinfo=tzutc())

【讨论】:

  • 谢谢,亚历克斯。今晚,我只是去掉了时区。同意,感觉很恶心。对于未来(我将继续开发它),我将研究 dateutil。我一般讨厌日期/时间问题,所以这可能会有所帮助。感谢您的研究和解决方案。
  • 而不是 "2016-04-01 17:29:25+00:00".rstrip("+00:00"),我们应该使用 "2016-04-01 17:29: 25+00:00".rsplit("+00:00")[0]。使用 rstrip 会删除所有匹配字符的组合,这可能会产生一些意想不到的后果,docs.python.org/library/stdtypes.html
【解决方案2】:

我认为您与datetime.datetime.fromtimestamp 非常接近。一直采用这种方法,您可以使用 timestamp 方法将 pywintypes.datetime 对象转换为时间戳。为了安全使用时区,还请使用tzinfo 属性。有关完整语法,请参阅下面的 In [4]:

我在尝试用几行 Excel 书籍制作 pd.DataFrame 时遇到了同样的问题。我不断收到这个可怕的 Python 已停止工作”对话框。

In [1]: pywindt
Out[1]: pywintypes.datetime(2018, 9, 13, 14, 2, 24, tzinfo=TimeZoneInfo('GMT Standard Time', True))

In [2]: str(pywindt)
Out[2]: '2018-09-13 14:02:24+00:00'

In [3]: # Conversion takes place here!

In [4]: dt = datetime.datetime.fromtimestamp(
   ...:     timestamp=pywindt.timestamp(),
   ...:     tz=pywindt.tzinfo
   ...: )

In [5]: dt
Out[5]: datetime.datetime(2018, 9, 13, 14, 2, 24, tzinfo=TimeZoneInfo('GMT Standard Time', True))

In [6]: str(dt)
Out[6]: '2018-09-13 14:02:24+00:00'

作为后续,如果您需要检查单元格值是否为 pywintypes 日期时间,以下应该足够了。

In [7]: import pywintypes

In [8]: isinstance(pywindt, pywintypes.TimeType)
Out[8]: True

In [9]: # just out of curiousity

In [10]: isinstance(dt, pywintypes.TimeType)
Out[10]: False

【讨论】:

    【解决方案3】:

    Pandas 也有类似的解决方案,使用 pd.Timestamp()

    插入pywintype.datetime 对象作为参数并设置unit='s'(表示秒,或输入时间戳所在的任何单位)。

    对于熊猫系列:

    def convert(time):
    
        return pd.Timestamp(time.timestamp(), unit = 's')
    
    
    newSeries = oldSeries.apply(convert)
    

    【讨论】:

      【解决方案4】:

      添加一个将 pywintypes.datetime 转换为 datetime.datetime 的简单选项

      通过将任何 datetime.datetime 类型添加到 pywintypes.datetime 将导致转换为 datetime.dateime 类型。例如,这可以使用零增量来完成。

      对于原始问题的情况,无需额外模块即可使用以下内容

      desired_datetime_type = excel_ws.Cells(2, 4).Value + datetime.timedelta(0)
      

      【讨论】:

        【解决方案5】:

        你可以试试这样的

        prior_datetime = datetime.strptime((str(excel_ws.Cells(2, 4).Value)).rstrip("+00:00"), '%Y-%m-%d %H:%M:%S')
        

        【讨论】:

          【解决方案6】:

          我看到很多使用 rstrip 的建议。我发现当时间以 00 结束时不起作用。

          >>> oltime='2020-06-21 19:50:00+00:00'
          >>> str(oltime).rstrip("+00:00").strip()
          '2020-06-21 19:5'
          

          我建议使用替换

          >>> str(oltime).replace('+00:00', '')
          '2020-06-21 19:50:00'
          >>> 
          

          这是因为 rstrip 从字符串的左端开始删除每个字符的所有实例并向右工作:

          >>> str(oltime).rstrip('+0:')
          '2020-06-21 19:5'
          >>> 
          

          【讨论】:

            【解决方案7】:

            在上面 Alex 的回答中,如果你删除 %S 和 %z 之间的空格,使用 python 3.8.3rc1 和 datetime 它可以工作:

            >>> import datetime
            >>> datetime.datetime.strptime("2016-04-01 17:29:25+00:00", '%Y-%m-%d %H:%M:%S%z')
            datetime.datetime(2016, 4, 1, 17, 29, 25, tzinfo=datetime.timezone.utc)
            

            【讨论】:

              【解决方案8】:

              如果时区的 .rstrip 感觉太恶心,我有下面正则表达式的解决方案。

              如果时区实际上包含在返回的数字格式中,应该能够处理!

              from datetime import datetime
              import re
              def xldatetime_to_datetime(xl_datetime):
                      """
                      takes the str() value of a  pywintypes.datetime object and 
                      converts it to a datetime.datetime object via regular expression
                      """
                      p = re.compile('(?<=\d{4}(-\d{2}){2}\s\d{2}(:\d{2}){2})\+\d{2}:\d{2}')
                      #2021-07-12 08:26:04+00:00 -> 2021-07-12 08:26:04
                      xl_datetime = p.sub('',xl_datetime)
                      py_datetime = datetime.strptime(xl_datetime,'%Y-%m-%d %H:%M:%S')
                      return py_datetime
              

              【讨论】:

                【解决方案9】:

                AlexLordThorsen 的回答非常接近。您必须将字符串中的每个字符与正确的指令匹配。 AlexLordThorsen 代码尝试将 'Space' 字符串与时区指令 %z 匹配,这是错误的。下面是解释得更好的图片

                以下更正的代码将起作用

                >>> datetime.datetime.strptime("2016-04-01 17:29:25+00:00", '%Y-%m-%d %H:%M:%S%z')
                datetime.datetime(2016, 4, 1, 17, 29, 25, tzinfo=datetime.timezone.utc)
                

                【讨论】:

                  猜你喜欢
                  • 2011-12-22
                  • 1970-01-01
                  • 2012-03-23
                  • 2022-06-15
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-09-16
                  • 1970-01-01
                  • 2020-09-05
                  相关资源
                  最近更新 更多