Python 如何在Django中舍入时区感知日期

Python 如何在Django中舍入时区感知日期,python,django,datetime,timezone,Python,Django,Datetime,Timezone,我正在尝试将默认时区datetime转换为localtime,并在Django视图中将时间舍入到15分钟。我有以下往返时间功能: def roundTime(dt=None, dateDelta=timedelta(minutes=1)): """Round a datetime object to a multiple of a timedelta dt : datetime.datetime object, default now. dateDelta : timed

我正在尝试将默认时区
datetime
转换为
localtime
,并在Django视图中将时间舍入到15分钟。我有以下往返时间功能:

def roundTime(dt=None, dateDelta=timedelta(minutes=1)):
    """Round a datetime object to a multiple of a timedelta
    dt : datetime.datetime object, default now.
    dateDelta : timedelta object, we round to a multiple of this, default 1 minute.
    Author: Thierry Husson 2012 - Use it as you want but don't blame me.
            Stijn Nevens 2014 - Changed to use only datetime objects as variables
    """
    roundTo = dateDelta.total_seconds()

    if dt == None:
        dt = datetime.now()
    seconds = (dt - dt.min).seconds
    # // is a floor division, not a comment on following line:
    rounding = (seconds+roundTo/2) // roundTo * roundTo
    return dt + timedelta(0,rounding-seconds,-dt.microsecond)
以下是我迄今为止所做的尝试:

mytime = roundTime(datetime.now(),timedelta(minutes=15)).strftime('%H:%M:%S') #works OK
mytime = datetime.strptime(str(mytime), '%H:%M:%S') #works OK
mytime = timezone.localtime(mytime) 
但最后一行给了我这个错误:

错误:astimezone()无法应用于原始日期时间

当我使用:

local_time = timezone.localtime(timezone.now()) 
我确实得到了正确的当地时间,但由于某些原因,我无法通过执行以下操作来调整时间:

mytime = roundTime(local_time,timedelta(minutes=15)).strftime('%H:%M:%S') 
它与上面的
datetime.now()配合使用

我想出了一个不漂亮但有效的代码:

mytime = timezone.localtime(timezone.now())
mytime = datetime.strftime(mytime, '%Y-%m-%d %H:%M:%S')
mytime = datetime.strptime(str(mytime), '%Y-%m-%d %H:%M:%S')
mytime = roundTime(mytime,timedelta(minutes=15)).strftime('%H:%M:%S')
mytime = datetime.strptime(str(mytime), '%H:%M:%S')

有更好的解决方案吗?

您正在使用的
roundTime
功能不适用于时区感知日期。 要支持它,您可以这样修改它:

def roundTime(dt=None, dateDelta=timedelta(minutes=1)):
    """Round a datetime object to a multiple of a timedelta
    dt : datetime.datetime object, default now.
    dateDelta : timedelta object, we round to a multiple of this, default 1 minute.
    Author: Thierry Husson 2012 - Use it as you want but don't blame me.
            Stijn Nevens 2014 - Changed to use only datetime objects as variables
    """
    roundTo = dateDelta.total_seconds()

    if dt == None : 
        dt = datetime.now()
    #Make sure dt and datetime.min have the same timezone
    tzmin = dt.min.replace(tzinfo=dt.tzinfo)

    seconds = (dt - tzmin).seconds
    # // is a floor division, not a comment on following line:
    rounding = (seconds+roundTo/2) // roundTo * roundTo
    return dt + timedelta(0,rounding-seconds,-dt.microsecond)
通过这种方式,该函数可以处理naive和TZ感知日期。 然后,您可以继续进行第二次尝试:

local_time = timezone.localtime(timezone.now()) 
mytime = roundTime(local_time, timedelta(minutes=15))

您正在使用的
roundTime
功能不适用于时区感知日期。 要支持它,您可以这样修改它:

def roundTime(dt=None, dateDelta=timedelta(minutes=1)):
    """Round a datetime object to a multiple of a timedelta
    dt : datetime.datetime object, default now.
    dateDelta : timedelta object, we round to a multiple of this, default 1 minute.
    Author: Thierry Husson 2012 - Use it as you want but don't blame me.
            Stijn Nevens 2014 - Changed to use only datetime objects as variables
    """
    roundTo = dateDelta.total_seconds()

    if dt == None : 
        dt = datetime.now()
    #Make sure dt and datetime.min have the same timezone
    tzmin = dt.min.replace(tzinfo=dt.tzinfo)

    seconds = (dt - tzmin).seconds
    # // is a floor division, not a comment on following line:
    rounding = (seconds+roundTo/2) // roundTo * roundTo
    return dt + timedelta(0,rounding-seconds,-dt.microsecond)
通过这种方式,该函数可以处理naive和TZ感知日期。 然后,您可以继续进行第二次尝试:

local_time = timezone.localtime(timezone.now()) 
mytime = roundTime(local_time, timedelta(minutes=15))

要舍入时区感知的日期时间对象,请执行以下操作:

为了避免浮点问题,可以使用整数微秒(
dt.resolution
)重写所有计算

例如:

>>> round_time(delta=timedelta(minutes=15))

要舍入时区感知的日期时间对象,请执行以下操作:

为了避免浮点问题,可以使用整数微秒(
dt.resolution
)重写所有计算

例如:

>>> round_time(delta=timedelta(minutes=15))

roundTime
是你的功能吗?如果是,你能显示它的代码吗?我已经发布了
roundTime
和我想出的一个工作代码。
roundTime
是你的功能吗?如果是,你能显示它的代码吗?我已经发布了
roundTime
和我想出的一个工作代码。谢谢你的帮助。我不想弄乱其他地方也在使用的往返时间函数。也许我可以为时区的需要做另一个版本。再次感谢你的帮助!此新版本在代码的其余部分中的行为将与以前相同,它只支持以前未使用过的新用例(您可以确定您没有使用它,因为您可能会遇到错误)@WayBehind:舍入可能会跨越DST边界,因此。感谢您的帮助。我不想弄乱其他地方也在使用的往返时间函数。也许我可以为时区的需要做另一个版本。再次感谢你的帮助!这个新版本在您的代码的其余部分中的行为将与以前一样,它只支持您以前没有使用过的新用例(您可以确定您没有使用它,因为您可能会遇到错误)@WayBehind:舍入可能会跨越DST边界,因此。