Checking errors about year,month,day - python

1. The days enterred should be after 15/10/1582
2. Should consider the leapyears.
3. Even when "ctrl + c" or alphabets are enterred, the source code should go on (Use try...except)
3. Repeat until 0 is enterred in 'year'.
THis is what I tried.....
while True:
year = int(input("Year: "))
if year == 0
break
month = int(input("Month: ")
day = int(input("Days: "))
I completely can't think of how to solve this, so I'd like to get some hints how I should deal with this problem!
Year: 2019 Month: 0 Day: 12 There is only January ~ December
Year: 2019 Month: 1 Day: 0 Day should be at least 1
Year: 2019 Month: 1 Day: 32 January is upto 31
Year: 2020 Month: 2 Day: 30 2020 is a leapyear, but Feburary is upto
29
Year: 2019 Month: 2 Day: 29 2019 is not a leapyear, so Feburary is
upto 28
Year: 1582 Month:1 Day:1 1/1/1582 is before when Gregorian calender
started
Year: 2019 Month: 1 Day:8 OK
Year: 0

Well, the first thing to do, obviously, is to check whether your user inputs are proper numerics. As mentionned in the instructions, this can be done using exception handling (try/except blocks). Exception handling is documented so first check the doc and use the interactive shell to test out things until you get how ot works... Just a couple hints here: only catch the exact exceptions you expect at a given point, and have the less possible code in the try block so you're sure you only catch the exceptions raised by this exact piece of code.
(NB : Note that this can ALSO be done without exception handling by testing the content of the strings returned by input() _before_ passing them to int(), but you're obviously expected to use exception handling here, cf the "Use try/except" mention.)
The second thing is to validate that the individual values entered for day, month and year are in the expected range; ie there are only 12 month, so for this variable, any value lower than 1 (january) or higher than 12 (december) is invalid.
Note that since the number of days in a month changes from month to month and, for february, can change from year to year, you can only validate days once you know the month and the year.
I suggest you first make the "day" validation work without taking care of leap years, and only then take care of the leap year special case. As often, a good data structure is key to simple effective code, so read about the standard basic Python data types (lists, dicts, tuples etc) and think about which of those types you could use to map a month number to how many days it has (for a non leap year, that is).
There are quite a few other things to care of, but first manage to get those first two points working and the rest should not be too difficult.

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)

Python - Check every other week using if statement

I have the following if statement:
if date.weekday() != 0:
How can I change this if statement to check every other Monday (one day every other week)?
Thanks in advance for your help!
You post doesn't mention what language you're using. That would be useful to know!
At any rate, a function like weekday probably returns a number from 0-6, which isn't going to give you enough info.
Most languages have a function that turns a date into a millisecond value, typically milliseconds since 1970-01-01 00:00 UTC.
If you take such a value and divide it by 86400000 (number of milliseconds in a day), you get a day number. Day 0 (January 1, 1970) happens to be a Thursday.
In JavaScript, this day number can be obtained from a Date object like this:
let dayNum = Math.floor(someDate.getTime() / 86400000)
From this, dayNum % 7 gives you a number from 0-6 for Thursday through Wednesday. You can add an offset to change what 0 means. (dayNum + 4) % 7 produces 0-6 for Sunday through Saturday.
You want a 14-day cycle for every other week, so dayNum % 14 is what you need, and you then just have to decide which value from 0 to 13 represents your target dates.
Take any sample date that is one of your desired dates, compute the remainder value you get for that date, and then test for that value to be able to match any qualifying date.
Two caveats:
For dates before 1970, the % operator might produces negative numbers. Python is one of the few languages that doesn't do this.
The timezone offset from UTC might be important to your task. And if that's important, Daylight Saving Time changes and/or historical changes in UTC offset can complicate matters.
Python update:
Let's say this coming Monday (July 5, 2021) is one of the every-other-week days that you want. This:
date(2021, 7, 5).toordinal() % 14
...produces a value of 8. Every other Monday before or after will also be 8. The toordinal() method goes straight to a day number, without having to fuss with milliseconds, 86400000, or having to worry about timezone offsets.

Returning a variable instead of its assigned range

So I'm trying to write a program that calculates the date from a day out of the year (out of 365) and I'm having this problem in which I cannot get my for loop to work properly with python's range function. I.e.\
Day = input("Enter day: ")
january = range(1,32)
february = range(32,59)
etc....
months = [january,february,etc....]
for i in months
if Day in i:
return i
However this only ever returns range(x,y). I need it to return a position in the months array. Such as if day is 31 then it should return the [0] position (i=0), if day is 360 then it returns [12]. Is my for loop written wrong? My other solution to this would be telling it to return the variable name instead of what range it has assigned to it, however I have no idea how to do this.
The direct answer to your question is to user enumerate() to give the index:
for month, i in enumerate(months):
However, this seems like an overly complicated way to solve this problem. An alternative solution is to store the number of days in each month:
months = [31, 28, 31, etc.]
Then use plain ol' arithmethic as you loop over this list:
for days, month in enumerate(months):
if Day <= days:
return month+1, day
Day -= days
Note that this completely eliminates the need for you to calculate the first and last number for each month. I don't know about you, but I'd rather let the computer do the math than do it myself. Also, I still use enumerate here. Finally, I am returning both the month number and the day which basically reconstructs the calendar date. The +1 is to make January start at 1 instead of 0.
A python range has the .index(value, [start, [stop]]) function, giving the index of a value in the range.
This returns the first index of the value found, or raises a ValueError if it is not present.
Just return the index of i in months. Also, note, if Day is 31 and it returns the 0, then Day=360 should return 11 since the last index of months is 11 not 12.
Day = input("Enter day: ")
january = range(1,32)
february = range(32,59)
etc....
months = [january,february,etc....]
for i in months:
if Day in i:
return months.index(i)

Non-standard week numbering

I'm building an API for my college's timetable website. The default option is to look up today's timetable. However, the timetable system is using week numbering different to the one we normally use.
One of the 2 things I need to build the URL is the week number.
TIMETABLE_URL = 'http://timetable.ait.ie/reporting/textspreadsheet;student+set;id;{}?t=student+set+textspreadsheet&days=1-5&=&periods=3-20&=student+set+textspreadsheet&weeks={}&template=student+set+textspreadsheet'
Week numbering should start at this date: 27 Aug 2018 - 2 Sep 2018. Following this, week 2 would be 3 Sep 2018-9 Sep 2018 and so on. This should carry over New Years, the date of 31 Dec 2018-6 Jan 2019 would be week 19. This 'year' would have 52 weeks total.
I know how to check if a certain date is in between one of the ranges from above, but I want to avoid manually setting all the date ranges. How can I have a script know that, for example, it's in week 3 on 12 September?
Using datetime.datetime object:
from datetime import datetime
start = datetime.strptime('20180827', '%Y%m%d')
current = datetime.strptime('20180912', '%Y%m%d')
print((current - start).days//7 +1) # The week number
# Output: 3
This can also handle different years. Note that this only works when the start date is Monday.

Regarding simple python date calc

I am trying to find out when someone will turn 1 billion seconds old. the user inputs when they were born. These values are then converted to seconds and then I add 1 billion seconds and convert back into a date. However, when I enter certain dates, python seems to mess up. Such an example is 1993/11/05 00:00:00 where python says the user will turn in the 0th month.
Note I cant use if/else or datetime.
Heres my code:
YEARSEC=(12*30*24*3600)
MONTHSEC=(3600*24*30)
DAYSEC=(24*3600)
HOURSEC=3600
MINUTESEC=60
year=int(input("Please enter the year in which you were born: "))
month=int(input("Please enter the month you were born: "))
day=int(input("Please enter the day you were born: "))
hour=int(input("Please enter the hour you were born: "))
minute=int(input("Please enter the minute you were born: "))
second=int(input("Please enter the second you were born: "))
year_calc=(year*YEARSEC)
month_calc=(month*MONTHSEC)
day_calc=(day*DAYSEC)
hour_calc=(hour*HOURSEC)
minute_calc=(minute*MINUTESEC)
s=(1000000000+year_calc+month_calc+day_calc+hour_calc+minute_calc+second)
year_num=int((s/YEARSEC))
s=(s-(year_num*YEARSEC))
month_num=int((s/MONTHSEC))
s=(s-(month_num*MONTHSEC))
day_num=int((s/DAYSEC))
s=(s-(DAYSEC*day_num))
hour_num=int((s/HOURSEC))
s=(s-(HOURSEC*hour_num))
minute_num=int((s/MINUTESEC))
s=(s-(MINUTESEC*minute_num))
print("You will turn 1 000 000 000 seconds old on: %04d/%02d/%02d %02d:%02d:%02d" %(year_num,month_num,day_num,hour_num,minute_num,s))
Though I have not test it all, I think you can not get Dec and day 30.
You should plus 1 to day_num and month_num cause month and day start from 1 not 0.
print("You will turn 1 000 000 000 seconds old on: %04d/%02d/%02d %02d:%02d:%02d" %(year_num,month_num+1,day_num+1,hour_num,minute_num,s))
Time calculations are tricky. Months don't all have 30 days, for example. Hours, minutes, and seconds are numbered starting from 0, but days and months are numbered starting from 1, creating off-by-one bugs in your calculations (hint, ask for month, then subtract one, do all the calculations, then add one when displaying it again). You aren't accounting for leap years either.
Best to use built-in tools, if only to check your eventual homework answer, although it looks like the teacher said to assume 30-day months ;^)
>>> import datetime
>>> birthday = datetime.datetime(1993,11,05,0,0,0)
>>> billion = birthday + datetime.timedelta(seconds=1000000000)
>>> billion.ctime()
'Mon Jul 14 01:46:40 2025'

Categories