使用dateutil.parser以另一种语言解析日期

时间:2013-11-12 11:14:19

标签: python date localization internationalization python-dateutil

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知道语言环境吗?

4 个答案:

答案 0 :(得分:3)

据我所知,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")
    

    我已经启动了一个fork,它从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。)

答案 1 :(得分: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和日期时间可能使用不同的时区定义)。

如果您只需要支持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

答案 2 :(得分:0)

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))

答案 3 :(得分:0)

我认为最好的解决方案是从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类。