如何在Python中确定datetime.strftime(...)的编码?

时间:2013-10-16 20:12:39

标签: python datetime encoding unicode

我想创建一个“unicode三明治”,其中包含一些日期/时间值,并且与区域设置无关。对于初学者来说,术语unicode三明治描述了从字节转换为unicode并返回程序边界的做法,即外部的字节和内部的unicode。

我今天早上看了Ned Batchelder's excellent video on unicode,并试图将我的一些代码转换为与他明智的建议一致。

我遇到的问题是我无法确定如何确定str(date)或其等价物返回的字符串的编码。我的想法是做这样的事情,为了清晰起见,有点冗长:

date_str_encoding = some_magical_method_I_have_yet_to_discover()
date = datetime.datetime(2013, 10, 16).date()
date_str = date.strftime('%A %B %d, &Y')  # perhaps 'Sábado Octubre 19, 2013'
date_unicode = date_str.decode(date_str_encoding)

Ned的unicode“生活中的事实”之一是“你无法推断出字节的编码。你必须被告知或者你必须猜测。”不幸的是,我在日期时间的Python文档中找不到特定的细节。

另一篇SO帖子提到了locale.getlocale()的使用,但是我返回(None,None)。

如何在运行时可靠地发现Python日期字符串的编码?

2 个答案:

答案 0 :(得分:4)

在CPython 2.7中,datetime.date.strftimetime.strftime的包装器,而后者又是posix strftime(3)的包装器。原则上,这取决于LC_TIME的区域设置类别。因此,您正在寻找的是:

import locale
def date_format_encoding():
    return locale.getlocale(locale.LC_TIME)[1] or locale.getpreferredencoding()

以下是datetime.date.__str__的解构,在编辑问题之前有相关内容。

在CPython 2.7中,datetime.date.__str__在C中实现,它是:

static PyObject *
date_str(PyDateTime_Date *self)
{
    return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
}

datetime.date.isoformat依次在C中实现:

static char *
isoformat_date(PyDateTime_Date *dt, char buffer[], int bufflen)
{
    int x;
    x = PyOS_snprintf(buffer, bufflen,
                      "%04d-%02d-%02d",
                      GET_YEAR(dt), GET_MONTH(dt), GET_DAY(dt));
    assert(bufflen >= x);
    return buffer + x;
}

基本上,str(datetime.date)返回的字节绝不是数字和“ - ”的ascii代码以外的任何字节。 总是正确地说:

str(my_date).decode('ascii')

答案 1 :(得分:2)

为什么不完全跳过date_strunicode构造函数接受日期对象。

>>> date_unicode = unicode(date)
>>> date_unicode
u'2013-10-16'

在内部,这会调用str(date)。然后它解码这些字节。所以它相当于显式创建字节然后解码它们,但在我看来更清楚阅读。并且值得养成使用unicode而不是显式使用strdecode的习惯,因为某些对象将定义一个__unicode__方法,该方法可以返回规范的Unicode表示而不进行完全通过__str__。日期没有。

文档说:

  

对于日期d,str(d)相当于d.isoformat()。

定义为:

  

返回表示ISO 8601格式的日期字符串'YYYY-MM-DD'。例如,date(2002,12,4).isoformat()=='2002-12-04'。

所以那也是ASCII。如果您的默认编码无法解码ASCII,那么您必须学习如何处理这种情况。