More Efficient way to code this? - python

I'm supposed to get the excel date of Dec 1 2011 and what day of the week it is and print it out in this format. The Excel date for Thursday, 2011-Dec-1 is 40878. I've been able to get both, but I don't think my method of getting the day using if statements is the best approach. This is my Original script file, so please forgive the roughness. I've checked and I know my solution are right. My only problem is getting a more efficient way to get the day and any suggestions on how to get the month in my final output.
We haven't done the date time module yet,so I can't experiment with that.
here is my code:
Year=2011
Month=12
Day=1
Y2=Year-1900
en=int((14-Month)/12)
Y3=Y2-en
m2=Month+12*
l=1+min(Y3,0)+int(Y3/4)-int(Y3/100)+int((Y3+300)/400)
d1=int(-1.63+(m2-1)*30.6)
import math
d2=math.floor(Day+Y3*365+l+d1) #d2 is the final excel date.
Day_Of_Week=((d2%7)-1)
print "%s"%(d2)
if Day_Of_Week==0:
print "sun"
if Day_Of_Week ==1:
print "mon"
if Day_Of_Week==2:
print"tue"
if Day_Of_Week==3:
print "wed"
if Day_Of_Week==4 :
print "thur"
if Day_Of_Week==5:
print "fri"
if Day_Of_Week==6:
print "sat"
Any Help will be appreciated :)

How about:
days = ['sun', 'mon', 'tue', 'wed', 'thur', 'fri', 'sat']
print days[Day_Of_week]
Also take a look at this: How do I read a date in Excel format in Python?

"""I'm supposed to get the excel date of Dec 1 2011""": There is no such thing as the Excel date". There are two" date systems in use by Excel, one where the epoch is in 1900 [the default in Windows Excel] and the other using 1904 [the default in Windows for the Mac.
See the xlrd documentation; there's a section up front about dates, and check out the functions that have xldate in their names.
>>> import xlrd
>>> xlrd.xldate.xldate_from_date_tuple((2011,12, 1), 0) # Windows origin
40878.0
>>> xlrd.xldate.xldate_from_date_tuple((2011,12, 1), 1) # Mac origin
39416.0

Thanks for all your help,I was able to do it in a better way ,but couldn't post it up until our assignments had been graded.
This is what i did:
from math import floor
def calcExcelDate(Year, Month,Day):
Yr_Offset=Year-1900 #Determines year offset from starting point.
Early_Mnth_Correctn=int((14-Month)/12)
#Early month correction:makes the year have 14 months so the leap day is added at the end of the year
DateCorrector=(Yr_Offset)-(Early_Mnth_Correctn) #Corrects Date
MonthCorrector=Month+12*Early_Mnth_Correctn #Corrects Month
Leapyr_Calc=1+min(DateCorrector,0)+int(DateCorrector/4)-int(DateCorrector/100)+int ((DateCorrector+300)/400)
#calculates no of leap years since starting point
char=int(floor(-1.63+(MonthCorrector-1)*30.6))
#determines the number of days preceding the given month in a non leap year.
Excel_Date=(Day+DateCorrector*365+Leapyr_Calc+char )
Days=["Monday","Tuesday","Wednesday","Thursday","Friday","saturday","sunday"]
Months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]
Offset=2
dayNo=(Excel_Date-Offset)%7
dayOfWk=Days[dayNo]
return "The excel date of %r %r-%r-%r is %r"%(dayOfWk,Day,Months[Month-1],Year,Excel_Date)

Related

Python: Find date of monday of a given calender week in a given year

