Python3.3: .format () with unicode format_spec

I have a datetime object, and my users provide their own format string to format the time as they like.

One way to find this is to use '{:...}'.format(mydatetime) .

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

English users can provide '{datetime:%B %d, %Y}' , which is formed until December 24, 2013.

Chinese users can provide '{datetime:%Y年%m月%d日}' (in the format YYYYMMDD, 年 = Year, 月 = Month, 日 = Day).

But when executing '{datetime:%Y年%m月%d日}'.format(datetime=d) , Python raises a UnicodeEncodingError: codec 'locale' cannot encode character '\ u5e74' at position 2: Incorrect sequence of bytes

I know there is a workaround that I can tell my Chinese users to display a format string, for example, '{datetime:%Y}年{datime:%m}月{datetime:%d}日' , but they couldn’t show unicode character character in format_spec format? How to solve this problem?

I am using windows.

thanks

+6
source share
1 answer

datetime.__format__ calls datetime.strftime , which does some preprocessing, and then calls time.strftime (source of CPython 3.3.3).

Windows time.strftime uses the multibyte C strftime instead of the wide format string function wcsftime . First, it must encode the format string according to the current locale by calling PyUnicode_EncodeLocale . This, in turn, calls the wcstombs CRT function (MSDN), which uses the currently configured language for the LC_CTYPE category. If the process currently uses the default locale “C”, wcstombs converts Latin-1 (codes <256) directly to bytes, and something else is an EILSEQ error, that is, “Illegal byte sequence”.

Use the local module to set a new locale. Actual locale names vary by platform, but with Microsoft setlocale you just have to set the language string and use the default codepage for that language. As a rule, you should not contact this for the library, and the application should configure the locale at startup. For instance:

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

If you want the formatting time to use local names (for example, month and day), then also set the LC_TIME category:

 >>> newlocale = locale.setlocale(locale.LC_TIME, 'chinese') >>> '{datetime:%B %d, %Y}'.format(datetime=d) '\u5341\u4e8c\u6708 25, 2013' 
+4
source

All Articles