0

使用 python,我想计算 day_of_a_year 天及其相应月份的增量天数,以及月份 + 1 的增量天数。

*对不起,我忘了提到年份是一个已知变量,例如。

def a(day_of_year):
    <...>
    return [(days_from_start_of_month),(days_untill_end_of_month)]

因此,如果

day_of_year = 32 
a(32) = (2,28) #assuming the month which the day_of_year corresponds to starts from day 30 and ends to day 60.

到目前为止,我正在研究 datetime 、 timeutils 和 calendar 模块,我真的无法弄清楚代码的逻辑!我希望我能展示一些可靠的东西,但我在 timedelta 函数的某个地方迷路了。

4

2 回答 2

2

每月的第一天很容易构建,下个月的第一天也是如此。一旦你有了这些,剩下的就更容易了。正如 OP 所指出的,该calendar.monthrange函数为我们提供了最易读的方法来获取一个月的最后一天。

>>> from datetime import date, year
>>> import calendar
>>> def first_day(dt):
...      # Simply copy year and month into new date instance
...      return date(dt.year, dt.month, 1)
...
>>> def last_day(dt):
...      days_in_month = calendar.monthrange(dt.year, dt.month)[1]
...      return date(dt.year, dt.month, days_in_month)
...
>>> nth_day = 32
>>> day_of_year = date(2012, 1, 1) + timedelta(days=nth_day - 1)
>>> day_of_year
datetime.date(2012, 2, 1)
>>> first_day(day_of_year), last_day(day_of_year)
(datetime.date(2012, 2, 1), datetime.date(2012, 2, 29))
>>> day_of_year - first_day(day_of_year), last_day(day_of_year) - day_of_year
(datetime.timedelta(0), datetime.timedelta(28))

要将这些技术组合成一个功能:

def delta_to_start_and_end(year, day_of_year):
    dt = date(year, 1, 1) + timedelta(days=(day_of_year - 1))

    def first_day(dt):
         return date(dt.year, dt.month, 1)
    def last_day(dt):
         days_in_month = calendar.monthrange(dt.year, dt.month)[1]
         return date(dt.year, dt.month, days_in_month)

    return (dt - first_day(dt)).days, (last_day(dt) - dt).days

输出:

>>> delta_to_start_and_end(2012, 32)
(0, 28)
>>> delta_to_start_and_end(2011, 32)
(0, 27)
>>> delta_to_start_and_end(2012, 34)
(2, 26)
>>> delta_to_start_and_end(2012, 364)
(28, 2)

我不确定您是否要添加1到这两个值中的每一个;目前,当月的第一天(第一个示例)将您0作为第一个值,将 (days-in-the-month - 1) 作为第二个值,因为这是与这些点的天数差。如果您需要这些,在函数的最后一行添加+ 1两次是微不足道的。delta_to_start_and_end

作为历史记录,此答案的先前版本使用不同的方法来计算没有日历模块的一个月的最后一天:

def last_day(dt):
     rest, month = divmod(dt.month, 12)
     return date(dt.year + rest, month + 1, 1) - timedelta(days=1) 

这个函数使用divmod内置函数来处理“当前月份是十二月”的边缘情况;在这种情况下,下个月不是13,但是1我们也需要将年份增加一。将数字滚动回“开始”是数字的模数,但该divmod函数也为我们提供了除数,1如果当前月份是12. 这为我们提供了一个方便的指标,何时增加年份。

于 2012-06-22T13:51:57.943 回答
0

我不认为有一个现有的图书馆可以解决这个问题。您必须自己制作一些东西,如下所示:

monthdays = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)

day = 32

total = 0
for i in monthdays:
    if day - total - i < 0:
        before = day - total
        after = total + i - day
        break
    total += i

print before, after

(只是一个快速开始,可能有更优雅的方式)

于 2012-06-22T13:50:30.783 回答