【问题标题】:Using dateutil.parser to parse a date in another language使用 dateutil.parser 解析另一种语言的日期
【发布时间】:2013-11-24 12:17:23
【问题描述】:

Dateutil 是解析字符串格式日期的好工具。例如

from dateutil.parser import parse
parse("Tue, 01 Oct 2013 14:26:00 -0300")

返回

datetime.datetime(2013, 10, 1, 14, 26, tzinfo=tzoffset(None, -10800))

然而,

parse("Ter, 01 Out 2013 14:26:00 -0300") # In portuguese

产生此错误:

ValueError: unknown string format

有人知道如何让 dateutil 了解语言环境吗?

【问题讨论】:

标签: python date localization internationalization python-dateutil


【解决方案1】:

据我所知,dateutil 不支持区域设置(还没有!)。

我能想到三个替代建议:

  • 日期和月份名称在dateutil.parser 中硬编码(作为parserinfo 类的一部分)。您可以将 parserinfo 子类化,并将这些名称替换为葡萄牙语的适当名称。

  • 修改 dateutil 以根据用户的区域设置获取日期和月份名称。所以你可以做类似的事情

    import locale
    locale.setlocale(locale.LC_ALL, "pt_PT")
    
    from dateutil.parser import parse
    parse("Ter, 01 Out 2013 14:26:00 -0300")
    

    我已经启动了一个分支,它从 calendar 模块(可识别语言环境)中获取名称来处理这个问题:https://github.com/alexwlchan/dateutil

    现在它适用于葡萄牙语(或似乎适用),但我想在向主分支提交补丁之前再考虑一下。特别是,如果它面对西欧语言中没有使用的字符,可能会发生怪异。我还没有测试过这个。 (见https://stackoverflow.com/a/8917539/1558022

  • 如果你没有绑定到 dateutil 模块,你可以使用 datetime 代替,它已经是语言环境感知的:

    from datetime import datetime, date
    import locale
    
    locale.setlocale(locale.LC_ALL, "pt_PT")
    datetime.strptime("Ter, 01 Out 2013 14:26:00 -0300",
                      "%a, %d %b %Y %H:%M:%S %z")
    

    (请注意,%z 令牌是 not consistently supported in datetime。)

【讨论】:

  • 您链接的答案是错误的。我在那里留下了相应的评论。
  • 我的意思是关于 %z 的答案。
【解决方案2】:

您可以使用PyICU 解析given format 中的本地化日期/时间字符串:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from datetime import datetime
import icu  # PyICU

df = icu.SimpleDateFormat(
               'EEE, dd MMM yyyy HH:mm:ss zzz', icu.Locale('pt_BR'))
ts = df.parse(u'Ter, 01 Out 2013 14:26:00 -0300')
print(datetime.utcfromtimestamp(ts))
# -> 2013-10-01 17:26:00 (UTC)

它适用于 Python 2/3。它不会修改全局状态(语言环境)。

如果您的实际输入时间字符串不包含明确的 utc 偏移量,那么您应该 specify a timezone to be used by ICU explicitly 否则您会得到错误的结果(ICU 和 datetime 可能使用不同的时区定义)。

如果您只需要支持 Python 3 并且不介意设置语言环境,那么您可以使用 datetime.strptime() 作为 @alexwlchan suggested

#!/usr/bin/env python3
import locale
from datetime import datetime

locale.setlocale(locale.LC_TIME, "pt_PT.UTF-8")
print(datetime.strptime("Ter, 01 Out 2013 14:26:00 -0300",
                        "%a, %d %b %Y %H:%M:%S %z")) # works on Python 3.2+
# -> 2013-10-01 14:26:00-03:00

【讨论】:

    【解决方案3】:
    from dateutil.parser import parse
    parse("Ter, 01 Out 2013 14:26:00 -0300",fuzzy=True)
    

    结果:

    datetime.datetime(2013, 1, 28, 14, 26, tzinfo=tzoffset(None, -10800))
    

    【讨论】:

      【解决方案4】:

      我认为最好的解决方案是从 dateutil 继承解析器并使用 calendar lib 常量。这是一个简单的解决方案,我没有大量测试,所以请谨慎使用。

      它非常简单,可以将 dateutil 本地化为多种语言。创建模块localeparseinfo.py

      import calendar
      from dateutil import parser
          
      class LocaleParserInfo(parser.parserinfo):
          WEEKDAYS = zip(calendar.day_abbr, calendar.day_name)
          MONTHS = list(zip(calendar.month_abbr, calendar.month_name))[1:]
      

      现在您可以使用新的 parseinfo 对象作为dateutil.parser 的参数。

      In [1]: import locale;locale.setlocale(locale.LC_ALL, "pt_BR.utf8")
      In [2]: from localeparserinfo import LocaleParserInfo                                   
      
      In [3]: from dateutil.parser import parse                                                
      
      In [4]: parse("Ter, 01 Out 2013 14:26:00 -0300", parserinfo=PtParserInfo())              
      Out[4]: datetime.datetime(2013, 10, 1, 14, 26, tzinfo=tzoffset(None, -10800))
      

      看起来这解决了很多不同的语言解析,但对于所有可能的日期和时间,它是一个不完整的解决方案。看看 dateutil parser.py,特别是 parserinfo 类变量。看看 HMS 变量和其他变量。

      您甚至可以将语言环境字符串作为参数传递给您的 parserinfo 类。

      【讨论】:

        猜你喜欢
        • 2018-02-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-16
        • 2019-11-10
        • 1970-01-01
        • 2014-03-12
        相关资源
        最近更新 更多