簡體   English   中英

給定日期范圍,如何計算部分或全部在該范圍內的周末數量?

[英]Given a date range how to calculate the number of weekends partially or wholly within that range?

給定日期范圍,如何計算部分或全部在該范圍內的周末數量?

(要求提供一些定義:將“周末”表示為星期六和星期日。日期范圍包括在內,即結束日期是“全部或部分”范圍的一部分,表示周末的任何部分都落在該日期范圍內,表示整個周末都算在內。)

為簡化起見,我想您實際上只需要知道持續時間以及第一天是星期幾...

我現在好多了,它涉及將整數除以7,並根據剩余的邏輯進行一些加1的運算,但我無法完全解決...

Python答案的加分;-)

編輯

這是我的最終代碼。

周末是星期五和星期六(因為我們在計算住宿天數),而天數從星期一開始是0索引。 我使用了bybyone的算法和Tom的代碼布局。 非常感謝大家。

def calc_weekends(start_day, duration):
    days_until_weekend = [5, 4, 3, 2, 1, 1, 6]
    adjusted_duration = duration - days_until_weekend[start_day]
    if adjusted_duration < 0:
        weekends = 0
    else:
        weekends = (adjusted_duration/7)+1
    if start_day == 5 and duration % 7 == 0: #Saturday to Saturday is an exception
        weekends += 1
    return weekends

if __name__ == "__main__":
    days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    for start_day in range(0,7):
        for duration in range(1,16):
            print "%s to %s (%s days): %s weekends" % (days[start_day], days[(start_day+duration) % 7], duration, calc_weekends(start_day, duration))
        print

這類事情的一般方法:

對於一周中的每一天,計算出從該天開始的一段“包含一個周末”之前需要多少天。 例如,如果“包含一個周末”的意思是“包含星期六和星期日”,那么我們有下表:

星期日:8星期一:7星期二:6星期三:5星期四:4星期五:3星期六:2

對於“部分或全部”,我們有:

星期日:1星期一:6星期二:5星期三:4星期四:3星期五:2星期六:1

顯然,不必將其編碼為表格,因為它看起來像什么。

然后,給定周期開始的星期幾,從周期的長度(以天為單位)中減去[*]魔術值(可能是start-end + 1,包括兩個柵欄)。 如果結果小於0,則包含0個周末。 如果等於或大於0,則它包含(至少)1個周末。

然后,您必須處理剩余的日子。 在第一種情況下,這很容易,每7天額外增加一個周末。 在第二種情況下,對於每個開始日(星期日除外)也是如此,星期日僅需要6天才能包含另一個周末。 因此,在第二種情況下,對於從星期日開始的時間段,您可以在時間段開始時算一個周末,然后從長度中減去1,然后從星期一重新計算。

更一般而言,“整個或部分”周末在這里發生的事情是,我們正在檢查是否從有趣的部分(“周末”)開始。 如果是這樣,我們可以:

  • 1)數一,將開始日期移動到感興趣的位的末尾,然后重新計算。
  • 2)將開始日期移回感興趣的位的開頭,然后重新計算。

在周末的情況下,只有一種特殊情況從中途開始,因此(1)看起來不錯。 但是,如果您以秒為單位而不是日期來獲取日期和日期,或者如果您對工作日為5天而不是周末為2天感興趣,那么(2)可能更容易理解。

[*]當然,除非您使用無符號類型。

對於這種事情,我的一般做法是:不要開始弄亂嘗試重新實現自己的日期邏輯-這很困難。 您會把它固定在邊盒上,看起來很糟。 提示:如果您在程序中的任何地方都使用了mod 7算術,或者在程序中的任何地方都將日期視為整數: 則會失敗 如果我在代碼庫中的任何地方(甚至附近)看到“可接受的解決方案”,那么有人將需要重新開始。 讓人難以想象的是,任何認為自己是程序員的人都會投票贊成這個答案。

相反,請使用Python隨附的內置日期/時間邏輯:

首先,獲取您感興趣的所有日期的列表:

from datetime import date, timedelta    
FRI = 5; SAT = 6

# a couple of random test dates
now = date.today()
start_date = now - timedelta(57)
end_date = now - timedelta(13)
print start_date, '...', end_date    # debug

days = [date.fromordinal(d) for d in  
            range( start_date.toordinal(),
                   end_date.toordinal()+1 )]

接下來,只過濾到周末的日子。 在您的情況下,您對周五和周六晚上分別為5和6感興趣。(請注意,我不打算將此部分推入先前的列表理解中,因為這很難證明是正確的)。

weekend_days = [d for d in days if d.weekday() in (FRI,SAT)]

for day in weekend_days:      # debug
    print day, day.weekday()  # debug

最后,您想弄清楚列表中有幾個周末。 這是棘手的部分,但實際上只需要考慮四種情況,星期五或星期六的每一端都需要考慮。 具體的示例有助於使它更加清晰,此外,這確實是您想要在代碼中記錄的一類東西:

num_weekends = len(weekend_days) // 2

# if we start on Friday and end on Saturday we're ok,
# otherwise add one weekend
#  
# F,S|F,S|F,S   ==3 and 3we, +0
# F,S|F,S|F     ==2 but 3we, +1
# S|F,S|F,S     ==2 but 3we, +1
# S|F,S|F       ==2 but 3we, +1

ends = (weekend_days[0].weekday(), weekend_days[-1].weekday())
if ends != (FRI, SAT):
    num_weekends += 1

print num_weekends    # your answer

更短,更清晰,更容易理解意味着您可以對代碼更有信心,並可以解決更多有趣的問題。

要計算整個周末,只需調整天數,以便從星期一開始,然后除以7。 (請注意,如果開始日期是工作日,請添加天數以移至上一個星期一,如果是周末,則減去天數以移至下周一,因為您已經錯過了這個周末。)

days = {"Saturday":-2, "Sunday":-1, "Monday":0, "Tuesday":1, "Wednesday":2, "Thursday":3, "Friday":4}

def n_full_weekends(n_days, start_day):
    n_days += days[start_day]
    if n_days <= 0:
        n_weekends = 0
    else:
        n_weekends = n_days//7
    return n_weekends

if __name__ == "__main__":
    tests = [("Tuesday", 10, 1), ("Monday", 7, 1), ("Wednesday", 21, 3), ("Saturday", 1, 0), ("Friday", 1, 0),
    ("Friday", 3, 1), ("Wednesday", 3, 0), ("Sunday", 8, 1), ("Sunday", 21, 2)]
    for start_day, n_days, expected in tests:
        print start_day, n_days, expected, n_full_weekends(n_days, start_day)

如果您想知道部分周末(或幾周),只需看除以7的小數部分即可。

除了原始數學之外,您還需要外部邏輯。 您需要有一個日歷庫(或者如果您有足夠的時間自己實施),以定義一個周末,一周中的哪一天開始,結束等等。

看一下Python的日歷類

如果沒有在代碼中對天數進行邏輯定義,則純數學方法將在極端情況下失敗,例如間隔1天,或者,我相信,任何低於整整一周的時間(或者如果允許分批,則不到6天)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM