Django timesince()函数实现时间显示"2分钟前"的格式

2019-11-12 21:07:41 最后一行代码 阅读:375

分类: Django

相信大家在别人网站中都见过"10分钟前"、"一周前"这种时间显示格式,那么如何实现呢。前段时间写项目的时候无意间发现Django一个内置处理时间的函数timesince(),看了下源码发现它可以将指定时间到当前时间之间的差计算出来,我们就用这个来实现。

 

一、源码

# \Lib\site-packages\django\utils\timesince.py
def timesince(d, now=None, reversed=False, time_strings=None):
    if time_strings is None:
        time_strings = TIME_STRINGS

    if not isinstance(d, datetime.datetime):
        d = datetime.datetime(d.year, d.month, d.day)
    if now and not isinstance(now, datetime.datetime):
        now = datetime.datetime(now.year, now.month, now.day)
    
    # 如果未指定now,则自动根据参数d的时间类型进行转换。比如如果参数d是UTC时间,那么now返回的就是当前UTC时间。如果参数d是本地时间,那么now返回的也是本地时间。
    now = now or datetime.datetime.now(utc if is_aware(d) else None)
    
    # 这里判断是否颠倒计算时间差,True表示d-now,反之就是now-d
    if reversed:
        d, now = now, d
    delta = now - d

    leapdays = calendar.leapdays(d.year, now.year)
    if leapdays != 0:
        if calendar.isleap(d.year):
            leapdays -= 1
        elif calendar.isleap(now.year):
            leapdays += 1
    delta -= datetime.timedelta(leapdays)

    since = delta.days * 24 * 60 * 60 + delta.seconds
    if since <= 0:
        # d is in the future compared to now, stop processing.
        return avoid_wrapping(gettext('0 minutes'))
    for i, (seconds, name) in enumerate(TIMESINCE_CHUNKS):
        count = since // seconds
        if count != 0:
            break
    result = avoid_wrapping(time_strings[name] % count)
    if i + 1 < len(TIMESINCE_CHUNKS):
        # Now get the second item
        seconds2, name2 = TIMESINCE_CHUNKS[i + 1]
        count2 = (since - (seconds * count)) // seconds2
        if count2 != 0:
            result += gettext(', ') + avoid_wrapping(time_strings[name2] % count2)
    return result

参数:

d                 起始时间

now             结束时间,默认使用当前时间

reversed      是否颠倒计算。True表是起始时间 - 结束时间。False表是结束时间 - 起始时间

 

二、使用

timesince()函数返回字符串格式为"xx年"、"xx月"、"xx周"、"xx日"、"xx小时"、"xx分钟",也有可能是"xx 小时,xx 分钟"、"xx 周,xx 日"。"秒"和"微妙"会被忽视不参与计算。

注意:返回字符串中的"空格"都是Unicode编码"\xa0"特殊字符表示(我也不知道为啥,看注释也没看出个头头)。源码注释"Avoid text wrapping in the middle of a phrase by adding non-breaking spaces where there previously were normal spaces."翻译:"通过添加不中断的内容,避免在短语中间换行。以前有普通空间的空间"。(有明白的大牛可以下方评论)

注意:时间差最多只有两个相邻单位才显示,但是像"2周3小时"、"1年5天"这种相隔一个单位的就不会显示。

注意:该函数不会返回"天"只会返回"日",如果不喜欢可以用re.sub()方法替换成"天",后面会讲到替换方法。

注意:返回字符串显示的语言会根据settings.py中LANGUAGE_CODE变量设置的地区显示,如果设置的是中国就显示中文。如:英文"10 hours"。中文"10 小时"

注意:如果now参数未指定,那么now会自动根据参数d的时间类型进行转换。如果参数d是带时区的时间,那么now返回当前时区时间。如果参数d是UTC时间,那么now返回当前UTC时间。

import datetime
from django.utils.timesince import timesince

time = datetime.datetime(year=2019, month=11, day=12, hour=20, minute=30, second=30)
t = timesince(time)    # 我这里偷个懒就不指定结束时间了,默认用的当前时间
print(t)    
# 打印:"20 分钟"

time = datetime.datetime(year=2019, month=11, day=12, hour=10, minute=30, second=30)
t = timesince(time)
print(t)    
# 打印:"10 小时,2 分钟"

 

三、字符串显示单位优化,让它只返回一个单位时间,如:"xx 分钟前"

import datetime
from django.utils.timesince import timesince

old_time = datetime.datetime(year=2019, month=11, day=12, hour=10, minute=30, second=30)
t = timesince(old_time)  # 我这里偷个懒就不指定结束时间了,默认用的当前时间
t = t.split(',')[0]      # 分割字符串
# 注意:返回的字符串里空格会用Unicode编码"\xa0"表示
# 判断如果能匹配到"0\xa0分钟"则说明是刚刚创建的,注意字符串中"空白符"是用"\xa0"表示的,所以匹配"\xa0"就行
if re.match(r'^0\xa0分钟$',time): 
	return '刚刚'
# 因为timesince()函数不会显示"天"只会显示"日",所以这里需要判断替换下
elif '日' in time:
	return re.sub(r'日','天',time)+'前'
else:
	return time+'前'

print(t)

 

可能有些地方讲的不太清楚,有不明白的可以下方评论留言laugh

回复:

快来抢沙发

老板赏瓶水呗
微信 微信 支付宝 支付宝