How to calculate when one's 10000 day after his or her birthday will be

Viewed 2346

I am wondering how to solve this problem with basic Python (no libraries to be used): How can I calculate when one's 10000 day after their birthday will be (/would be)?

For instance, given Monday 19/05/2008, the desired day is Friday 05/10/2035 (according to https://www.durrans.com/projects/calc/10000/index.html?dob=19%2F5%2F2008&e=mc2)

So far I have done the following script:

years = range(2000, 2050)
lst_days = []
count = 0
tot_days = 0
for year in years:
    if((year % 400 == 0) or  (year % 100 != 0) and  (year % 4 == 0)):
        lst_days.append(366)
    else:
        lst_days.append(365)
while tot_days <= 10000:
        tot_days = tot_days + lst_days[count]
        count = count+1
print(count)

Which estimates the person's age after 10,000 days from their birthday (for people born after 2000). But how can I proceed?

4 Answers

Using base Python packages only

On the basis that "no special packages" means you can only use base Python packages, you can use datetime.timedelta for this type of problem:

import datetime

start_date = datetime.datetime(year=2008, month=5, day=19)

end_date = start_date + datetime.timedelta(days=10000)

print(end_date.date())

Without any base packages (and progressing to the problem)

Side-stepping even base Python packages, and taking the problem forwards, something along the lines of the following should help (I hope!).

Start by defining a function that determines if a year is a leap year or not:

def is_it_a_leap_year(year) -> bool:
    """
    Determine if a year is a leap year

    Args:
        year: int

    Extended Summary:
        According to:
            https://airandspace.si.edu/stories/editorial/science-leap-year
        The rule is that if the year is divisible by 100 and not divisible by
        400, leap year is skipped. The year 2000 was a leap year, for example,
        but the years 1700, 1800, and 1900 were not.  The next time a leap year
        will be skipped is the year 2100.
    """
    if year % 4 != 0:

        return False

    if year % 100 == 0 and year % 400 != 0:

        return False

    return True

Then define a function that determines the age of a person (utilizing the above to recognise leap years):

def age_after_n_days(start_year: int,
                     start_month: int,
                     start_day: int,
                     n_days: int) -> tuple:
    """
    Calculate an approximate age of a person after a given number of days,
    attempting to take into account leap years appropriately.

    Return the number of days left until their next birthday

    Args:
        start_year (int): year of the start date
        start_month (int): month of the start date
        start_day (int): day of the start date
        n_days (int): number of days to elapse
    """

    # Check if the start date happens on a leap year and occurs before the
    # 29 February (additional leap year day)
    start_pre_leap = (is_it_a_leap_year(start_year) and start_month < 3)

    # Account for the edge case where you start exactly on the 29 February
    if start_month == 2 and start_day == 29:

        start_pre_leap = False

    # Keep a running counter of age
    age = 0

    # Store the "current year" whilst iterating through the days
    current_year = start_year

    # Count the number of days left
    days_left = n_days

    # While there is at least one year left to elapse...
    while days_left > 364:

        # Is it a leap year?
        if is_it_a_leap_year(current_year):

            # If not the first year
            if age > 0:

                days_left -= 366

            # If the first year is a leap year but starting after the 29 Feb...
            elif age == 0 and not start_pre_leap:

                days_left -= 365

            else:

                days_left -= 366

        # If not a leap year...
        else:

            days_left -= 365

        # If the number of days left hasn't dropped below zero
        if days_left >= 0:

            # Increment age
            age += 1

            # Increment year
            current_year += 1

    return age, days_left

Using your example, you can test the function with:

age, remaining_days = age_after_n_days(start_year=2000, start_month=5, start_day=19, n_days=10000)

Now you have the number of complete years that will elapse and the number of remaining days

You can then use the remaining_days to work out the exact date.

If you import library datetime

import datetime
your_date = "01/05/2000"
(day, month, years) = your_date.split("/")
date = datetime.date(int(years), int(month), int(day))
date_10000 = date+datetime.timedelta(days=10000)
print(date_10000)

No library script

your_date = "20/05/2000"
(day, month, year) = your_date.split("/")
days = 10000
year = int(year)
month = int(month)
day = int(day)
end=False
#m1,m3,m5,m7,m8,m10,m12=31
#m2=28
#m4,m6,m9,m11=30
m=[31,28,31,30,31,30,31,31,30,31,30,31]
while end!=True:
    if(((year % 400 == 0) or  (year % 100 != 0) and  (year % 4 == 0)) and(days-366>=0)):   
        days-=366
        year+=1
    elif(((year % 400 != 0) or  (year % 100 != 0) and  (year % 4 != 0)) and(days-366>=0)):
        days-=365
        year+=1
    else:
        end=True
end=False
if(((year % 400 == 0) or  (year % 100 != 0) and  (year % 4 == 0))):   
    m[1]=29
else:
    m[1]=28
while end!=True:
    if(days-m[month]>=0):
        days-=m[month]
        if(month+1!=12):
            month+=1
        else:
            year+=1
            if(((year % 400 == 0) or  (year % 100 != 0) and  (year % 4 == 0))):   
                m[1]=29
            else:
                m[1]=28
            month=0
    else:
        end=True

if(day+days>m[month]):
    day=day+days-m[month]+1
    if(month+1!=12):
        month+=1
    else:
        year+=1
        if(((year % 400 == 0) or  (year % 100 != 0) and  (year % 4 == 0))):   
            m[1]=29
        else:
            m[1]=28
        month=0
else:
    day=day+days
print(day,"/",month,"/",year)

Here's a solution I came up with that involves no libraries or packages, just loops and conditionals (accounts for leap years):

def isLeapYear(years):
  if years % 4 == 0:
    if years % 100 == 0:
      if years % 400 == 0:
        return True
      else:
        return False
    else:
      return True
  else:
    return False

monthDays = [31,28,31,30,31,30,31,31,30,31,30,31]
sum = 0
sumDays = []
for i in monthDays:
  sumDays.append(365 - sum)
  sum += i

timeInp = input("Please enter your birthdate in the format dd/mm/yyyy\n")
timeInp = timeInp.split("/")
days = int(timeInp[0])
months = int(timeInp[1])
years = int(timeInp[2])
totDays = 10000

if totDays > 366:
  if isLeapYear(years):
    if months == 1 or months == 2:
      totDays -= (sumDays[months - 1] + 1 - days) + 1
    else:
      totDays -= (sumDays[months - 1] - days) + 1
  else:
    totDays -= (sumDays[months - 1] - days) + 1

  months = 1
  days = 1
  years += 1

while totDays > 366:
  if isLeapYear(years):
    totDays -= 366
  else:
    totDays -= 365
  years += 1

i = 0
while totDays != 0:
  if isLeapYear(years):
    monthDays[1] = 29
  else:
    monthDays[1] = 28

  if totDays >= monthDays[i]:
    months += 1
    totDays -= monthDays[i]
  elif totDays == monthDays[i]:
    months += 1
    totDays = 0
  else:
    days += totDays
    if days % (monthDays[i] + 1)!= days:
      days %= monthDays[i] + 1
      months += 1
    totDays = 0

  if months == 13:
    months = 1
    years += 1

  i += 1
  if i == 12:
    i = 0

print(str(days) + "/" + str(months) + "/" + str(years))

As the name suggests, isLeapYear() takes in a parameter years, and returns a boolean value.

Our first step to this problem, to make it easier, is to just first "translate" our date to the next year. This makes our future calculations easier. To do this, we can define an array sumDays that stores the amount of days each month takes to finish the year (go to new years). Then, we subtract this amount from totDays, account for leap years, and update our variables.

Next, is the easy part, just skipping forward by the years while we have enough days for a complete year.

Once we can not add another full year, we just go month by month until we run out of days.

Sample Test Cases:

Input #1:

19/05/2008

Output #1:

5/10/2035

Input #2:

05/05/2020

Output #2:

21/9/2047

Input #3:

29/02/2020

Output #3:

17/7/2047

I checked most of my solutions with this website: https://www.countcalculate.com/calendar/birthday-in-days/result

I have updated my code for the leap year and month dates. Here is the code that I'm using:

n = input("Enter your DOB:(dd/mm/yyyy)")
d,m,y = n.split('/') #Splitting the DOB
d,m,y = int(d), int(m), int(y)
def if_leap(year): # Checking for leap year.
    if year % 4 != 0:
        return False
    elif year % 100 == 0 and year % 400 != 0:
        return False
    else:
        return True


target = 10000
while target > 364: # getting no.of years
    if if_leap(y):
        target -= 366
        y += 1
    else:
        target -= 365
        y += 1

while target > 27: # getting no. of months
    if m == 2 :
        if if_leap(y):
            target -= 29
            m += 1
            if m >= 12: # Resetting the month to 1 if it's value is greater than 12
                y += 1
                m -= 12
        else:
            target -= 28
            m += 1
            if m >= 12:
                y += 1
                m -= 12
    elif m in [1, 3, 5, 7, 8, 10, 12]:
        target -= 31
        m += 1
        if m >= 12:
            y += 1
            m -= 12
    elif m in [4, 6, 9, 11]:
        target -= 30
        m += 1
        if m >= 12:
            y += 1
            m -= 12
            
d = d + target # getting the no. of days
if d > 27:
    if m == 2:
        if if_leap(y):
            d -= 29
            m += 1
        else:
            d -= 28
            m += 1
    elif m in [1, 3, 5, 7, 8, 10, 12]:
        d -= 31
        m += 1
    else:
        d -= 30
        m += 1

print(f"The 10000th date will be {d}/{m}/{y}") 

Output:

Enter your DOB:(dd/mm/yyyy): 06/01/2006
The 10000th date will be 24/5/2033

P.S: I am getting some slightly different outputs when checking with that website. Can anyone figure out the bug/mistake in the code? It'll be really helpful. For eg. for the date 08/12/2004, it should be 25/4/2032 but my output is showing 24/4/2032.

Related