Mir Muhammad Murtaza
Mir Muhammad Murtaza

Reputation: 17

I want to determine the names of all the months between two dates using datetime

import datetime
import calendar

dateStart = datetime.date(2017, 8, 2)
dateEnd = datetime.date(2018, 1, 1)
st = dateStart.month
ed = dateEnd.month
lis = []

for i in range(st, ed + 1):
    lis.append(calendar.month_name[i])

print(lis)

The output that I am expecting is:

['January', 'August', 'September', 'October', 'November', 'December']

With 'January' belonging to the year 2018. The list has to be sorted in accordance with the order of the months. This code isn't working for this case.

Upvotes: 0

Views: 84

Answers (4)

keithpjolley
keithpjolley

Reputation: 2263

Using a generator to iterate over the months. Preserves start and end dates.

import datetime
import calendar

dateStart = datetime.date(2017, 8, 2)
dateEnd = datetime.date(2018, 1, 1)

def months(start, end):
    ''' Input a start and end date and yields a numerical month
        (between 1 and 12) for each month between the dates.
    '''
    # Include start month:
    if start < end:
        yield start.month
    while start < end: 
        if start.month < 12:  
            start = start.replace(month=start.month+1) 
        else:     
            start = start.replace(year=start.year+1).replace(month=1) 
        yield start.month 

months = [calendar.month_name[month] for month in
            sorted(set(months(dateStart, dateEnd)))] 

print(dateStart) 
print(dateEnd)
print(months)

Output:

2017-08-02
2018-01-01
['January', 'August', 'September', 'October', 'November', 'December']

The above will at most print 12 month names, even if the two dates are more than 12 months apart. If the requirement is to list repeated months in order it's a bit simpler (notice that I added a few months to dateEnd to illustrate).

import datetime
import calendar

dateStart = datetime.date(2017, 8, 2)
dateEnd = datetime.date(2018, 10, 1)

def months(start, end):
    ''' Input a start and end date and yields a numerical month
        (between 1 and 12) for each month between the dates.
    '''
    if start < end:
        yield calendar.month_name[start.month]
    while start < end:
        if start.month < 12: 
            start = start.replace(month=start.month+1)
        else:
            start = start.replace(year=start.year+1).replace(month=1)
        yield calendar.month_name[start.month]

months = [month for month in months(dateStart, dateEnd)]

print(months)

Output:

['August', 'September', 'October', 'November', 'December', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October']

Upvotes: 0

dzang
dzang

Reputation: 2260

You can use relativedelta:

from dateutil.relativedelta import relativedelta
import datetime
import calendar

dateStart = datetime.date(2017,8,2)
dateEnd = datetime.date(2018,1,1)
st = datetime.date(dateStart.year, dateStart.month, 1)
ed = dateEnd

tmp = st
months = {}

while tmp <= dateEnd:
    months[tmp.month] = calendar.month_name[tmp.month]
    tmp += relativedelta(months=1)

lis = [months[k] for k in sorted(list(months.keys()))]
print(lis)

['January', 'August', 'September', 'October', 'November', 'December']

Upvotes: 1

martineau
martineau

Reputation: 123463

Here's a way to do it using only Python built-ins. Note that it's possible for a month to be repeated depending on the start and end dates.

import datetime
import calendar

dateStart = datetime.date(2017, 8, 2)
dateEnd = datetime.date(2018, 1, 1)

ONE_DAY = datetime.timedelta(days=1)
dt, ed = dateStart, dateEnd
lis = []
last_month = None

while dt <= ed:
    if dt.month != last_month:
        lis.append(dt.month)
        last_month = dt.month
    dt += ONE_DAY

# Sort the month numbers and replace them with their names.
lis = [calendar.month_name[month] for month in sorted(lis)]

print(lis)

Output:

['January', 'August', 'September', 'October', 'November', 'December']

Upvotes: 1

Abdulhamid Oksuz
Abdulhamid Oksuz

Reputation: 1

the problem is in your range() when you enter range(8,1) it will return 0 step because you cannot increase 8 to 1.

you can try below code for little improvment:

if st < ed:
    for i in range(st, ed+1):
        lis.append(calendar.month_name[i])
else:
    for i in range(st, ed+1, -1):
        lis.append(calendar.month_name[i])
print(lis)

but don't forget if you use same mount this will not work. (2017, 8, 2 / 2018, 8, 1)

Upvotes: 0

Related Questions