Advertisement
Geometrian

Calculating Weekdays

Mar 7th, 2015
520
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.00 KB | None | 0 0
  1. from datetime import date
  2. import random
  3. import time
  4.  
  5. try:    input_func=raw_input
  6. except: input_func=input
  7.  
  8.  
  9. #Coded by Ian Mallett
  10. #   http://pastebin.com/eGWj0TNK
  11.  
  12. def calculate_is_leapyear(year):
  13.     is_leapyear = False
  14.     if year%4==0:
  15.         is_leapyear = True
  16.         if year%100==0:
  17.             is_leapyear = False
  18.             if year%400==0:
  19.                 is_leapyear = True
  20.     return is_leapyear
  21. def calculate_weekday(year,month,day):
  22.     #Execute algorithm you should use to mentally calculate any day-of-the-week.  It is the easiest known.
  23.     #   See http://firstsundaydoomsday.blogspot.com/2009/12/quick-start-guide.html
  24.     #   In the below, I mod by 7 after every step, but you can do this all at once at the very end if you'd
  25.     #   prefer.  An easy way to mod by 7 is to subtract multiples of 7.  7, 14, 21, 28, 35, 42, 49, 56,
  26.     #   and 63 are the useful multiples here.
  27.    
  28.     #============================================
  29.     #1. Calculate if is leapyear
  30.     is_leapyear = calculate_is_leapyear(year)
  31.  
  32.     #============================================
  33.     #2. Add offset due to year
  34.     T = year % 100 #last two digits of year
  35.     if T%2==1: #last two digits odd
  36.         T += 11
  37.     T //= 2 #"T" is even at this point.  Divide it by 2.
  38.     if T%2==1: #"T" is odd
  39.         T += 11 #or add 4, since about to mod
  40.     T %= 7
  41.  
  42.     #============================================
  43.     #3. Add century's first Sunday (CFS)
  44.     #   0     2    4    5
  45.     #--------------------
  46.     #  n/a  n/a 1500 1600
  47.     # 1700 1800 1900 2000
  48.     # 2100 2200 2300 etc.
  49.     #The delineation between Julian and Gregorian calendars is fuzzy based on location.  E.g. in Italy,
  50.     #   where the change from Julian to Gregorian was invented/mandated, it was 1582.  In
  51.     #   England/colonies, it was 1752.  Here's the whole gory thing: http://norbyhus.dk/calendar.php
  52.     is_gregorian = year >= 1582 #Italy-centric
  53.     if is_gregorian: #Newer, Gregorian calendar
  54.         if   year>=1500 and year<=1599: T+=4
  55.         elif year>=1600 and year<=1699: T+=5
  56.         elif year>=1700 and year<=1799: T+=0
  57.         elif year>=1800 and year<=1899: T+=2
  58.         elif year>=1900 and year<=1999: T+=4
  59.         elif year>=2000 and year<=2099: T+=5
  60.         elif year>=2100 and year<=2199: T+=0
  61.         elif year>=2200 and year<=2299: T+=2
  62.         elif year>=2300 and year<=2399: T+=4
  63.         else: assert False
  64.     else: #Older, Julian calendar
  65.         T += year // 100
  66.     T %= 7
  67.     #Note that you can memorize the values of "T" up to here for years you care about.  For example,
  68.     #   for 2015, "T" is 1.  Then, if you were given a date in 2015, you could just jump to here.
  69.  
  70.     #============================================
  71.     #4. Add Month's doomsday
  72.     #   If January, February, or March, use memorized values
  73.     #   Otherwise:
  74.     #       If even-numbered month, use month number
  75.     #       If odd-numbered month, use the unordered pairs (5,9) and (7,11) (that is, 5->9,9->5 and 7->11,11->7)
  76.     if   month ==  1: #January
  77.         if is_leapyear: T+=4
  78.         else:           T+=3
  79.     elif month ==  2: #February
  80.         if is_leapyear: T+=1
  81.         else:           T+=0
  82.     elif month ==  3: T+= 0 #March
  83.     elif month ==  4: T+= 4 #April
  84.     elif month ==  5: T+= 9 #May
  85.     elif month ==  6: T+= 6 #June
  86.     elif month ==  7: T+=11 #July
  87.     elif month ==  8: T+= 8 #August
  88.     elif month ==  9: T+= 5 #September
  89.     elif month == 10: T+=10 #October
  90.     elif month == 11: T+= 7 #November
  91.     elif month == 12: T+=12 #December
  92.     else: assert False
  93.     T %= 7
  94.  
  95.     #============================================
  96.     #5. Subtract total from day
  97.     T = day - T
  98.     T %= 7
  99.  
  100.     #============================================
  101.     #6. Done!  Convert T into weekday and output.
  102.     if T<0: T+=7
  103.     #              0        1         2          3           4         5         6
  104.     weekdays = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]
  105.  
  106.     #============================================
  107.     #Check answer using Zeller's Congruence (simpler, but harder to do mentally)
  108.     #   See https://en.wikipedia.org/wiki/Zeller%27s_congruence
  109.     m = month
  110.     y = year
  111.     if m<3:
  112.         #See http://stackoverflow.com/questions/16376684/is-there-formula-to-calculate-what-day-is-for-anyday-i-got-stuck-by-project-eul
  113.         m += 12
  114.         y -= 1
  115.     K = y % 100
  116.     J = y // 100
  117.     if is_gregorian:
  118.         h = (day + int(13.0*(m+1)/5.0) + K + int(K/4.0) + int(J/4.0) + 5*J) % 7
  119.     else:
  120.         h = (day + int(13.0*(m+1)/5.0) + K + int(K/4.0) + 5 + 6*J) % 7
  121.     d = (h+6) % 7
  122.     assert weekdays[T] == weekdays[d]
  123.  
  124.     #============================================
  125.     #Return
  126.     return weekdays[T]
  127. def output_weekday(year,month,day):
  128.     weekday = calculate_weekday(year,month,day)
  129.     print("Weekday for %04d-%02d-%02d: %s"%(year,month,day,weekday))
  130.  
  131. def test():
  132.     #Thursday
  133.     output_weekday(1776,7,4) #United States Independence Day
  134.  
  135.     #Wednesday
  136.     output_weekday(1895,5,1)
  137.  
  138.     #Saturday
  139.     output_weekday(1962,8,4)
  140.  
  141.     #Sunday
  142.     output_weekday(1941,12,7) #Pearl Harbor Day
  143.  
  144.     #Sunday
  145.     output_weekday(1899,12,31)
  146.  
  147.     #Monday
  148.     output_weekday(1900,1,1) #The next day
  149.  
  150.     #Saturday
  151.     output_weekday(1066,10,14) #Battle of Hastings (note Julian calendar)
  152.  
  153. def quiz():
  154.     while True:
  155.         year = random.randrange(1582,2399+1,1)
  156.         is_leapyear = calculate_is_leapyear(year)
  157.        
  158.         month = random.randrange(1,12+1,1)
  159.         if   month== 1: day=random.randrange(1,31+1,1)
  160.         elif month== 2:
  161.             if is_leapyear: day=random.randrange(1,28+1,1)
  162.             else:           day=random.randrange(1,29+1,1)
  163.         elif month== 3: day=random.randrange(1,31+1,1)
  164.         elif month== 4: day=random.randrange(1,30+1,1)
  165.         elif month== 5: day=random.randrange(1,31+1,1)
  166.         elif month== 6: day=random.randrange(1,30+1,1)
  167.         elif month== 7: day=random.randrange(1,31+1,1)
  168.         elif month== 8: day=random.randrange(1,31+1,1)
  169.         elif month== 9: day=random.randrange(1,30+1,1)
  170.         elif month==10: day=random.randrange(1,31+1,1)
  171.         elif month==11: day=random.randrange(1,30+1,1)
  172.         elif month==12: day=random.randrange(1,31+1,1)
  173.  
  174.         weekday = calculate_weekday(year,month,day)
  175.  
  176.         current_date = date.today()
  177.         if year==current_date.year and month==current_date.month and day==current_date.day:
  178.             s = "What day of the week is it today, "
  179.         elif year<current_date.year or (year==current_date.year and (month<current_date.month or (month==current_date.month and day<current_date.day))):
  180.             s = "What day of the week was it on "
  181.         else:
  182.             s = "What day of the week will it be on "
  183.         s += "%04d-%02d-%02d?  ENTER to get answer." % (year,month,day)
  184.         t0 = time.time()
  185.         input_func(s)
  186.         print("\tIt is/was a %s."%weekday)
  187.         t1 = time.time()
  188.         print("\t%f seconds"%(t1-t0))
  189.         print("")
  190. quiz()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement