Skip to content

Instantly share code, notes, and snippets.

@bipinkrish
Last active June 9, 2023 11:41
Show Gist options
  • Save bipinkrish/5b676ad162db08b19d130e742bf4fb05 to your computer and use it in GitHub Desktop.
Save bipinkrish/5b676ad162db08b19d130e742bf4fb05 to your computer and use it in GitHub Desktop.
Find Day from Date
# Comparing with Zeller's Congruence formula gives us it is 1.15 times faster
import time
import random
from datetime import datetime, timedelta
# My approach
def get_day_of_week_alternative(day, month, year):
cen_odds = [0,5,3,1]
mon_odds = [0,3,3,6,8,11,13,16,19,21,24,26,29]
words = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]
rem = year % 100
odd_count = ((cen_odds[((year-rem)%400)%100]) + ((rem - 1) + ((rem - 1) // 4)) + (mon_odds[month - 1]) +
((day + 1) if ((rem % 4) == 0) and (month > 2 or (month == 2 and day == 29)) else day)) % 7
return words[odd_count]
# Zeller's Congruence approach
def get_day_of_week_zeller(day, month, year):
if month < 3:
month += 12
year -= 1
K = year % 100
J = year // 100
h = (day + (13 * (month + 1) // 5) + K + (K // 4) + (J // 4) - 2 * J) % 7
days_of_week = ["Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
return days_of_week[h]
# Performance test
num_tests = 100
start_time = time.time()
for _ in range(num_tests):
# Generate a random date within a range of years
start_date = datetime(1800, 1, 1)
end_date = datetime(2100, 12, 31)
random_date = start_date + timedelta(days=random.randint(0, (end_date - start_date).days))
day = random_date.day
month = random_date.month
year = random_date.year
get_day_of_week_alternative(day, month, year)
elapsed_time_alternative = time.time() - start_time
start_time = time.time()
for _ in range(num_tests):
# Generate a random date within a range of years
start_date = datetime(1800, 1, 1)
end_date = datetime(2100, 12, 31)
random_date = start_date + timedelta(days=random.randint(0, (end_date - start_date).days))
day = random_date.day
month = random_date.month
year = random_date.year
get_day_of_week_zeller(day, month, year)
elapsed_time_zeller = time.time() - start_time
print(f"Performance test for {num_tests} random dates:")
print(f"My approach (alternative): {elapsed_time_alternative} seconds")
print(f"Zeller's Congruence: {elapsed_time_zeller} seconds")
print()
if elapsed_time_alternative < elapsed_time_zeller:
print("My approach (alternative) is faster.")
speedup_factor = elapsed_time_zeller / elapsed_time_alternative
print(f"My approach is {speedup_factor:.2f} times faster than Zeller's Congruence.")
elif elapsed_time_alternative > elapsed_time_zeller:
print("Zeller's Congruence is faster.")
speedup_factor = elapsed_time_alternative / elapsed_time_zeller
print(f"Zeller's Congruence is {speedup_factor:.2f} times faster than your approach.")
else:
print("Both approaches have the same performance.")
day = 15
month = 8
year = 1947
cen_odds = [0,5,3,1]
mon_odds = [0,3,3,6,8,11,13,16,19,21,24,26,29]
words = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]
rem = year%100
# century odds year odds month odds day + month odds
odd_count = ((cen_odds[((year-rem)%400)%100]) + ((rem-1) + ((rem-1) // 4)) + (mon_odds[month-1]) + ((day+1) if ((rem%4) == 0) and (month>2 or (month==2 and day==29)) else day)) % 7
print(words[odd_count])
@bipinkrish
Copy link
Author

bipinkrish commented Jun 9, 2023

z

h is the day of the week (0 = Saturday, 1 = Sunday, 2 = Monday, ..., 6 = Friday)
q is the day of the month
m is the month (3 = March, 4 = April, ..., 12 = December). January and February are counted as months 13 and 14 of the previous year.
K is the year of the century (year % 100)
J is the zero-based century (actually floor(year/100))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment