Henri
Henri

Reputation: 1235

Function to create a list of months where januari is a date and other months are strings

I aim to develop a function that creates the list target_list, see below. Target list has the following structure, it always starts with a date, '1995-01-01', then follows eleven elements representing the following eleven month of the year. After 'dec' I want a new datestring, '1996-01-01' and then comes the months as last year.

Target list below has length 27. I want the function to has the length of target_list as a parameter. If 28, one element would be added to target_list('april').

target_list=['1995-01-01','feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec', '1996-01-01',
'feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec', '1997-01-01', 'feb', 'mar']

The code below returns the list I want. Because I want a list of 27 months I loop over 3 years. That force me to remove the last nine elements of the list. I struggle to find a way to make this process automated. Perhaps I want a list of 145 months. The function must know how many elements to remove. This I haven't figured out. Any help or recommendations would be much appreciated. Of course more efficient solutions is also of great interest.

import math
from datetime import datetime
from datetime import date

def add_years(d, years):
    try:
        return d.replace(year = d.year + years)
    except ValueError:
        return d + (date(d.year + years, 1, 1) - date(d.year, 1, 1))

year=pd.to_datetime('1994-01-01')
years=math.ceil(27/12) #For 27 month I need three years. Use math.ceil to "round" upwards.

target=[] 

for i in range(1,years+1): # Loop over the number of years
    year=add_years(year,1) # Add one year for each loop
    y=[year.strftime("%Y-%m-%d")] 
    z=y+ month # Concat the lists
    
    target=target + z # Concat with target
    
target_list=target[:len(target)-9] # Remove the last nine elements of the list 

print(target_list)

This is one solution.

def get_list(no_month):
    
    import math

    year=pd.to_datetime('1994-01-01')
    years=math.ceil(no_month/12)
    remove=(years*12)-no_month
    target=[]
    
    for i in range(1,years+1): # Loop over the number of years involved
        year=add_years(year,1) # Add one year for each loop
        y=[year.strftime("%Y-%m-%d")] 
        z=y+ month # Concat the lists
    
        target=target + z # Concat with target
    
    target_list=target[:len(target)-remove]
    
    return target_list

Upvotes: 2

Views: 86

Answers (6)

Adon Bilivit
Adon Bilivit

Reputation: 27043

You could do it like this:

from datetime import datetime
from dateutil.relativedelta import relativedelta

FORMAT = '%Y-%m-%d'

def genvals(start_date, length):
    d = datetime.strptime(start_date, FORMAT)
    for _ in range(length):
        yield datetime.strftime(d, FORMAT) if d.month == 1 else d.strftime('%b')
        d += relativedelta(months=1)

def genlist(start_date, length):
    return [d for d in genvals(start_date, length)]

print(genlist('1994-01-01', 27))

Output:

['1994-01-01', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', '1995-01-01', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', '1996-01-01', 'Feb', 'Mar']

Note:

The actual output will vary depending on your locale

Upvotes: 1

Anass
Anass

Reputation: 436

from datetime import date
import pandas as pd

months = ['feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec']
def add_years(d, years):
    """Return a date that's `years` years after the date (or datetime)
    object `d`. Return the same calendar date (month and day) in the
    destination year, if it exists, otherwise use the following day
    (thus changing February 29 to March 1).

    """
    try:
        return d.replace(year = d.year + years)
    except ValueError:
        return d + (date(d.year + years, 1, 1) - date(d.year, 1, 1))
    
def create_target_list(n):
    m = n//12 # floor division to get the number of times
    date_zero = '1995-01-01'
    date_zero=pd.to_datetime(date_zero)
    target_list = []
    for k in range(m):
        target_list.append(str(date_zero)[:10])
        target_list.extend(months)
        date_zero = add_years(date_zero, 1)
    if n%12 > 0 :
        if n%12 == 1:
            target_list.append(str(date_zero)[:10])
        else :
            target_list.append(str(date_zero)[:10])
            target_list.extend(months[:n%12-1]) 
    return target_list

#print(create_target_list(26))

Upvotes: 1

palmarbg
palmarbg

Reputation: 159

date = "1995-01-01"
numberOfMonth = 27
month =['feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec']

date=int(date[0:4])
output = []

for i in range(numberOfMonth):
    if not i%12:
        output.append(str(date+i//12)+"-01-01")
    else:
        output.append(month[i%12-1])

print(output)

Upvotes: 1

sudden_appearance
sudden_appearance

Reputation: 2197

You can do the following

from datetime import datetime, timedelta


def target_list(length=27):
    target = []
    start = datetime.strptime("1995-01-01", "%Y-%m-%d")
    for i in range(length // 12 + (1 if length % 12 != 0 else 0)):
        target.extend([
            start.replace(year=start.year + i).strftime("%Y-%m-%d"),
            'feb',
            'mar',
            'april',
            'maj',
            'jun',
            'juli',
            'aug',
            'sep',
            'okt',
            'nov',
            'dec',
        ])
    return target[:length]

print(target_list())

This will populate the list with full 12 values and then will cut it by the given length

Upvotes: 1

Daweo
Daweo

Reputation: 36550

I would use itertools for this task as follows

import itertools
def months():
    year = itertools.count(1995)
    for m in itertools.cycle(['y', 'feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec']):
        yield '{}-01-01'.format(next(year)) if m=='y' else m
target145 = list(itertools.islice(months(),145))
print(target145)

output

['1995-01-01', 'feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec', '1996-01-01', 'feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec', '1997-01-01', 'feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec', '1998-01-01', 'feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec', '1999-01-01', 'feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec', '2000-01-01', 'feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec', '2001-01-01', 'feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec', '2002-01-01', 'feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec', '2003-01-01', 'feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec', '2004-01-01', 'feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec', '2005-01-01', 'feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec', '2006-01-01', 'feb', 'mar', 'april', 'maj', 'jun', 'juli', 'aug', 'sep', 'okt', 'nov', 'dec', '2007-01-01']

Explanation: firstly I create endless iterator months, internally I use itertools.cycle to cycle month codes, I used y letter to denote where year should appear, when it so I take next year starting from 1995. I use .format to get desired str holding year, otherwise month case is provided as-is. Then I get 145 first elements of endless months() and convert it into list to comply with requirements imposed.

Upvotes: 2

Karsten Gabriel
Karsten Gabriel

Reputation: 3672

You want to know how much months are left for a full year and can use modulo for that:

months = 27
toRemove = 12 - (months % 12)

Upvotes: 1

Related Questions