Python:一个月中的周数

发布于 2024-11-29 06:24:00 字数 281 浏览 0 评论 0原文

指定日期时:

datetime.datetime(2011, 8, 15)

我如何知道这是该月的第三周?

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

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

据我了解,如果给定日期是闰年(双六分相),则只有 2 月有 4 周

When specifying a date:

datetime.datetime(2011, 8, 15)

How can i get to know that this is the third week of the month?

What if I want this dates?

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

I understand that only February has 4 weeks if the given date is in a leap year (bissextile)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

宣告ˉ结束 2024-12-06 06:24:00

其他答案中显示的模式方法可能会产生误导。想象一下一年中的几周。一年 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日。
每年它都会向后推迟一天,直到第六年,我们将第 52 周的结束时间向后移动了 6 天(并为了更好地衡量而加入了闰日),因此 2017 年的整个第一周将是包含在 2016 年,那将是愚蠢的。所以 2016 年将有 53 周。

完全相同的逻辑也适用于月份,但可能更难发现。不幸的是,您选择了 2011 年 8 月,该日期的安排很巧妙,即每月 1 日从星期一开始。

>>> 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 月的第一周。

所以 9 月 29 日将是,简单地将天数除以 7 的方法是,在 9 月的第 5 周,但是查看上面的日历,如果 9 月 1-4 日在 8 月,那么 9 月 29 日就是九月的第四周。

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

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 周......

The modulo-style approach shown in other answers can be misleading. Imagine weeks in a year. THere are 52 chunks of 7 days in any 365 day year, with one day left over. So if for my first year, the 52nd week ends on Dec 30, and I have Dec 31 left to worry about.

I could either consider that there are 53 weeks in the year, and have the 53rd week be 31 Dec, 1 Jan, 2 Jan, 3 Jan ... Or, more conventionally, I consider that the first week of the next year actually begins on Dec 31. This is how your diary pocket book does it.

Of course this means that the next year the 52nd week ends not on Dec 30 now, but Dec 29.
And each year it creeps back one day at a time, until the 6th year where we have moved the end of 52nd week back 6 days (and thrown in a leap day for good measure) so the whole of the 1st week of 2017 would be contained in the year 2016, and that would be silly. So 2016 will have 53 weeks in it.

The exact same logic applies to months, however it can be harder to spot. Unfortunately you choose August 2011 which has a neat arrangement of starting the 1st of the month on a monday.

>>> 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

29 of Aug is in 5th week of Aug, but with same logic, the 1st, 2nd 3rd 4th of Sept would also be in the 5th week of Aug, and so cannot be in 1st week of Sept.

So 29 Sept would be, by the simple divide number of days by 7 approach, be in 5th week of September, but looking at calendar above, if 1-4 of sept are in August, then 29 Sept is in 4th week of Sept.

It all depends on your defintion of when a week begins.

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

Above, week 0 means the week is not considered part of this month. So 1st sept is in the 5th week of august.

NB

I would like to comment on @unutbu answer but I dont have enough points I guess.
The modulo 7 approach fails in sept 2011.

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

from the above calendar, 1st of sept is in week one, but that means the 28th cannot be in week 4 - it must be either in week 5, or 1st is in week 0...

伏妖词 2024-12-06 06:24:00
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
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
奢华的一滴泪 2024-12-06 06:24:00

也许 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

Maybe http://labix.org/python-dateutil will help.

Other than that it's just math.

 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
夜血缘 2024-12-06 06:24:00

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

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的答案是错误的,除非每周从星期二开始。

This (somewhat clumsy) example, using the calendar module ...

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

... gets the answer wrong for 2011-02-28, based on the OP's expectation, unless weeks start on Tuesday.

如若梦似彩虹 2024-12-06 06:24:00

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

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

How about this. We give the date that we wish to find the week for. We reset the date to the first day of the month in a new variable. We then create the week in the year for both the first day and our given date. Subtract the first isoweek from the given date's isoweek and add one. You add one to correct the zero index number. This should give the week number in the month.

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
氛圍 2024-12-06 06:24:00
testdate = datetime.datetime(2011, 2, 28)
weekofmonth = (testdate.day+7-1)/7

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

testdate = datetime.datetime(2011, 2, 28)
weekofmonth = (testdate.day+7-1)/7

In general to find the ceiling of division: ceiling of (x/y) = (x+y-1)/y

寒冷纷飞旳雪 2024-12-06 06:24:00

考虑到@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 之间的周数

To take into account the comment of @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

The following equation manage that the first day of a month is not necessary a monday:

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

The -2 and +2 allow to get a week number between 1 and 6

疏忽 2024-12-06 06:24:00
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)
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)
镜花水月 2024-12-06 06:24:00

在此处检查答案: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'])

Check answer here: 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'])
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文