title: Day of the week finder
body: <p>I was working on <a href="https://projecteuler.net/problem=19" rel="nofollow noreferrer">Project Euler problem 19</a> and my initial approach at the problem involved finding a function that would just tell me the day of the week given a date in the form yyy-mm-dd by generating the number of days that had passed since 1900-01-01 (which we are told is a Monday).</p>
  
  <p>I later wrote a loop that would consider the 1st day of every month in the range 1901-01-01 and 2000-12-31 and count the number of Sundays.</p>
  
  <p>As with some of the other project Euler problems, it is quite hard to resist playing around with it and trying to produce a couple of other results. The code that I have before correctly tells me the result for the number of Sundays in the given range but I also asked it to tell me (a) the number of occurences of any given day in the given range (both specified by the user) and (b) the day of the week for the first of each month in the year 2000. I think part (a) seems to work correctly also but looking at the result of part (b), all of these days are off by a single day from what the year 2000 calendar actually was. Playing around with other years, there seem to be similar discrepencies appearing. </p>
  
  <p>Whilst I have solved what the question asks me, this is annoying me greatly and I can't happily move on to the next problem before I figure out what I did wrong here! Can anyone help me? Thanks!</p>
  
  <p>My code is below (I'm fairly new to Python so it's probably very far from optimal but it runs in 1 or 2 seconds so I'm not too upset!)</p>
  
  <pre><code>import time
  
  date = input("Enter a date after 1900-01-01 in the form yyyy-mm-dd: ")
  which_day = input("Which day of the week would you like to count? ")
  
  start_time = time.time() #Start the clock after the input
  
  date_year = date[0:4]
  date_month = date[5:7]
  date_day = date[8:10]
  
  def day_difference_month(date_month): #Find the number of days accumulated until we reach the month in question
      if date_month=='01':
          return 0
      elif date_month=='02':
          return 31
      elif date_month=='03':
          return 59
      elif date_month=='04':
          return 90
      elif date_month=='05':
          return 120
      elif date_month=='06':
          return 151
      elif date_month=='07':
          return 181
      elif date_month=='08':
          return 212
      elif date_month=='09':
          return 243
      elif date_month=='10':
          return 273
      elif date_month=='11':
          return 304
      elif date_month=='12':
          return 334
  
  day_difference_day = int(date_day)  #Find the number of days accumulated between first of month and day in question
  
  def day_difference_year(date_year): #Find the number of days accumulated between 1900 and the year in question
      days = abs(int(date_year) - 1900)*365
      return days
  
  def leap_days(date_year,x,date_month):
      total=0
      total =  (x // 1460) - (x // 36500) + (x // 146000) #This takes account of leap years. We find the floor wrt 1460 days (4 year period) and thus add a day for each 4 year period. We subtract a day for each 100 year period e.g. in 100th year no day is added since we get +1 from mod 4 and -1 from mod 100. We then add a third contribution for mod 400 meaning a leap year takes place in this situation.
      if (int(date_month)==1 or int(date_month)==2) and (int(date_year) % 100 != 0 or int(date_year) % 400 == 0): #This accounts for the fact that the extra day won't contribute until March or later so we better not add yet it if the date in question is January or February
          total -=1
      return total
  
  total_days = leap_days(date_year,day_difference_year(date_year),date_month) + day_difference_year(date_year) + day_difference_month(date_month) + day_difference_day
  
  def day_finder(total_days):
      if total_days % 7 == 1:
          return 'Monday'
      elif total_days % 7 == 2:
          return 'Tuesday'
      elif total_days % 7 == 3:
          return 'Wednesday'
      elif total_days % 7 == 4:
          return 'Thursday'
      elif total_days % 7 == 5:
          return 'Friday'
      elif total_days % 7 == 6:
          return 'Saturday'
      elif total_days % 7 == 0:
          return 'Sunday'
  
  def no_particular_day(which_day,total_days):
      if which_day == 'Monday':
          if total_days &gt;6 and total_days %7 ==0: #if the end day is same as day we're counting, we add the number of weeks (total_days //7) + 1 (initial day)
              return total_days // 7 + 1
          elif total_days &gt;7: #if end day is different to day we are counting we simply count the number of weeks
              return total_days // 7
          else:
              return 1 #if end date is within one week of start date then we count 1 for 1900-01-01
      elif which_day == 'Tuesday':
          if total_days &gt;7 and total_days %7 ==1: #logic same as above - we need total_days %7 ==1 for end date to be Tuesday
              return total_days // 7 + 1
          elif total_days &gt;7:
              return total_days //7
          elif total_days &gt;0: #if we're within one week of the start date and more than one day has passed, then we count 1 Tuesday (first day was a Monday)
              return 1
          else:
              return 0 #if less than one day has passed i.e. zero days then we are stuck on zero Tuesdays
      elif which_day == 'Wednesday':
          if total_days &gt;8 and total_days %7 ==2:
              return total_days // 7 + 1
          elif total_days &gt;7:
              return total_days // 7
          elif total_days &gt;1:
              return 1
          else:
              return 0
      elif which_day == 'Thursday':
          if total_days &gt;9 and total_days %7 ==3:
              return total_days // 7 + 1
          elif total_days &gt;7:
              return total_days // 7
          elif total_days &gt;2:
              return 1
          else:
              return 0
      elif which_day == 'Friday':
          if total_days &gt;10 and total_days %7 ==4:
              return total_days // 7 + 1
          elif total_days &gt;7:
              return total_days // 7
          elif total_days &gt;3:
              return 1
          else:
              return 0
      elif which_day == 'Saturday':
          if total_days &gt;11 and total_days %7 ==5:
              return total_days // 7 + 1
          elif total_days &gt;7:
              return total_days // 7
          elif total_days &gt;4:
              return 1
          else:
              return 0
      elif which_day == 'Sunday':
          if total_days &gt;12 and total_days %7 ==6:
              return total_days // 7 + 1
          elif total_days &gt;7:
              return total_days //7
          elif total_days &gt;5:
              return 1
          else:
              return 0
  
  
  def sunday_counter_from_1900(date_year):
      increment = 0
      for i in range(1900,int(date_year)+1):
          string_year=str(i)
          for month in ['01','02','03','04','05','06','07','08','09','10','11','12']:
              day_count = day_difference_year(string_year) + day_difference_month(month) + 1 #we're considering 1st of each month so day_difference(date_day)=1 always)
              if day_count %7 ==0:
                  increment +=1
      return increment
  
  def sunday_counter_1900_to_1901():
      increment = 0
      string_year=str(1900)
      for month in ['01','02','03','04','05','06','07','08','09','10','11','12']:
          day_count = day_difference_year(string_year) + day_difference_month(month)  +1 #we're considering 1st of each month so day_difference(date_day)=1 always)
          if day_count %7 ==0:
              increment +=1
      return increment
  
  def sunday_counter_from_1901(date_year):
      x= sunday_counter_from_1900(date_year) - sunday_counter_1900_to_1901()
      return x
  
  for month in ['01','02','03','04','05','06','07','08','09','10','11','12']:
      print(day_finder(leap_days(2000,day_difference_year(2000),month)+day_difference_year(2000)+day_difference_month(month)+1))            
  print("%s was a %s." %(date,day_finder(total_days)))
  if int(date_year) &gt;= 1900:
      print("There were %s %s between 1900-01-01 and %s." %(no_particular_day(which_day,total_days),which_day+'s',date))
  else:
      print("You entered a date in the past of the start date. This formula only counts day occurences for end dates in the future. Try again please.")    
  print("Between 1901-01-01 and the end of the year %s, there were %s months with a Sunday falling on the first day." %(date_year, sunday_counter_from_1901(date_year)))
  print("Runtime: %.2f seconds" % (time.time() - start_time))
  </code></pre>
  
  <p>And the output that I get is:</p>
  
  <pre><code>Enter a date after 1900-01-01 in the form yyyy-mm-dd: 2000-12-31
  
  Which day of the week would you like to count? Sunday
  
  Friday
  
  Monday
  
  Tuesday
  
  Friday
  
  Sunday
  
  Wednesday
  
  Friday
  
  Monday
  
  Thursday
  
  Saturday
  
  Tuesday
  
  Thursday
  
  2000-12-31 was a Saturday.
  
  There were 5270 Sundays between 1900-01-01 and 2000-12-31.
  
  Between 1901-01-01 and the end of the year 2000, there were 171 months with a Sunday falling on the first day.
  
  Runtime: 0.07 seconds
  </code></pre>