【问题标题】:Django/python date aggregation by month and quarter按月和季度的 Django/python 日期聚合
【发布时间】:2011-02-01 12:02:21
【问题描述】:

我正在编写一个需要不同时间(周、月、季度等)的平均价格的功能。这是模型:

class ItemPrice(models.Model):
    item = models.ForeignKey(Item)
    date = models.DateField()
    price = models.FloatField()

此模型会随着时间的推移跟踪商品的价格,并以频繁但不定期的间隔添加新商品。 找到上周的平均 price 很容易:

ItemPrice.objects.filter(item__id = 1)
    .filter(date_lt = TODAY)
    .filter(date_gte = TODAY_MINUS_7_DAYS)
    .filter(date_.aggregate(Avg('value'))

因为一周总是有 7 天,但是月份和季度呢?他们有不同的天数...?

谢谢!

编辑: 该应用程序是为金融机构准备的,恐怕30天的月不会削减它,谢谢您的建议!

【问题讨论】:

    标签: python django orm date


    【解决方案1】:

    解决方案分两部分,第一部分使用django ORM的aggregation函数,第二部分使用python-dateutil

    from dateutil.relativedelta import relativedelta
    
    A_MONTH = relativedelta(months=1)
    
    month = ItemPrice.objects \
        .filter(date__gte = date - A_MONTH) \
        .filter(date__lt = date) \
        .aggregate(month_average = Avg('price'))
    

    month 等于:

    {'month_average': 40}
    

    值得注意的是,您可以通过更改.aggregate() 参数来更改month 字典的键。

    dateutil 的 relativedelta 可以处理几天、几周、几年等等。一个很棒的包,我将重写我自己的hax。

    【讨论】:

      【解决方案2】:
      import datetime
      from dateutil import relativedelta, rrule  
      
      obj = self.get_object()  
      datenow = datetime.datetime.now() 
      
      quarters = rrule.rrule(
              rrule.MONTHLY,
              bymonth=(1, 4, 7, 10),
              bysetpos=-1,
              dtstart=datetime.datetime(datenow.year, 1, 1),
              count=5)
      
          first_day = quarters.before(datenow)
          last_day = (quarters.after(datenow) - relativedelta.relativedelta(days=1))
      
          quarter = Payment.objects.filter(
              operation__department__cashbox__id=obj.pk,
              created__range=(first_day, last_day)).aggregate(count=Sum('amount'))
      

      inspiration from there

      【讨论】:

        【解决方案3】:

        我会选择360-day calendar,而不必担心这些小错误。只需将过去 30 天用作“上个月平均值”,将过去 90 天用作“上季度平均值”即可。

        【讨论】:

        • 你真的阅读了我链接到的维基百科文章吗? 360 天日历的设计正是出于这一目的。毕竟,为什么显示“过去一个月”平均值的应用在 1 月 31 日(过去 31 天的平均值)和 2 月 1 日(过去 28 天的平均值)表现不同??
        • 我的意思是与公历的偏差,而不是从一个月到另一个。感谢您向我指出 DAYS360,我将来也许可以使用它,但它没有回答问题。
        【解决方案4】:

        首先,您对过去 7 天还是上周感兴趣?如果答案是上周,则您的查询不正确。

        如果您关心的是过去的“n”天,那么您的查询是正确的,我想您可以放松一下,一个月用 30 天,一个季度用 90 天。

        【讨论】:

        • 我对月份和季度感兴趣,真的。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-09-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-22
        • 2021-10-16
        • 1970-01-01
        相关资源
        最近更新 更多