我需要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
答案 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)