Gregology
Gregology

Reputation: 1735

Python list of first day of month for given period

I am trying find an efficient way of creating a list of dates only including the first day of the month for a given period. Something like this but better:

import datetime
dates = [
  datetime.date (2014, 4, 1),
  datetime.date (2014, 5, 1),
  datetime.date (2014, 6, 1),
  datetime.date (2014, 7, 1),
  datetime.date (2014, 8, 1),
  datetime.date (2014, 9, 1),
  datetime.date (2014, 10, 1),
  datetime.date (2014, 11, 1),
  datetime.date (2014, 12, 1),
  datetime.date (2015, 1, 1),
  datetime.date (2015, 2, 1)]

Alternatively, some direction on what to Google for this. Cheers!

Upvotes: 14

Views: 22726

Answers (8)

decks_dark
decks_dark

Reputation: 61

Try pandas.date_range() with the 'MS' (Month Start) frequency alias:

import pandas as pd

start = '2020-01-01'
end = '2020-12-01'

dates = pd.date_range(start, end, freq='MS')

print(dates)

Result:

DatetimeIndex(['2020-01-01', '2020-02-01', '2020-03-01', '2020-04-01',
               '2020-05-01', '2020-06-01', '2020-07-01', '2020-08-01',
               '2020-09-01', '2020-10-01', '2020-11-01', '2020-12-01'],
              dtype='datetime64[ns]', freq='MS')

A list of all frequency aliases can be found here.

Upvotes: 6

shx2
shx2

Reputation: 64328

This is the same as @Andrew's answer, but much faster:

dates = []
date = datetime.date.today()
while date.year < 2015:
    if date.day == 1:
        dates.append(date)
        # I added the following line:
        date += datetime.timedelta(days=27)
    date += datetime.timedelta(days=1)

Using force, but not being brutal.

Upvotes: 0

Abdullah
Abdullah

Reputation: 1

import datetime 
import calendar 
import re
from datetime import date

def findDay(date): 
    born = datetime.datetime.strptime(date, '%Y %m %d').weekday() 
    return (calendar.day_name[born]) 

def hyp(j):    
    no_hyphens = re.sub('-',' ',str(j))
    return no_hyphens

def send(year_start):    
    date = hyp(year_start)
    print (date)
    print(findDay(date))

epoch_year = 2019
for i in range(1,13):
    year_start = date(epoch_year, i, 1)
    send(year_start)

Upvotes: 0

MEA
MEA

Reputation: 221

With pandas :

   dates= pd.date_range('2018-01-01','2020-01-01' , freq='1M')-pd.offsets.MonthBegin(1)

result :

`DatetimeIndex(['2018-01-01', '2018-02-01', '2018-03-01', '2018-04-01',
               '2018-05-01', '2018-06-01', '2018-07-01', '2018-08-01',
               '2018-09-01', '2018-10-01', '2018-11-01', '2018-12-01',
               '2019-01-01', '2019-02-01', '2019-03-01', '2019-04-01',
               '2019-05-01', '2019-06-01', '2019-07-01', '2019-08-01',
               '2019-09-01', '2019-10-01', '2019-11-01', '2019-12-01'],
              dtype='datetime64[ns]', freq='MS')

Upvotes: 22

000
000

Reputation: 27247

>>> startyear = 2014
>>> startmonth = 4
>>> endyear = 2015
>>> endmonth = 2
>>> [datetime.date(m/12, m%12+1, 1) for m in xrange(startyear*12+startmonth-1, endyear*12+endmonth)]
[datetime.date(2014, 4, 1), datetime.date(2014, 5, 1), datetime.date(2014, 6, 1), datetime.date(2014, 7, 1), datetime.date(2014, 8, 1), datetime.date(2014, 9, 1), datetime.date(2014, 10, 1), datetime.date(2014, 11, 1), datetime.date(2014, 12, 1), datetime.date(2015, 1, 1), datetime.date(2015, 2, 1)]

For Python 3, you'll need to use range instead of xrange, and // (floor division) instead of / (which does float division in Python 3):

[datetime.date(m//12, m%12+1, 1) for m in range(startyear*12+startmonth-1, endyear*12+endmonth)]

Upvotes: 8

Ricky McMaster
Ricky McMaster

Reputation: 4647

You can use relativedelta from dateutil, and then create a function to use any date range:

from datetime import date
from dateutil.relativedelta import relativedelta

def mthStList(start_date, end_date):
    stdt_list = []
    cur_date = start_date.replace(day=1) # sets date range to start of month
    while cur_date <= end_date:
        stdt_list.append(cur_date)
        cur_date += relativedelta(months=+1)
    return stdt_list

mthStList(date(2012, 5, 26), date.today())

Upvotes: 2

Steinar Lima
Steinar Lima

Reputation: 7821

There is no reason to bruteforce this:

import datetime
from pprint import pprint

dt = datetime.date.today()
end = datetime.date(2015, 2, 1)
dates = []

while dt < end:
    if not dt.month % 12:
        dt = datetime.date(dt.year+1, 1, 1)
    else:
        dt = datetime.date(dt.year, dt.month+1, 1)
    dates.append(dt)

pprint(dates)

Output:

[datetime.date(2014, 4, 1),
 datetime.date(2014, 5, 1),
 datetime.date(2014, 6, 1),
 datetime.date(2014, 7, 1),
 datetime.date(2014, 8, 1),
 datetime.date(2014, 9, 1),
 datetime.date(2014, 10, 1),
 datetime.date(2014, 11, 1),
 datetime.date(2014, 12, 1),
 datetime.date(2015, 1, 1),
 datetime.date(2015, 2, 1)]

Upvotes: 2

Andrew Wilkinson
Andrew Wilkinson

Reputation: 10846

If you're only creating the list for a few years then efficiency should not be a concern. Clarity of code is the most important aspect.

dates = []
date = datetime.date.today()
while date.year < 2015:
    if date.day == 1:
        dates.append(date)
    date += datetime.timedelta(days=1)

Upvotes: 8

Related Questions