如何使用python_dateutil 1.5'解析'函数来使用unicode?

时间:2012-01-17 14:12:24

标签: python datetime internationalization

我需要Python_dateutil 1.5 parse()使用Unicode月份名称。

如果使用fuzzy = True,它会跳过月份名称并生成月份= 1的结果

当我在没有模糊参数的情况下使用它时,我得到了下一个例外:

from dateutil.parser import parserinfo, parser, parse

class myparserinfo(parserinfo):
    MONTHS = parserinfo.MONTHS[:]
    MONTHS[3] = (u"Foo", u"Foo", u"Июнь")


>>> test = unicode('8th of Июнь', 'utf-8')
>>> tester = parse(test, parserinfo=myparserinfo())
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Python27\lib\site-packages\python_dateutil-1.5-py2.7.egg\dateutil\parser.py", line 695, in parse
    return parser(parserinfo).parse(timestr, **kwargs)
  File "C:\Python27\lib\site-packages\python_dateutil-1.5-py2.7.egg\dateutil\parser.py", line 303, in parse
    raise ValueError, "unknown string format"
ValueError: unknown string format

2 个答案:

答案 0 :(得分:8)

Rik Poggi是对的,字符串'Июнь'不能是python-dateutil的一个月。稍微深入dateutil/parser.py,基本问题是这个模块只有国际化,足以处理西欧拉丁语脚本语言。它不是为了能够使用非拉丁文脚本(例如Cyrillic)处理俄语等语言而设计的。

最大的障碍是dateutil/parser.py:45-48,其中词法分析器class _timelex定义了可用于令牌的字符,包括月份和日期名称:

class _timelex(object):
    def __init__(self, instream):
        # ... [some material omitted] ...
        self.wordchars = ('abcdfeghijklmnopqrstuvwxyz'
                          'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'
                          'ßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ'
                          'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ')
        self.numchars = '0123456789'
        self.whitespace = ' \t\r\n'

由于wordchars不包含西里尔字母,_timelex会将日期字符串中的每个字节作为单独的字符发出。这是Rik观察到的。

另一个重大障碍是dateutil在内部使用Python字节字符串而不是Unicode字符串进行所有处理。这意味着,即使_timelex被扩展为接受西里尔字母,那么在处理字节和字符之间仍然存在不匹配,以及由调用者和python_dateutil源代码之间的字符串编码差异引起的问题。

还有其他一些小问题,例如假设每个月的名字长度至少为3个字符(日语不是这样),以及与公历相关的许多细节。 wordchars字段从parserinfo中获取(如果存在)会很有帮助,因此parserinfo可以为其月份和日期名称定义正确的字符集。

python_dateutil v 2.0已移植到Python 3,但上述设计问题没有明显改变。 2.0和1.5之间的差异是处理Pyhon语言的变化,而不是dateutil的设计和数据结构。

Oleg,你能够修改parserinfo,我怀疑你成功了,因为你的测试代码没有使用parser()的{​​{1}}(和_timelex)。你本质上提供了自己的解析器和词法分析器。

纠正此问题需要对python_dateutil的文本处理进行相当大的改进。如果有人用这个改变制作一个补丁,并且包维护者能够合并它,那将是很棒的。

答案 1 :(得分:3)

我查看了dateutil/parser.py中的源代码,我基本上发现字符串 'Июнь'不能是dateutil的一个月

问题在timestr被拆分时开始。

在第349行,你有:

l = _timelex.split(timestr)

,因为_timelex.split的定义如下:

def split(cls, s):      # at line 142
    return list(cls(s))

你得到l

['8', 'th', ' ', 'of', ' ', '\x18', '\x04', 'N', '\x04', '=', '\x04', 'L', '\x04']

而不是(或多或少)人们所期望的:

[u'8th', u'of', u'\u0418\u044e\u043d\u044c']

因此月检查返回None,这会导致异常。

# Check month name
value = info.month(l[i])

可能的解决方法:

用英语翻译所有内容,然后用俄语翻译。

示例:

dictionary = {u"Июнь": 'June', u'ноябрь': 'November'}

for russian,english in dictionary.items():
    test = test.replace(russian,english)