David
David

Reputation: 149

Start and end of a period

Is there a way to extend get_month_day_range() function with week and year in addition to month?

The method could be define as get_day_range(period, date) which period could be either week, month or year.

import datetime

from dateutil.relativedelta import relativedelta

def get_month_day_range(date):
    """
    For a date 'date' returns the start and end date for the month of 'date'.

    Month with 31 days:
    >>> date = datetime.date(2011, 7, 27)
    >>> get_month_day_range(date)
    (datetime.date(2011, 7, 1), datetime.date(2011, 7, 31))

    Month with 28 days:
    >>> date = datetime.date(2011, 2, 15)
    >>> get_month_day_range(date)
    (datetime.date(2011, 2, 1), datetime.date(2011, 2, 28))
    """
    last_day = date + relativedelta(day=1, months=+1, days=-1)
    first_day = date + relativedelta(day=1)
    return first_day, last_day

if __name__ == "__main__":
    import doctest
    doctest.testmod()

I have got this result so far :

def get_period_day_range(date, period='month'):
        last_day = None
        first_day = date + relativedelta(day=1)

        if period == 'month':
            last_day = date + relativedelta(day=1, months=1, days=-1)
        elif period == 'week':
            last_day = date + relativedelta(day=1, weeks=1, days=-1)
        elif period == 'year':
            last_day = date + relativedelta(day=1, years=1, days=-1)
        return first_day, last_day

It is not working all the time. It is not working with week for datetime.datetime(2017, 7, 10) and with year for datetime.datetime(2017, 7, 5). How could I fix it? Any suggestions?

Be aware that the function will have of purposes to give us the start and end date of a certain period depending of what date we pass in input. For instance, if I give datetime.datetime(2017, 7, 10) with year, it will give me (datetime.datetime(2017, 1, 1), datetime.datetime(2017, 12, 31)) or with week for datetime.datetime(2017, 7, 5) the output will be (datetime.datetime(2017, 7, 2), datetime.datetime(2017, 7, 8))

Upvotes: 1

Views: 673

Answers (1)

MiguelSR
MiguelSR

Reputation: 166

You're doing it wrong, just copying the code above without looking at the documentation of the library you are using (link: http://dateutil.readthedocs.io/en/stable/relativedelta.html)

You need to do something like this (not tested):

from dateutil.relativedelta import *

def get_period_day_range(date, period='month'):
    if period == 'month':
        # Then we want day 1 of that month and previous day of the 
        # day 1 of the next month, hence months = 1 (next month) and
        # days = -1 (previous date)
        first_day = date + relativedelta(day=1)
        last_day = date + relativedelta(day=1, months=1, days=-1)
    elif period == 'week':
        # Last monday
        first_day = date + relativedelta(weekday=MO(-1))
        # Next sunday
        last_day = date + relativedelta(weekday=SU)
    elif period == 'year':
        # First day of the year, note day and month are singular so they
        # are not relative terms (read the doc)
        first_day = date + relativedelta(day=1, month=1)
        # Last day is always 31 December
        last_day = date + relativedelta(day=31, month=12)
    return first_day, last_day

Upvotes: 3

Related Questions