Python: Date manipulation code

后端 未结 2 1091
南笙
南笙 2021-01-28 10:25

With python I want to calculate the delta days of a day_of_a_year day and its corresponding month, as well delta days for month + 1.

*Sorry I forgot to mention that the

相关标签:
2条回答
  • 2021-01-28 11:02

    I don't think that there's an existing library that works for this. You have to make something yourself, like this:

    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
    

    (just a quick start, there is possibly a more elegant way)

    0 讨论(0)
  • 2021-01-28 11:26

    The first day of the month is easy to construct, as is the first day of the next month. Once you have those, the rest is even easier. As pointed out by the OP, the calendar.monthrange function gives us the most readable method to get the last day of a month.

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

    To combine these techniques into one function:

    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
    

    Output:

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

    I'm not sure if you want to add 1 to each of these two values; currently the first day of the month (first example) gives you 0 as the first value and (days-in-the-month - 1) as the second value, as this is the difference in days from those points. It's trivial to add + 1 twice on the last line of the delta_to_start_and_end function if you need these.

    As a historic note, a previous version of this answer used a different method to calculate the last day of a month without the calendar module:

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

    This function uses the divmod builtin function to handle the 'current month is December' edge-case; in that case the next month is not 13, but 1 and we'd need to increase the year by one as well. Rolling over a number back to the 'start' is the modulus of the number, but the divmod function gives us the divisor as well, which happens to be 1 if the current month is 12. This gives us a handy indicator when to increase the year.

    0 讨论(0)
提交回复
热议问题