Python3.3: .format() with unicode format_spec



我有datetime对象,我的用户提供他们自己的格式字符串,以他们喜欢的方式格式化时间。

我发现一种方法是使用'{:...}'.format(mydatetime)

lt = time.localtime(time.time())
d = datetime. datetime.fromtimestamp(time.mktime(lt))
print(userString.format(datetime=d))

英文用户可提供'{datetime:%B %d, %Y}',格式至2013年12月24日。

中国用户可以提供CCD_ 3(YYYYMMDD格式,年=年月=月日=天)。

但在执行'{datetime:%Y年%m月%d日}'.format(datetime=d)时,Python会引发UnicodeEncodingError:"locale"编解码器无法对位置2中的字符"\u5e74"进行编码:非法字节序列

我知道有一个解决办法,我可以告诉我的中国用户提供像'{datetime:%Y}年{datime:%m}月{datetime:%d}日'这样的格式字符串,但不能在format_spec中显示unicode字符?如何解决这个问题?

我正在使用Windows。

感谢

datetime.__format__调用datetime.strftime,后者进行一些预处理,然后调用time.strftime(CPython 3.3.3源代码)。

在Windows上,time.strftime使用C运行时的多字节字符串函数strftime,而不是宽字符串函数wcsftime。首先,它必须通过调用PyUnicode_EncodeLocale根据当前区域设置对格式字符串进行编码。这反过来调用CRT函数wcstombs(MSDN),该函数使用当前配置的LC_CTYPE类别的区域设置。如果进程当前使用默认的"C"语言环境,则wcstombs会将Latin-1(代码<256)直接转换为字节,其他任何操作都是EILSEQ错误,即"非法字节序列"。

使用区域设置模块设置新的区域设置。实际的区域设置名称因平台而异,但使用Microsoft的setlocale,您应该能够仅设置语言字符串并使用给定语言的默认代码页。一般来说,对于库来说,您不应该搞砸这一点,应用程序应该在启动时配置区域设置。例如:

>>> import datetime, locale
>>> oldlocale = locale.setlocale(locale.LC_CTYPE, None)
>>> oldlocale
'C'
>>> newlocale = locale.setlocale(locale.LC_CTYPE, 'chinese')
>>> d = datetime.datetime.now()
>>> '{datetime:%Y\u5e74%m\u6708%d\u65e5}'.format(datetime=d)
'2013\u5e7412\u670825\u65e5'

如果您希望格式化的时间使用特定于区域设置的名称(例如,月和日),那么也可以设置LC_TIME类别:

>>> newlocale = locale.setlocale(locale.LC_TIME, 'chinese')
>>> '{datetime:%B %d, %Y}'.format(datetime=d)              
'u5341u4e8cu6708 25, 2013'

最新更新