2019-08-05 03:22:28 +00:00
|
|
|
import argparse
|
2020-07-06 07:44:19 +00:00
|
|
|
import datetime
|
2019-08-05 03:22:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
def zeller(date_input: str) -> str:
|
|
|
|
|
|
|
|
"""
|
|
|
|
Zellers Congruence Algorithm
|
2019-08-19 13:37:49 +00:00
|
|
|
Find the day of the week for nearly any Gregorian or Julian calendar date
|
2019-08-05 03:22:28 +00:00
|
|
|
|
|
|
|
>>> zeller('01-31-2010')
|
|
|
|
'Your date 01-31-2010, is a Sunday!'
|
|
|
|
|
|
|
|
Validate out of range month
|
|
|
|
>>> zeller('13-31-2010')
|
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
|
|
|
ValueError: Month must be between 1 - 12
|
|
|
|
>>> zeller('.2-31-2010')
|
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
|
|
|
ValueError: invalid literal for int() with base 10: '.2'
|
|
|
|
|
|
|
|
Validate out of range date:
|
|
|
|
>>> zeller('01-33-2010')
|
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
|
|
|
ValueError: Date must be between 1 - 31
|
|
|
|
>>> zeller('01-.4-2010')
|
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
|
|
|
ValueError: invalid literal for int() with base 10: '.4'
|
|
|
|
|
2020-01-18 12:24:33 +00:00
|
|
|
Validate second separator:
|
2019-08-05 03:22:28 +00:00
|
|
|
>>> zeller('01-31*2010')
|
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
2020-01-18 12:24:33 +00:00
|
|
|
ValueError: Date separator must be '-' or '/'
|
2019-08-05 03:22:28 +00:00
|
|
|
|
2020-01-18 12:24:33 +00:00
|
|
|
Validate first separator:
|
2019-08-05 03:22:28 +00:00
|
|
|
>>> zeller('01^31-2010')
|
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
2020-01-18 12:24:33 +00:00
|
|
|
ValueError: Date separator must be '-' or '/'
|
2019-08-05 03:22:28 +00:00
|
|
|
|
|
|
|
Validate out of range year:
|
|
|
|
>>> zeller('01-31-8999')
|
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
|
|
|
ValueError: Year out of range. There has to be some sort of limit...right?
|
|
|
|
|
|
|
|
Test null input:
|
|
|
|
>>> zeller()
|
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
|
|
|
TypeError: zeller() missing 1 required positional argument: 'date_input'
|
|
|
|
|
2020-01-18 12:24:33 +00:00
|
|
|
Test length of date_input:
|
2019-08-05 03:22:28 +00:00
|
|
|
>>> zeller('')
|
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
|
|
|
ValueError: Must be 10 characters long
|
|
|
|
>>> zeller('01-31-19082939')
|
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
|
|
|
ValueError: Must be 10 characters long
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Days of the week for response
|
|
|
|
days = {
|
2019-10-05 05:14:13 +00:00
|
|
|
"0": "Sunday",
|
|
|
|
"1": "Monday",
|
|
|
|
"2": "Tuesday",
|
|
|
|
"3": "Wednesday",
|
|
|
|
"4": "Thursday",
|
|
|
|
"5": "Friday",
|
|
|
|
"6": "Saturday",
|
2019-08-05 03:22:28 +00:00
|
|
|
}
|
|
|
|
|
2019-10-05 05:14:13 +00:00
|
|
|
convert_datetime_days = {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 0}
|
2019-08-05 03:22:28 +00:00
|
|
|
|
|
|
|
# Validate
|
|
|
|
if not 0 < len(date_input) < 11:
|
|
|
|
raise ValueError("Must be 10 characters long")
|
|
|
|
|
|
|
|
# Get month
|
|
|
|
m: int = int(date_input[0] + date_input[1])
|
|
|
|
# Validate
|
|
|
|
if not 0 < m < 13:
|
|
|
|
raise ValueError("Month must be between 1 - 12")
|
|
|
|
|
2019-10-05 05:14:13 +00:00
|
|
|
sep_1: str = date_input[2]
|
2019-08-05 03:22:28 +00:00
|
|
|
# Validate
|
2019-10-05 05:14:13 +00:00
|
|
|
if sep_1 not in ["-", "/"]:
|
2020-01-18 12:24:33 +00:00
|
|
|
raise ValueError("Date separator must be '-' or '/'")
|
2019-08-05 03:22:28 +00:00
|
|
|
|
|
|
|
# Get day
|
|
|
|
d: int = int(date_input[3] + date_input[4])
|
|
|
|
# Validate
|
|
|
|
if not 0 < d < 32:
|
|
|
|
raise ValueError("Date must be between 1 - 31")
|
2019-08-19 13:37:49 +00:00
|
|
|
|
2020-01-18 12:24:33 +00:00
|
|
|
# Get second separator
|
2019-08-05 03:22:28 +00:00
|
|
|
sep_2: str = date_input[5]
|
|
|
|
# Validate
|
2019-10-05 05:14:13 +00:00
|
|
|
if sep_2 not in ["-", "/"]:
|
2020-01-18 12:24:33 +00:00
|
|
|
raise ValueError("Date separator must be '-' or '/'")
|
2019-08-05 03:22:28 +00:00
|
|
|
|
|
|
|
# Get year
|
|
|
|
y: int = int(date_input[6] + date_input[7] + date_input[8] + date_input[9])
|
|
|
|
# Arbitrary year range
|
|
|
|
if not 45 < y < 8500:
|
2019-10-05 05:14:13 +00:00
|
|
|
raise ValueError(
|
|
|
|
"Year out of range. There has to be some sort of limit...right?"
|
|
|
|
)
|
2019-08-05 03:22:28 +00:00
|
|
|
|
|
|
|
# Get datetime obj for validation
|
|
|
|
dt_ck = datetime.date(int(y), int(m), int(d))
|
|
|
|
|
|
|
|
# Start math
|
|
|
|
if m <= 2:
|
|
|
|
y = y - 1
|
|
|
|
m = m + 12
|
|
|
|
# maths var
|
|
|
|
c: int = int(str(y)[:2])
|
|
|
|
k: int = int(str(y)[2:])
|
2019-10-05 05:14:13 +00:00
|
|
|
t: int = int(2.6 * m - 5.39)
|
2019-08-05 03:22:28 +00:00
|
|
|
u: int = int(c / 4)
|
|
|
|
v: int = int(k / 4)
|
|
|
|
x: int = int(d + k)
|
|
|
|
z: int = int(t + u + v + x)
|
|
|
|
w: int = int(z - (2 * c))
|
2019-10-05 05:14:13 +00:00
|
|
|
f: int = round(w % 7)
|
2019-08-05 03:22:28 +00:00
|
|
|
# End math
|
|
|
|
|
|
|
|
# Validate math
|
|
|
|
if f != convert_datetime_days[dt_ck.weekday()]:
|
|
|
|
raise AssertionError("The date was evaluated incorrectly. Contact developer.")
|
|
|
|
|
|
|
|
# Response
|
|
|
|
response: str = f"Your date {date_input}, is a {days[str(f)]}!"
|
|
|
|
return response
|
|
|
|
|
2019-10-05 05:14:13 +00:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2019-08-05 03:22:28 +00:00
|
|
|
import doctest
|
2019-10-05 05:14:13 +00:00
|
|
|
|
2019-08-05 03:22:28 +00:00
|
|
|
doctest.testmod()
|
2019-10-05 05:14:13 +00:00
|
|
|
parser = argparse.ArgumentParser(
|
2020-05-01 21:36:35 +00:00
|
|
|
description=(
|
|
|
|
"Find out what day of the week nearly any date is or was. Enter "
|
|
|
|
"date as a string in the mm-dd-yyyy or mm/dd/yyyy format"
|
|
|
|
)
|
2019-10-05 05:14:13 +00:00
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"date_input", type=str, help="Date as a string (mm-dd-yyyy or mm/dd/yyyy)"
|
|
|
|
)
|
2019-08-05 03:22:28 +00:00
|
|
|
args = parser.parse_args()
|
|
|
|
zeller(args.date_input)
|