I have a questions about Python.
My goal is the following: Let a year and a calender week be given. Then I want to find the calender date of the Monday of this calender week.
I want to use the calender week standard ISO 8601, see https://en.wikipedia.org/wiki/Week#Numbering
I have written the following code:
def calWeekMonday(year,calWeek):
firstDayOfYear = int(dt.date(year,1,1).strftime("%w")) # first day of year as a number
if calWeek > 53:
return "There exists no calender week greater than 53."
elif calWeek == 53 and firstDayOfYear != 4:
# a year has 53 calender weeks if and only if it starts with Thursday
return "There is no calender week 53 in this year."
else:
if firstDayOfYear < 4: # then Jan 1st is in week 1 of the new year
mondayWeek1 = dt.date(year, 1, 1) + dt.timedelta(days=-(firstDayOfYear - 1))
else: # then Jan 1st is in last week of old year
mondayWeek1 = dt.date(year, 1, 1) + dt.timedelta(days=7 - firstDayOfYear + 1)
# calculate monday of calWeek
wantedMonday = mondayWeek1 + dt.timedelta(weeks=(calWeek - 1))
return wantedMonday
I have tested some examples and they work, but I am worried that I haven't considered all special cases (there are a loooot of them). Maybe someone can help me with the following questions:
Is there any way to make sure that my code works for ALL special cases?
Does anyone see a mistake in my code?
Does anyone have any improvements?
Is there a faster/easier way to do it, for example, is there any package which might help me (I tried to find something, but I wasn't successfull).
I am happy about any help and want to say thank you in advance!
At the moment, your function works for most inputs. Of course, if you are handling week 53+, then do you want to handle non-positive inputs? If you give a zero/negative week-number then the function gives a date from a different year, is this what you want?
Negative years give an error (obviously), do you want to handle that?
Finally, you haven't considered leap years in your '53-week years must start on Thursday' rule (2020 was 53-week but started on Wednesday)

Work out if date is in current week python

I'm trying to write a bit of code to check if a document has been updated this week, and if not to read in the data and update it. I need to be able to check if the last modified date/time of the document occurred in this week or not (Monday-Sunday).
I know this code gives me the last modified time of the file as a float of secconds since the epoch:
os.path.getmtime('path')
And I know I can use time.ctime to get that as a string date:
time.ctime(os.path.getmtime('path'))
But I'm not sure how to check if that date was in the current week. I also don't know if its easier to convert to a datetime object rather than ctime for this?
you can use datetime.isocalendar and compare the week attribute, basicallly
import os
from datetime import datetime
t_file = datetime.fromtimestamp(os.path.getmtime(filepath))
t_now = datetime.now()
print(t_file.isocalendar().week == t_now.isocalendar().week)
# or print(t_file.isocalendar()[1]== t_now.isocalendar()[1])
# to compare the year as well, use e.g.
print(t_file.isocalendar()[:2] == t_now.isocalendar()[:2])
The ISO year consists of 52 or 53 full weeks, and where a week starts on a Monday and ends on a Sunday. The first week of an ISO year is the first (Gregorian) calendar week of a year containing a Thursday. This is called week number 1, and the ISO year of that Thursday is the same as its Gregorian year.

Make conditional changes to numerous dates

I'm sure this is really easy to answer but I have only just started using Pandas.
I have a column in my excel file called 'Day' and a Date/time column called 'Date'.
I want to update my Day column with the corresponding day of NUMEROUS Dates from the 'Date' column.
So far I use this code shown below to change the date/time to just date
df['Date'] = pd.to_datetime(df.Date).dt.strftime('%d/%m/%Y')
And then use this code to change the 'Day' column to Tuesday
df.loc[df['Date'] == '02/02/2018', 'Day'] = '2'
(2 signifies the 2nd day of the week)
This works great. The problem is, my excel sheet has 500000+ rows of data and lots of dates. Therefore I need this code to work with numerous dates (4 different dates to be exact)
For example; I have tried this code;
df.loc[df['Date'] == '02/02/2018' + '09/02/2018' + '16/02/2018' + '23/02/2018', 'Day'] = '2'
Which does not give me an error, but does not change the date to 2. I know I could just use the same line of code numerous times and change the date each time...but there must be a way to do it the way I explained? Help would be greatly appreciated :)
2/2/2018 is a Friday so I don't know what "2nd day in a week" mean. Does your week starts on Thursday?
Since you have already converted day to Timestamp, use the dt accessor:
df['Day'] = df['Date'].dt.dayofweek()
Monday is 0 and Sunday = 6. Manipulate that as needed.
If got it right, you want to change the Day column for just a few Dates, right? If so, you can just include these dates in a separated list and do
my_dates = ['02/02/2018', '09/02/2018', '16/02/2018', '23/02/2018']
df.loc[df['Date'].isin(my_dates), 'Day'] = '2'

Pandas sets datetime to first day of month if missing day?

When I used Pandas to convert my datetime string, it sets it to the first day of the month if the day is missing.
For example:
pd.to_datetime('2017-06')
OUT[]: Timestamp('2017-06-01 00:00:00')
Is there a way to have it use the 15th (middle) day of the month?
EDIT:
I only want it to use day 15 if the day is missing, otherwise use the actual date - so offsetting all values by 15 won't work.
While this isn't possible using the actual call, you could always use regex matching to figure out if the string contains a date and proceed accordingly. Note: this code only works if using '-' delimited dates:
import re
date_str = '2017-06'
if (not bool(re.match('.+-.+-.+',date_str))):
pd.to_datetime(date_str).replace(date=15)
else:
pd.to_datetime(date_str)

How format date into BYDAY (iCalendar specification)

I need to create RRULE string with BYDAY parameter, from my date value.
Is there any natural way to do it?
I wrote this utility code for this purpose:
import calendar
fweek_fday, mdays = calendar.monthrange(date.year, date.month)
# Get weekday of first day and total days in current month
mweeks = ((mdays+fweek_fday-1)//7)+1
# Get total weeks in current month
mday, wday = date.day, date.weekday()
# Get current day of month and current day as day of a week
week_days = ['MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU']
week = ((mday+fweek_fday-1)//7)+(1 if wday>=fweek_fday else 0)
# Get current week no
week = -1 if week == mweeks else week
wday = week_days[wday]
output = "BYDAY=%d%s" % (week, wday)
as you said in comment there is no module that I've found yet to make a rule out from a set of constraints.
should it be possible for you, you may consider the RDATE rather than going for the BYDAY.
another option for you would be:
import datetime
(y,w,d ) = date.isocalendar()
#w will be the iso week number, d the day of week
(y2,wb,d2) = datetime.datetime(date.year,date.month,1).isocalendar()
wkcount = 1 if d>=d2 else 0
# you need to account whether your date is a weekday after the one of the first of the month or not
print "BYDAY=%d%s"%(w-wb+wkcount,date.strftime("%a").upper()[0:2])
however be careful should your rule also include WKST
The natural way to do this—unless you're writing an iCalendar library—is to use a pre-existing iCalendar library that has methods for dealing with recurrence rules, etc., as objects instead of doing string parsing and generation.
It's possible that there is no such library, in which case you're out of luck. But the first thing you should do is look for one.
A quick search at PyPI turns up many possibilities. The first one, iCalendar, is described as "a parser/generator of iCalendar files", which sounds like a good candidate. Skim the docs, or just pip install it and play with it, to see if it can do what you want.

Categories