【问题标题】:Python: Number of the Week in a MonthPython:一个月中的周数
【发布时间】:2011-08-11 16:11:56
【问题描述】:

指定日期时:

datetime.datetime(2011, 8, 15)

我怎样才能知道这是本月的第三周?

如果我想要这个日期怎么办?

datetime.datetime(2011, 2, 28) //should return 4
datetime.datetime(2011, 8, 29) //should return 5

我知道,如果给定日期是闰年(双六分位),则只有 2 月有 4 周

【问题讨论】:

  • 2011-8-15 不是本月的第三周吗?
  • @Francisco - 你对二月的第 n 周的定义是什么?只是为了澄清一下,您将哪个日期范围应用于 2011 年 2 月的第一周?很多人实际上会说 2011 年 2 月有 5 周,而 28 日是第 5 周。
  • 我对这个相关问题的回答应该可以完成这项工作:stackoverflow.com/questions/3806473/…

标签: python numbers


【解决方案1】:
In [115]: d = datetime.datetime(2011, 2, 28)

In [116]: (d.day-1)//7+1
Out[116]: 4

In [117]: d = datetime.datetime(2011, 8, 29)

In [118]: (d.day-1)//7+1
Out[118]: 5

【讨论】:

  • @Usagi:也许我错了,但由于2011-2-28 应该返回4,我将OP 的问题理解为“给定日期d,它发生在nth当月的工作日w,您如何找到n?”。
  • 我明白了。是的,这令人困惑。 OP 应该添加更多背景信息,因为正如 Paul 指出的那样,第 n 周的定义改变了答案。
  • @Mathia Haure-Touzé:您的编辑建议的解决方案与我的截然不同。因此,请将其发布为您自己的答案。
【解决方案2】:

其他答案中显示的模数方法可能会产生误导。想象一下一年中的几个星期。在任何 365 天的一年中有 52 个 7 天,还剩下一天。因此,如果我第一年的第 52 周在 12 月 30 日结束,那么我还有 12 月 31 日需要担心。

我可以或者考虑一年中有 53 周,并且第 53 周是 12 月 31 日、1 月 1 日、1 月 2 日、1 月 3 日......或者,更传统地,我认为明年的第一周实际上是从 12 月 31 日开始的。这就是你的日记本。

当然,这意味着明年的第 52 周现在不是在 12 月 30 日结束,而是在 12 月 29 日结束。 每年它一次一天地往回爬,直到第 6 年,我们将第 52 周结束后移了 6 天(并且为了更好的衡量标准,在闰日抛出),所以 2017 年的整个第一周将是包含在 2016 年,那将是愚蠢的。所以 2016 年将有 53 周。

完全相同的逻辑适用于几个月,但可能更难发现。不幸的是,您选择了 2011 年 8 月,该日期安排得很整齐,从星期一开始。

>>> print calendar.month(2011,8)
    August 2011
Mo Tu We Th Fr Sa Su
 1  2  3  4  5  6  7
 8  9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

>>> print calendar.month(2011,9)
   September 2011
Mo Tu We Th Fr Sa Su
          1  2  3  4
 5  6  7  8  9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30

8 月 29 日是 8 月的第 5 周,但同样的逻辑,9 月 1 日、2 日 3 日 4 日也应该是 8 月的第 5 周,所以不可能是 9 月的第 1 周。

因此,通过简单的天数除以 7 方法,9 月 29 日是 9 月的第 5 周,但查看上面的日历,如果 9 月 1-4 日是在 8 月,那么 9 月 29 日是第 4 周9 月。

这完全取决于您对一周开始时间的定义。

import datetime
import calendar

# I am assuming that the first week of a month starts with the first monday of a month...
#I *think* my logic is OK - if Monday (0) is the start of the week, then
#any dayof the month minus its own day of week (0,1,2...) must be positive
#if that day is on or after the first monday of the month

def week_of_month(tgtdate):

    days_this_month = calendar.mdays[tgtdate.month]
    for i in range(1, days_this_month):
        d = datetime.date(tgtdate.year, tgtdate.month, i)
        if d.day - d.weekday() > 0:
            startdate = d
            break
    # now we canuse the modulo 7 appraoch
    return (tgtdate - startdate).days //7 + 1

tgtdates = [datetime.date(2011, 8, 29),
            datetime.date(2011, 8, 1)
            ]

for tgtdate in tgtdates:
    print tgtdate,
    print "is in week %s" % week_of_month(tgtdate)

