在 Python 中解析 OFX 日期时间

Posted

技术标签:

【中文标题】在 Python 中解析 OFX 日期时间【英文标题】:Parsing OFX datetime in Python 【发布时间】:2022-01-22 12:15:05 【问题描述】:

我正在尝试在 Python 中解析 OFX 2.3 规范中指定的日期时间。我相信这是一种自定义格式,但如果它有名称,请随时告诉我。规范声明如下:

有一种表示日期、时间和时区的格式。完整的表格是: YYYYMMDDHHMMSS.XXX [gmt offset[:tz name]]

例如,“19961005132200.124[-5:EST]”表示东部标准时间 1996 年 10 月 5 日下午 1:22 和 124 毫秒。这与下午 6:22 相同。格林威治标准时间 (GMT)。

这是我目前的尝试:

from datetime import datetime

date_str = "19961005132200.124[EST]"
date = datetime.strptime(date_str, "%Y%m%d%H%M%S.%f[%Z]")

这个部分示例到目前为止有效,但缺少 GMT 偏移部分(-5 in [-5:EST])。我不确定如何指定最多两位数的时区偏移量。

【问题讨论】:

我看到的问题是 Python 内置的 strptime 在这里会遇到困难 - %z 不会解析单个数字偏移小时,%Z 不会解析一些(可能)不明确的时区缩写。不确定是否例如dateutil 的解析器在这里也有帮助。考虑过编写自定义解析器吗? @MrFuppes 老实说,我不介意写一个。我只是想确认我没有重新发明***——奇怪的是 OFX 没有使用更标准的东西。感谢您的帮助! 我反过来问,为什么 OFX 不使用像 ISO 8601 这样的常用标准? ;-) 我猜这几个字符不会让存储成本爆炸式增长... 【参考方案1】:

这里首先要注意一些事情(如评论):

Python 内置 strptime 在这里会遇到困难 - %z 不会解析单个数字偏移小时,%Z 不会解析一些(可能)不明确的时区缩写。

然后,OFX 银行 2.3 版文档(第 3.2.8.2 节日期和日期时间)给我留下了一些问题:

UTC 偏移量是可选的吗? 为什么将 EST 称为时区,而它只是一个缩写词? 为什么在示例中 UTC 偏移量是 -5 小时,而在 1996 年 10 月 5 日,美国/东部时间是 UTC-4? 指定了分钟的偏移量,例如+5:30 亚洲/加尔各答? (有意见)为什么要重新发明***,而不是使用 ISO 8601 等常用标准?

无论如何,这是一个自定义解析器的尝试:

from datetime import datetime, timedelta, timezone
from zoneinfo import ZoneInfo

def parseOFXdatetime(s, tzinfos=None, _tz=None):
    """
    parse OFX datetime string to an aware Python datetime object.
    """
    # first, treat formats that have no UTC offset specified.
    if not '[' in s:
        # just make sure default format is satisfied by filling with zeros if needed
        s = s.ljust(14, '0') + '.000' if not '.' in s else s
        return datetime.strptime(s, "%Y%m%d%H%M%S.%f").replace(tzinfo=timezone.utc)

    # offset and tz are specified, so first get the date/time, offset and tzname components
    s, off = s.strip(']').split('[')
    off, name = off.split(':')
    s = s.ljust(14, '0') + '.000' if not '.' in s else s
    # if tzinfos are specified, map the tz name:
    if tzinfos:
        _tz = tzinfos.get(name) # this might still leave _tz as None...
    if not _tz: # ...so we derive a tz from a timedelta
        _tz = timezone(timedelta(hours=int(off)), name=name)
    return datetime.strptime(s, "%Y%m%d%H%M%S.%f").replace(tzinfo=_tz)


# some test strings

t = ["19961005132200.124[-5:EST]", "19961005132200.124", "199610051322", "19961005",
     "199610051322[-5:EST]", "19961005[-5:EST]"]

for s in t:
    print(# normal parsing
          f's\n repr(parseOFXdatetime(s))\n'
          # parsing with tzinfo mapping supplied; abbreviation -> timezone object
          f' repr(parseOFXdatetime(s, tzinfos="EST": ZoneInfo("US/Eastern")))\n\n')

【讨论】:

感谢您花时间实现自定义解析器!我也很困惑为什么 OFX 没有采用广泛使用的标准。也许他们的下一个版本 FDX 会有更好的支持,因为我相信它将是一个 REST API。

以上是关于在 Python 中解析 OFX 日期时间的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 ofx4j 解析格式错误的 xml (ofx)?

使用WTForms Flask解析日期 - Python

如何在Python中将字符串解析为日期时间

如何在 Power BI 中解析 a-ofx-version-1-0-2-file?

Python:检查解析的日期时间是不是具有正确的时区

使用 Coldfusion 解析 OFX(开放金融交换文档)