给定一个日期范围,如何计算部分或全部在该范围内的周末数量?
给定一个日期范围,如何计算部分或全部在该范围内的周末数量?
(根据要求提供一些定义: “周末”是指星期六和星期日。 日期范围包含在内,即结束日期是该范围的一部分 “全部或部分”意味着周末的任何部分落在日期范围内意味着整个周末都被计算在内。)
为了简化,我想你实际上只需要知道持续时间以及第一天是一周中的哪一天......
我现在很好,它将涉及到整数除以 7 以及一些根据余数加 1 的逻辑,但我不太清楚......
Python 中答案的额外积分;-)
编辑
我的最终代码。
周末为周五和周六(因为我们计算的是入住天数),从周一开始,天数的索引为 0。 我使用了onebyone的算法和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
Given a date range how to calculate the number of weekends partially or wholly within that range?
(A few definitions as requested:
take 'weekend' to mean Saturday and Sunday.
The date range is inclusive i.e. the end date is part of the range
'wholly or partially' means that any part of the weekend falling within the date range means the whole weekend is counted.)
To simplify I imagine you only actually need to know the duration and what day of the week the initial day is...
I darn well now it's going to involve doing integer division by 7 and some logic to add 1 depending on the remainder but I can't quite work out what...
extra points for answers in Python ;-)
Edit
Here's my final code.
Weekends are Friday and Saturday (as we are counting nights stayed) and days are 0-indexed starting from Monday. I used onebyone's algorithm and Tom's code layout. Thanks a lot folks.
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
处理此类事情的一般方法:
对于一周中的每一天,计算出从该天开始的一段时间“包含周末”之前需要多少天。 例如,如果“包含周末”意味着“包含周六和周日”,那么我们有下表:
周日:8
星期一:7
星期二:6
星期三:5
星期四:4
星期五:3
星期六:2
对于“部分或全部”,我们有:
星期日:1
星期一:6
星期二:5
星期三:4
星期四:3
星期五:2
星期六:1
显然,这不必编码为表格,因为它的外观已经很明显了。
然后,给定经期开始的星期几,从经期长度(以天为单位)中减去[*]魔法值(可能是开始-结束+1,以包括两个栅栏柱)。 如果结果小于 0,则包含 0 个周末。 如果它等于或大于 0,则它包含(至少)1 个周末。
然后你就得处理剩下的日子了。 在第一种情况下,这很简单,每 7 天多一个周末。 在第二种情况下,除了星期日之外的每个开始日也是如此,只需要 6 天就可以包括另一个周末。 因此,在第二种情况下,对于从星期日开始的期间,您可以在该期间开始时计算 1 个周末,然后从长度中减去 1 并从星期一开始重新计算。
更一般地说,“整个或部分”周末发生的情况是,我们正在检查是否从有趣的部分(“周末”)中途开始。 如果是这样,我们可以:
就周末而言,只有一种特殊情况从中途开始,因此 (1) 看起来不错。 但是,如果您获取的日期是日期+时间(以秒为单位而不是天),或者如果您对 5 天的工作周而不是 2 天的周末感兴趣,那么 (2) 可能更容易理解。
[*] 当然,除非您使用无符号类型。
General approach for this kind of thing:
For each day of the week, figure out how many days are required before a period starting on that day "contains a weekend". For instance, if "contains a weekend" means "contains both the Saturday and the Sunday", then we have the following table:
Sunday: 8
Monday: 7
Tuesday: 6
Wednesday: 5
Thursday: 4
Friday: 3
Saturday: 2
For "partially or wholly", we have:
Sunday: 1
Monday: 6
Tuesday: 5
Wednesday: 4
Thursday: 3
Friday: 2
Saturday: 1
Obviously this doesn't have to be coded as a table, now that it's obvious what it looks like.
Then, given the day-of-week of the start of your period, subtract[*] the magic value from the length of the period in days (probably start-end+1, to include both fenceposts). If the result is less than 0, it contains 0 weekends. If it is equal to or greater than 0, then it contains (at least) 1 weekend.
Then you have to deal with the remaining days. In the first case this is easy, one extra weekend per full 7 days. This is also true in the second case for every starting day except Sunday, which only requires 6 more days to include another weekend. So in the second case for periods starting on Sunday you could count 1 weekend at the start of the period, then subtract 1 from the length and recalculate from Monday.
More generally, what's happening here for "whole or part" weekends is that we're checking to see whether we start midway through the interesting bit (the "weekend"). If so, we can either:
In the case of weekends, there's only one special case which starts midway, so (1) looks good. But if you were getting the date as a date+time in seconds rather than day, or if you were interested in 5-day working weeks rather than 2-day weekends, then (2) might be simpler to understand.
[*] Unless you're using unsigned types, of course.
我对这类事情的一般方法是:不要开始胡乱尝试重新实现你自己的日期逻辑 - 这很难,即。 你会把它搞砸的边缘情况并且看起来很糟糕。 提示:如果您在程序中的任何位置使用 mod 7 算术,或者在程序中的任何位置将日期视为整数:您失败了。 如果我在代码库中(甚至附近)的任何地方看到“已接受的解决方案”,则有人需要重新开始。 令人难以置信的是,任何自认为程序员的人都会对这个答案投赞成票。
相反,请使用 Python 附带的内置日期/时间逻辑:
首先,获取您感兴趣的所有日期的列表:
接下来,筛选出周末的日期。 在你的例子中,你对周五和周六晚上感兴趣,分别是 5 点和 6 点。(请注意,我并没有尝试将这部分纳入之前的列表理解中,因为这很难验证其正确性)。
最后,您想知道您的列表中有多少个周末。 这是棘手的部分,但实际上只需要考虑四种情况,周五或周六各结束一种情况。 具体的例子有助于让它变得更清晰,而且这确实是你想要在代码中记录的事情:
更短、更清晰、更容易理解意味着你可以对你的代码更有信心,并且可以解决更有趣的问题。
My general approach for this sort of thing: don't start messing around trying to reimplement your own date logic - it's hard, ie. you'll screw it up for the edge cases and look bad. Hint: if you have mod 7 arithmetic anywhere in your program, or are treating dates as integers anywhere in your program: you fail. If I saw the "accepted solution" anywhere in (or even near) my codebase, someone would need to start over. It beggars the imagination that anyone who considers themselves a programmer would vote that answer up.
Instead, use the built in date/time logic that comes with Python:
First, get a list of all of the days that you're interested in:
Next, filter down to just the days which are weekends. In your case you're interested in Friday and Saturday nights, which are 5 and 6. (Notice how I'm not trying to roll this part into the previous list comprehension, since that'd be hard to verify as correct).
Finally, you want to figure out how many weekends are in your list. This is the tricky part, but there are really only four cases to consider, one for each end for either Friday or Saturday. Concrete examples help make it clearer, plus this is really the sort of thing you want documented in your code:
Shorter, clearer and easier to understand means that you can have more confidence in your code, and can get on with more interesting problems.
要计算整个周末,只需调整天数,从星期一开始,然后除以七即可。 (请注意,如果开始日是工作日,则添加天数以移至上周一,如果是周末,则减去天数以移至下周一,因为您已经错过了这个周末。)
如果您想了解部分周末(或几周),只需查看除以七的小数部分即可。
To count whole weekends, just adjust the number of days so that you start on a Monday, then divide by seven. (Note that if the start day is a weekday, add days to move to the previous Monday, and if it is on a weekend, subtract days to move to the next Monday since you already missed this weekend.)
If you want to know partial weekends (or weeks), just look at the fractional part of the division by seven.
除了原始数学之外,您还需要外部逻辑。 您需要有一个日历库(或者如果您有足够的时间自己实现它)来定义周末、一周中的哪一天开始、结束等。
看看 Python 的日历类。
如果代码中没有对天数进行逻辑定义,纯数学方法在极端情况下会失败,例如 1 天的间隔,或者我相信低于一周的时间(或者如果允许部分时间,则低于 6 天)。
You would need external logic beside raw math. You need to have a calendar library (or if you have a decent amount of time implement it yourself) to define what a weekend, what day of the week you start on, end on, etc.
Take a look at Python's calendar class.
Without a logical definition of days in your code, a pure mathematical methods would fail on corner case, like a interval of 1 day or, I believe, anything lower then a full week (or lower then 6 days if you allowed partials).