I'm teaching myself python to ATBS. Instead of spending 45 minutes typing out a bunch of repetitive data in excel I've spent the past 90 failing to write a simple calendar script.
Starting with the values "2012-09-01" and "2012-09-30" I want to each line to increase the month value by 1 it hits 12 and at which point the year value advances by 1, until the date 2018-12-31.
e.g.
"2012-09-01 2012-09-30
2012-10-01 2012-10-31
2012-11-01 2012-11-30
2012-12-01 2012-12-31"
Here's my code, which stops at 2012-12-31.
import datetime
year = 2012
month = 9
day_start = 1
day_end = 31
while year <= 2018:
while month <= 12:
if month == 4 or month == 6 or month == 9 or month == 11:
day_end = 30
else:
day_end = 31
print(datetime.date(year, month, day_start), " ", datetime.date(year, month, day_end))
month = month + 1
year = year + 1
Any help is much appreciated!
Check this out. Using the calendar library to detect leap years.
import datetime
import calendar
year = 2012
month = 9
day_start = 1
day_end = 31
while year <= 2018:
while month <= 12:
if month == 4 or month == 6 or month == 9 or month == 11:
day_end = 30
elif month == 2:
day_end = 29 if calendar.isleap(year) else 28
else:
day_end = 31
print(datetime.date(year, month, day_start), " ", datetime.date(year, month, day_end))
month = month + 1
year = year + 1
month = 1
Line
if month == 4 or month == 6 or month == 9 or month == 11:
can be abbreviated to:
if month in (4, 6, 9, 11):
Related
How can i find all 'friday the 13th' due year 2000 to 2020 by python and have it print as below using a nested for loop:
print(i,k,13,"is friday the 13th!")
ex)
2000 10 13 is friday the 13th!
2001 4 13 is friday the 13th!
...
2020 11 13 is friday the 13th!
Based on your code in the comments, this should work for you:
from datetime import date, timedelta
def friday_13_in_year(y):
day = date(y, 1, 1)
end = date(y, 12, 31)
one_day = timedelta(days=1)
while day < end:
if day.weekday() == 4 and day.day == 13:
return str(day)+" is friday the 13th!"
day += one_day
print([friday_13_in_year(y) for y in range(2000, 2022+1)])
l=[i for i in ((datetime.datetime.strptime('20000101','%Y%m%d')+datetime.timedelta(days=i)) for i in range(7306)) if i.day == 13 and i.weekday() == 4]
l lists all Fridays 13th from 2000 to 2020. 20 years in days is 20*365.25+1 = 7306
So i have this problem, I want to calculate an amount of money between the first and last day of the month.
Example:
I am going to receive a payment of $1000 for a job that is going to take 3 months but i want to subtract the amount I'm going to receive each month lets say I work 8 a day 5 days a week.
def get_montly_adjustments(self, start_date, end_date, project_id):
# calculating the month first day and last day
month_range = monthrange(year, month)
first_day_month_str = "%s-%s-01" % (year, month)
last_day_month_str = "%s-%s-01" % (year, month, month_range[1])
month_first_day = datetime.strptime(first_day_month_str, "%Y-%m-%d")
month_last_day = datetime.strptime(last_day_month_str, "%Y-%m-%d")
I have created a function to calculate the first and last day of the month but im looking for an idea on how to calculate the amount?
Thanks!.
First, let's not convert a date to string and parse it back. We can do better:
def get_montly_adjustments(self, start_date, end_date, project_id):
first_of_month = date(start_date.year, start_date.month, 1)
last_of_month = date(start_date.year, start_date.month + 1, 1) + timedelta(-1)
Assuming that workdays are Monday through Friday, I get
day = first_of_month
workdays = 0
while day <= last_of_month:
if day.weekday() not in [5, 6]: # Saturday, Sunday
workdays += 1
day += timedelta(1)
print(f"workdays: {workdays}")
It's not clear to me how you expect to be paid. This probably depends on country and law regulations. One approach would be as follows
Starting on 2021-06-09, work until 2021-09-08 (3 months) gives 4 payments:
9 to 30 in June = 22 days (= x workdays)
1 to 31 in July = 31 days (= x workdays)
1 to 31 in August = 31 days (= x workdays)
1 to 8 in September = 8 days (= x workdays)
Code for that:
def get_montly_adjustments(self, start_date, end_date, project_id):
# Calculate all workdays in project range
day = start_date
last_of_month = date(day.year, day.month + 1, 1) + timedelta(-1)
workdays = 0
workdayspermonth = []
while day <= end_date:
if day.weekday() not in [5, 6]:
workdays += 1
if day == last_of_month or day == end_date:
workdayspermonth.append(workdays)
workdays = 0
last_of_month = date(day.year, day.month + 2, 1) + timedelta(-1) # next last of month
day += timedelta(1)
# Get to the money
monthnames = {1: "Jan", 2: "Feb", 3: "Mar", 4: "Apr", 5: "May", 6: "Jun", 7: "Jul", 8: "Aug", 9: "Sep", 10: "Oct",
11: "Nov", 12: "Dec"}
totalworkdays = sum(workdayspermonth)
print(f"Total workdays: {totalworkdays}")
moneyperday = 1000 / totalworkdays
print(f"That's an awesome {moneyperday:.2f} USD per day")
for month in range(len(workdayspermonth)):
workdays = workdayspermonth[month]
print(f"Get paid! {workdays * moneyperday:.2f} USD for {workdays} workdays in {monthnames[start_date.month + month]}")
Output for
get_montly_adjustments(None, date(2021, 6, 9), date(2021, 9, 9), 815)
is
Total workdays: 67
That's an awesome 14.93 USD per day
Get paid! 238.81 USD for 16 workdays in Jun
Get paid! 328.36 USD for 22 workdays in Jul
Get paid! 328.36 USD for 22 workdays in Aug
Get paid! 104.48 USD for 7 workdays in Sep
I'm going to use pandas date range but perhaps someone can modify it for datetime.
create the days in the month range:
days = pd.date_range("01/01/2021", "03/01/2021", freq="D")
state what days you work:
working_days = ["Mon", "Tue", "Wed", "Thu", "Fri"]
Find the days in the month you would work in that time:
worked_days = days[days.strftime('%a').isin(days_worked)]
multiply the number of days worked by your price per day:
cost = len(worked_days)*8*price_per_hour
You may need to take into account bank holidays, days off etc.
Given a week number, (1st, 2nd, …), the day on which the 1st of the month falls (1 for Monday, 2 for Tuesday, …), and the number of days in the month: return a string consisting of the day of the month for each day in that week, starting with Monday and ending with Sunday. Week number represents the weeks in the months.
I have done the following functions:
My code for these functions are below.
import datetime
from datetime import datetime
import calendar
from datetime import date
def week(week_num, start_day, days_in_month):
week_string = ""
if week_num == 1:
if start_day == 1:
week_string = "1 2 3 4 5 6 7"
elif start_day == 2:
week_string = " 1 2 3 4 5 6"
elif start_day == 3:
week_string = " 1 2 3 4 5"
elif start_day == 4:
week_string = " 1 2 3 4"
elif start_day == 5:
week_string = " 1 2 3"
elif start_day == 6:
week_string = " 1 2"
elif start_day == 7:
week_string = " 1"
elif week_num == 2:
if start_day == 1:
week_string = "8 9 10 11 12 13 14"
elif start_day == 2:
week_string = "7 8 9 10 11 12 13"
elif start_day == 3:
week_string = "6 7 8 9 10 11 12"
elif start_day == 4:
#carry on in the above way, but this doesn't seem efficient
return week_string
def main():
month_name = input("Enter month:\n")
year = eval(input("Enter year:\n"))
if __name__=='__main__':
main()
Does anyone have any ideas on how to do the function? I need to return a string value
Another idea I had:
def week(week_num, start_day, days_in_month):
week_string = ""
if week_num == 1:
week_string = ""
day = start_day
for i in range(1, 8 -start_day+1):
week_string = week_string + str(i) + " "
week_string = "{0:<20}".format(week_string)
return week_string
An example of the input and output of this function:
week(1, 3, 30)
returns the string
' 1 2 3 4 5'
week(2, 3, 30)
returns the string
' 6 7 8 9 10 11 12’
edit: you heavily altered your question, I'll update my response once I'll understand what you need
datetime and calendar modules should supply you with all you need
from datetime import datetime
import calendar
# is leapyear
calendar.isleap(2020) # True
# just add +1 if you need it in the format that you want
datetime.strptime('25.2.2020', '%d.%m.%Y').weekday() # = 1 = Tuesday
# from name to month number
datetime.strptime('february', '%B').month # = 2
# days in month and weekday of starting month
# with the starting weekday you can easily calculate the number of weeks
calendar.monthrange(2020,2) # = (5, 29), 5=saturday, 29 days in month
Some general remarks to your code:
You can use 'January'.upper() to convert it to 'JANUARY' and only need to check month_name=='JANUARY' and save you the redundant comparison
You can use if month_num in [1,3,5,7,8,10,12]: to make it more readable
I have a dataframe with a column that includes individuals' birthdays. I would like to map that column to the individuals' astrology sign using code I found (below). I am having trouble writing the code to creat the variables.
My current dataframe looks like this
birthdate answer YEAR MONTH-DAY
1970-03-31 5 1970 03-31
1970-05-25 9 1970 05-25
1970-06-05 3 1970 06-05
1970-08-28 2 1970 08-28
The code I found that creates a function to map the dates is available at this website: https://www.geeksforgeeks.org/program-display-astrological-sign-zodiac-sign-given-date-birth/
Any tips would be appreciated.
Change previous answer by Series.dt.month_name with lowercase strings:
def zodiac_sign(day, month):
# checks month and date within the valid range
# of a specified zodiac
if month == 'december':
return 'Sagittarius' if (day < 22) else 'capricorn'
elif month == 'january':
return 'Capricorn' if (day < 20) else 'aquarius'
elif month == 'february':
return 'Aquarius' if (day < 19) else 'pisces'
elif month == 'march':
return 'Pisces' if (day < 21) else 'aries'
elif month == 'april':
return 'Aries' if (day < 20) else 'taurus'
elif month == 'may':
return 'Taurus' if (day < 21) else 'gemini'
elif month == 'june':
return 'Gemini' if (day < 21) else 'cancer'
elif month == 'july':
return 'Cancer' if (day < 23) else 'leo'
elif month == 'august':
return 'Leo' if (day < 23) else 'virgo'
elif month == 'september':
return 'Virgo' if (day < 23) else 'libra'
elif month == 'october':
return 'Libra' if (day < 23) else 'scorpio'
elif month == 'november':
return 'scorpio' if (day < 22) else 'sagittarius'
dates = pd.to_datetime(astrology['birthdate'])
y = dates.dt.year
now = pd.to_datetime('now').year
astrology = astrology.assign(month = dates.dt.month_name().str.lower(),
day = dates.dt.day,
year = y.mask(y > now, y - 100))
print (astrology)
birthdate answer YEAR MONTH-DAY month day year
0 1970-03-31 5 1970 03-31 march 31 1970
1 1970-05-25 9 1970 05-25 may 25 1970
2 1970-06-05 3 1970 06-05 june 5 1970
3 1970-08-28 2 1970 08-28 august 28 1970
astrology['sign'] = astrology.apply(lambda x: zodiac_sign(x['day'], x['month']), axis=1)
print (astrology)
birthdate answer YEAR MONTH-DAY month day year sign
0 1970-03-31 5 1970 03-31 march 31 1970 aries
1 1970-05-25 9 1970 05-25 may 25 1970 gemini
2 1970-06-05 3 1970 06-05 june 5 1970 Gemini
3 1970-08-28 2 1970 08-28 august 28 1970 virgo
You can apply the zodiac_sign function to the dataframe as -
import pandas as pd
from io import StringIO
# Sample
x = StringIO("""birthdate,answer,YEAR,MONTH-DAY
1970-03-31,5,1970,03-31
1970-05-25,9,1970,05-25
1970-06-05,3,1970,06-05
1970-08-28,2,1970,08-28
""")
df = pd.read_csv(x, sep=',')
df['birthdate'] = pd.to_datetime(df['birthdate'])
df['zodiac_sign'] = df['birthdate'].apply(lambda x: zodiac_sign(x.day, x.strftime("%B").lower()))
print(df)
Output:
birthdate answer YEAR MONTH-DAY zodiac_sign
0 1970-03-31 5 1970 03-31 aries
1 1970-05-25 9 1970 05-25 gemini
2 1970-06-05 3 1970 06-05 Gemini
3 1970-08-28 2 1970 08-28 virgo
I'm writing a program where the user will input 3 numbers the day month and year and it will output in the format 2nd January 2014. So far i have done this
year =input("what year is it")
month=int(input("what is the numerical value of the month"))
day=input("what number day is it")
if month == 1:
January = str(month)
if day == 1 or 21 or 31:
print (day+"st January",year)
elif day == 2 or 22:
print (day+"nd January",year)
elif day ==3 or 23:
print (day+"rd January",year)
elif day == 4 or 5 or 6 or 7 or 8 or 9 or 10 or 11 or 12 or 13 or 14 or 15 or 16 or 18 or 19 or 20 or 24 or 25 or 26 or 27 or 28 or 29 or 30:
print (day+"th January",year)
the problem i have run into is that when i input a day such as 4 it will ouput as 4st January 2014.
I am using python 3 and have learnt for and while loops and also if statements if that helps
Use the libraries and dictionaries, a good rule to remember is if you need more than two ifs a dictionary might be better.
from datetime import date
ext_dir = {1:'st.', 2:'nd.', 3:'rd.',
21:'st.', 22:'nd.', 23:'rd.',
31:'st.' } # all the rest are th
# prompt for the year month day as numbers remember to int them
thedate = date(year, month, day)
ext = ext_dir.get(day, 'th.')
datestr = thedate.strftime('%%d%s %%M %%Y' % ext)
The problem you are running in to is that when you perform the check:
if day == 1 or 21 or 31:
operator precedence in python makes this statement act something like this:
if (day == 1) or (21) or (31):
and in python, like many other languages, non-null/non-zero values are "true", so you always evaluate to true in the first test. To fix this, modify the if statement, and all of the following tests to look more like the following:
if (day == 1) or (day == 21) or (day == 31):
year =input("what year is it")
month=int(input("what is the numerical value of the month"))
day=input("what number day is it")
if month == 1:
January = str(month)
if day == 1 or day == 21 or day == 31:
print (day+"st January",year)
elif day == 2 or day == 22:
print (day+"nd January",year)
elif day ==3 or day == 23:
print (day+"rd January",year)
else:
print (day+"th January",year)