关于python:Django – DateTimeField收到了一个天真的日期时间

Django - DateTimeField received a naive datetime

基本上我有以下模型:

1
2
class Event(models.Model):
    start = models.DateTimeField(default=0)

当我尝试使用datetime.datetime.strptime创建一个对象时,我得到

1
2
3
4
5
6
Event.objects.create(start=datetime.datetime.strptime("02/03/2014 12:00 UTC",
                                                     "%d/%m/%Y %H:%M %Z"))

/usr/local/lib/python2.7/dist-packages/django/db/models/fields/__init__.py:903:
RuntimeWarning: DateTimeField Event.start received a naive datetime (2014-03-02
12:00:00) while time zone support is active.

我读过很多类似的文章,但我不明白为什么在我提出UTC (%Z)的论点时,它会产生错误。

事先谢谢。


由于您正在使用时区,并且正在"手动"创建日期时间对象,因此会记录该警告。我还建议您通过添加以下内容将警告转换为错误:

1
2
3
4
import warnings
warnings.filterwarnings('error',
                        r"DateTimeField .* received a naive datetime",
                        RuntimeWarning, r'django\.db\.models\.fields')

在您的settings.py中,通过这种方式,您可以更容易地发现此类不规则。

老实说,我不知道为什么,但实际上你的约会对象似乎不知道(如果你使用timezone.is_aware(),它应该返回false)。

要修复当前代码,我建议您使用django utilis作为时区:

1
2
from django.utils import timezone
timezone.make_aware(yourdate, timezone.get_current_timezone())

对于我的项目,我为日期创建了一个实用程序类,因为我面临这样的问题,您可以看一下(尤其是方法dateFromString)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
class DateUtils(object):

    @classmethod
    def currentTimezoneDate(cls):
       """
        Returns an aware datetime object based on current timezone.

        :return: datetime: date
       """

        return timezone.make_aware(datetime.now(), timezone.get_current_timezone())


    @classmethod
    def currentTimezoneOffset(cls):
       """
        Returns the offset (expressed in hours) between current timezone and UTC.

        :return: int: offset
       """

        offset = cls.currentTimezoneDate().utcoffset()
        return int(offset.total_seconds() / 60 / 60)


    @classmethod
    def UTCDate(cls, year, month, day, hour=0, minute=0, second=0, microsecond=0):
       """
        Creates an aware UTC datetime object.

        :return: datetime: date
       """

        d = datetime(year, month, day, hour, minute, second, microsecond)
        return timezone.make_aware(d, timezone.utc)


    @classmethod
    def asUTCDate(cls, date):
       """
        Get the UTC version of the given date.

        :param date: datetime: Date to be converted into UTC
        :return: datetime UTC date
       """

        if type(date) is Date:
            return timezone.make_aware(datetime(date.year, date.month, date.day), timezone.utc)
        if not timezone.is_aware(date):
            return timezone.make_aware(date, timezone.utc)
        return date.replace(tzinfo=timezone.utc)


    @classmethod
    def getJavaScriptDateFormatForCurrentLocale(cls):
       """
        Return a date mask string that will be understood and used by JavaScript.

        :return: str: Date mask string for JavaScript.
       """

        f = get_format('SHORT_DATE_FORMAT')
        return f.replace('Y', 'yyyy').replace('m', 'mm').replace('d', 'dd')


    @classmethod
    def getPythonDateFormatForCurrentLocale(cls):
       """
        Return a date mask string that will be understood and used by Python.

        :return: str: Date mask string for Python.
       """

        f = get_format('SHORT_DATE_FORMAT')
        return f.replace('Y', '%Y').replace('m', '%m').replace('d', '%d')


    @classmethod
    def dateFromString(cls, string, format=None, utc=True):
       """
        Returns a datetime object from the given string.

        :param string: str: A date string
        :param format: str: The format of the date
        :return: datetime: date
       """

        date = datetime.strptime(string, format or cls.getPythonDateFormatForCurrentLocale())
        if utc:
            return cls.asUTCDate(date)
        return date


    @classmethod
    def getFormattedStringForCurrentLocale(cls, date):
       """
        Return a date string formatted using current locale settings.

        :param date: datetime:
        :return: str: Formatted Date string.
       """

        return date.strftime(cls.getPythonDateFormatForCurrentLocale())


    @classmethod
    def randomDate(cls, start, end):
       """
        Return a random date between the 2 dates provided.
        See: http://stackoverflow.com/a/8170651/267719

        :param start: datetime: Min date.
        :param end: datetime: Max date.
        :return: datetime: Random date in range.
       """

        return start + timedelta(seconds=randint(0, int((end - start).total_seconds())))


    @classmethod
    def hourRange(cls, fromHour, toHour):
        n = fromHour
        hRange = [fromHour]
        while n != toHour:
            n += 1
            if n > 23:
                n = 0
            hRange.append(n)
        hRange.pop()
        return hRange

您需要使用Django的make_aware()函数。

1
2
3
4
5
from django.utils import timezone
#....

aware_date = timezone.make_aware(datetime.strptime("02/03/2014 12:00 UTC","%d/%m/%Y %H:%M %Z"), \
                                  timezone.get_default_timezone())