print calendar.month(tgtdate.year,tgtdate.month)


 # 2011-09-29 is in week 4
 # 2011-09-01 is in week 0
 #    September 2011
 # Mo Tu We Th Fr Sa Su
 #           1  2  3  4
 #  5  6  7  8  9 10 11
 # 12 13 14 15 16 17 18
 # 19 20 21 22 23 24 25
 # 26 27 28 29 30

 # 2011-08-29 is in week 5
 # 2011-08-01 is in week 1
 #     August 2011
 # Mo Tu We Th Fr Sa Su
 #  1  2  3  4  5  6  7
 #  8  9 10 11 12 13 14
 # 15 16 17 18 19 20 21
 # 22 23 24 25 26 27 28
 # 29 30 31

在上面,第 0 周表示该周不被视为本月的一部分。所以 9 月 1 日是 8 月的第 5 周。

注意

我想对@unutbu 的答案发表评论,但我猜我没有足够的分数。 模 7 方法在 2011 年 9 月失败了。

>>> d = datetime.date(2011,9,28)
>>> (d.day-1)//7+1
4
>>> d = datetime.date(2011,9,1)
>>> 
>>> (d.day-1)//7+1
1

根据上述日历,9 月 1 日在第一周,但这意味着 28 日不能在第 4 周 - 它必须在第 5 周,或者 1 日在第 0 周...

【讨论】:

  • 我认为您的解决方案也为 datetime.date(2011,9,28) 返回 4
【解决方案3】:

也许http://labix.org/python-dateutil 会有所帮助。

除此之外,它只是数学。

 from datetime import datetime, timedelta

    def week_of_month(date):
        month = date.month
        week = 0
        while date.month == month:
            week += 1
            date -= timedelta(days=7)

        return week

【讨论】:

    【解决方案4】:

    这个(有点笨拙的)例子,使用日历模块...

    import calendar
    import datetime
    
    def week(dt):
        mth = calendar.monthcalendar(dt.year, dt.month)
        for i, wk in enumerate(mth):
            if dt.day in wk:
                return i + 1
    
    calendar.setfirstweekday(calendar.MONDAY)
    
    week(datetime.datetime(2011, 8, 15)) # 3
    week(datetime.datetime(2011, 2, 28)) # 5
    week(datetime.datetime(2011, 8, 29)) # 5
    

    ... 根据 OP 的预期,2011-02-28 的答案是错误的,除非每周从周二开始。

    【讨论】:

      【解决方案5】:

      这个怎么样。我们给出了我们希望找到一周的日期。我们在一个新变量中将日期重置为该月的第一天。然后,我们为第一天和给定日期创建一年中的一周。从给定日期的 isoweek 中减去第一个 isoweek 并添加一个。您加一以更正零索引号。这应该给出该月的周数。

      import datetime
      
      def _get_week_of_day(date):
          first_day = date.replace(day=1)
          iso_day_one = first_day.isocalendar()[1]
          iso_day_date = date.isocalendar()[1]
          adjusted_week = (iso_day_date - iso_day_one) + 1
          return adjusted_week
      

      【讨论】:

        【解决方案6】:
        testdate = datetime.datetime(2011, 2, 28)
        weekofmonth = (testdate.day+7-1)/7
        

        一般求除法的上限:(x/y) = (x+y-1)/y的上限

        【讨论】:

        • 你能解释一下吗?我以为是 (28+7-1)/7 = 34/7 = 4。这不正确吗?
        • 查看 2011 年 10 月的日历。保罗也在下面解释了这一点。对于 2011 年 10 月 28 日,答案应该是 5,2011 年 10 月总共有六周。
        【解决方案7】:

        考虑到@Usagi 的评论:

        datetime.datetime(2011, 8, 15) // should return 3
        datetime.datetime(2011, 2, 28) // should return 5
        datetime.datetime(2011, 8, 29) // should return 5
        

        以下等式说明一个月的第一天不一定是星期一:

        (d.day-d.weekday() -2)//7+2
        

        -2 和 +2 允许获得 1 到 6 之间的周数

        【讨论】:

          【解决方案8】:
          d = datetime.datetime.today()
          year = d.year
          month = d.month
          last_day = calendar.monthrange(year,month)[1]
          d = datetime.datetime(year, month, last_day)
          total_week = (d.day-1)//7+1
          print(total_week)
          

          【讨论】:

            【解决方案9】:

            在这里查看答案:https://stackoverflow.com/a/64192858/6089311

            import pandas as pd
            
            def weekinmonth(dates):
                """Get week number in a month.
                
                Parameters: 
                    dates (pd.Series): Series of dates.
                Returns: 
                    pd.Series: Week number in a month.
                """
                firstday_in_month = dates - pd.to_timedelta(dates.dt.day - 1, unit='d')
                return (dates.dt.day-1 + firstday_in_month.dt.weekday) // 7 + 1
                
            
            df = pd.DataFrame(pd.date_range(' 1/ 1/ 2000', periods = 100, freq ='D'), columns=['Date'])
            weekinmonth(df['Date'])
            

            【讨论】:

              猜你喜欢
              • 2010-12-20
              • 2011-04-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-04-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多