python:将 pywintyptes.datetime 转换为 datetime.datetime

问题描述 投票:0回答:10

我正在使用 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 。

有什么帮助吗?

python excel pywin32
10个回答
9
投票

所以问题是

+00:00
时区偏移。 仔细研究一下,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())

8
投票

我认为你与

datetime.datetime.fromtimestamp
非常接近。一直采用这种方法,您可以使用其
pywintypes.datetime
方法将
timestamp
对象转换为时间戳。为了确保时区安全,还可以使用
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

2
投票

Pandas 有类似的解决方案,使用

pd.Timestamp()

插入

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

对于熊猫系列:

def convert(time):

    return pd.Timestamp(time.timestamp(), unit = 's')


newSeries = oldSeries.apply(convert)

1
投票

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

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

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

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

0
投票

你可以尝试这样的事情

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

0
投票

我看到很多使用 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'
>>> 

0
投票

在上面 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)

0
投票

如果时区的 .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

0
投票

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)

0
投票

您也可以只使用 datetime.datetime.fromisoformat(),这可能是最简单的方法。

import datetime 

datetime.datetime.fromisoformat("2016-04-01 17:29:25+00:00")
© www.soinside.com 2019 - 2024. All rights reserved.