如何在我的jinja过滤器中使用babel启用时区?

1 投票
1 回答
1538 浏览
提问于 2025-04-17 08:58

我想根据babel的语言设置来使用时区。请问我该怎么做?具体来说,我的目标是以一种人性化和本地化的方式显示文章的日期和时间,比如:

昨天

13:21

或者如果设置的是瑞典语参数,它会显示:

Igår

13:21

如果日期不是昨天或今天,它就会打印出日期和24小时制的时间。我觉得我在其他方面都做得不错,除了处理时区:

    from webapp2_extras import i18n
    from webapp2_extras.i18n import lazy_gettext as _
    import datetime
    from datetime import date, datetime, time
    from babel.dates import format_date, format_datetime, format_time
    from babel.numbers import format_number, format_decimal, format_percent
    def datetimeformat_jinja(value, format='%H:%M / %d-%m-%Y', locale='en'):
        now= datetime.now()
        info = None
        if datetime.date(value) == datetime.date(now):
          info= _('Today')
        elif (now - value).days < 2:
          info= _('Yesterday')
        else:
          month = value.month
          if month == 1:
            info = str(value.day)+' '+_('Jan')
          elif month == 2:
            info = str(value.day)+' '+_('Feb')
          elif month == 3:
            info = str(value.day)+' '+_('Mar')
          elif month == 4:
            info = str(value.day)+' '+_('April')
          elif month == 5:
            info = str(value.day)+' '+_('May')
          elif month == 6:
            info = str(value.day)+' '+_('June')
          elif month == 7:
            info = str(value.day)+' '+_('July')
          elif month == 8:
            info = str(value.day)+' '+_('Aug')
          elif month == 9:
            info = str(value.day)+' '+_('Sep')
          elif month == 10:
            info = str(value.day)+' '+_('Oct')
          elif month == 11:
            info = str(value.day)+' '+_('Nov')
          else:
            info = str(value.day)+' '+_('Dec')
        return info+'<br>'+format_time(value, 'H:mm', locale=locale)

上面的代码可以本地化和人性化输出:

在这里输入图片描述

我还可以切换语言,比如巴西葡萄牙语:

在这里输入图片描述

其中“Hoje”意思是“今天”,所以这个过滤器看起来是有效的。

你能告诉我怎么让我的代码也支持时区吗?我使用babel进行本地化,使用Jinja2进行渲染。时区应该是文章的时区还是查看者的时区?比如,一个在巴西的用户发布了一条消息,而一个在瑞典的查看者查看了这条消息。那应该用哪个时区呢?

我可以尝试通过导入pytz库来处理时区,就像文档中说的那样,并使用一个时区对象。我可以通过模板代码传递时区参数,但怎么知道这个时区参数是来自文章还是来自语言环境呢?在这种情况下,语言环境和时区会不同,因为它是印度的,而语言环境是英语,时区是印度:

{{ article.modified|datetimeformat_jinja(locale='en') }}

然后我也可以这样传递时区参数:

{{ article.modified|datetimeformat_jinja(locale='en') }}

过滤器:

def datetimeformat_jinja(value, format='%H:%M / %d-%m-%Y', locale='en', tzinfo=timezone('India')):
    now= datetime.now()
    info = None
    if datetime.date(value) == datetime.date(now):
      info= _('Today')
    elif (now - value).days < 2:
      info= _('Yesterday')
    else:
      month = value.month
      if month == 1:
        info = str(value.day)+' '+_('Jan')
      elif month == 2:
        info = str(value.day)+' '+_('Feb')
      elif month == 3:
        info = str(value.day)+' '+_('Mar')
      elif month == 4:
        info = str(value.day)+' '+_('April')
      elif month == 5:
        info = str(value.day)+' '+_('May')
      elif month == 6:
        info = str(value.day)+' '+_('June')
      elif month == 7:
        info = str(value.day)+' '+_('July')
      elif month == 8:
        info = str(value.day)+' '+_('Aug')
      elif month == 9:
        info = str(value.day)+' '+_('Sep')
      elif month == 10:
        info = str(value.day)+' '+_('Oct')
      elif month == 11:
        info = str(value.day)+' '+_('Nov')
      else:
        info = str(value.day)+' '+_('Dec')
    return info+'<br>'+format_time(value, 'H:mm', tzinfo=tzinfo, locale=locale)

所以至少看起来我可以本地化一个时区,但我在想怎么让它变得动态。

1 个回答

1

时间应该显示为文章的时区还是观看者的时区呢?比如说,一个在巴西的用户发了一条消息,而一个在瑞典的用户查看了这条消息。那么应该用哪个时区呢?

我会始终显示为“墙上时钟时间”,也就是说,使用观看者在桌子上看到的普通时钟的时区。不过,这个决定还是要看你自己。

我可以通过模板代码传递时区参数,但怎么知道这个时区参数是来自文章还是来自地区呢?在这种情况下,地区和时区会不同,因为这是关于印度的,而地区是英语,时区是印度的:

实际上,时区和地区是两回事,它们之间的联系非常松散。比如说,一个在瑞典的印度人仍然想用英语(或者印地语等)阅读,但他希望看到的是瑞典的时区。

当然,你可以为特定的用途硬编码时区,但更明智的做法是将地区和时区分开,让用户自己控制时区设置。

至于你的代码,你可能需要把简单的日期时间切换到支持时区的日期时间。

撰写回答