簡體   English   中英

如何在Django中舍入可識別時區的日期

[英]How to round a timezone-aware date in Django

我正在嘗試將默認時區datetime轉換為localtime並將時間在Django視圖中舍入為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()
    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)

這樣,該功能可同時用於天真日期和TZ感知日期。 然后,您可以繼續進行第二次嘗試:

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

要舍入可識別時區的datetime對象, 請將其設為朴素的datetime對象,將其舍入,並為舍入的時間附加正確的時區信息

from datetime import timedelta
from django.utils import timezone

def round_time(dt=None, delta=timedelta(minutes=1)):
    if dt is None:
        dt = timezone.localtime(timezone.now()) # assume USE_TZ=True
    tzinfo, is_dst = dt.tzinfo, bool(dt.dst())
    dt = dt.replace(tzinfo=None)
    f = delta.total_seconds()
    rounded_ordinal_seconds = f * round((dt - dt.min).total_seconds() / f)
    rounded_dt = dt.min + timedelta(seconds=rounded_ordinal_seconds)
    localize = getattr(tzinfo, 'localize', None)
    if localize:
        rounded_dt = localize(rounded_dt, is_dst=is_dst)
    else:
        rounded_dt = rounded_dt.replace(tzinfo=tzinfo)
    return rounded_dt

為了避免浮點問題,可以使用整數微秒( dt.resolution )重寫所有計算。

例:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM