Reputation: 21
I'm trying to create a function that returns a date in string format (MM-DD-YYYY) given the seconds since epoch. I believe the logic in my function is sound, and I'm posting here because there might be something about UNIX time that I don't understand. I'm looking for anyone who might shed some light on where my blind spot is. I believe my logic and thought process is correct, but clearly it's not. Hoping someone can help clear it up, and that this may be helpful for other newbies.
My function is passed an argument, seconds (int), that is the number of seconds since epoch. I then have to return a string 'MM-DD-YYYY'. Hours, minutes, seconds, and time-zone do not matter. I'm using Python, so int size and the 2038 problem should not matter either. My function calculates the date iteratively. I essentially keep decrementing the seconds parameter for years, then months, then days, tracking the time that has passed. Once I can no longer iterate in each of those three areas (years -> months -> days) I have found my date. Except that the date I find is incorrect.
I take the seconds parameter, and decrement it by the seconds in the given year, unless the decrement leads to a negative number. I track the years added as I decrement. If the year is a leap year, I decrement by 86400 * 366. For a common year, 86400 * 365. I add +1 to the year tracker each iteration.
The seconds parameter now contains the leftover number of seconds, which is less than the length of a year. I decrement the number of seconds in each month unless the decrement leads to a negative number. January = 86400 * 31, February is 28 or 29 days depending on if it's a leap year, and so on.
The seconds parameter now contains some number of seconds less than a month. I follow the same process, decrementing 86400 (and tracking the days) until I can't decrement seconds any longer.
Based on what I understand about UNIX time, I should arrive at the correct MM-DD-YYYY date using this method. However, my function is 2 days shy.
Input: 9876543210
Output: '12-20-2282'
Expected: '12-22-2282'
Input is always a positive integer
I do not need to do time-zone conversions or calculations. GMT assumed.
def date_from_epoch_seconds(seconds: int) -> str:
"""
Returns a date in string format ('MM-DD-YYYY') given param:seconds since epoch
:param: seconds: int, number of seconds since epoch
:return: string: date 'MM-DD-YYY'
"""
# variables
DAYS_IN_COMMON_MONTH = {1: 31, \
2: 28, \
3: 31, \
4: 30, \
5: 31, \
6: 30, \
7: 31, \
8: 31, \
9: 30, \
10: 31, \
11: 30, \
12: 31}
DAY = 86400
year = 1970
month = 1
day = 1
# calculate year
while True:
# get the number of seconds in this year
if year % 4 != 0:
add_year = DAY * 365
else:
add_year = DAY * 366
# exit criteria
if seconds - add_year < 0:
break
# add a year
seconds -= add_year
year += 1
print(f"Year calculated: {year}")
# calculate month
while True:
# get the number of seconds in this month
if month == 2 and year % 4 == 0:
add_month = DAY * 29
else:
add_month = DAY * DAYS_IN_COMMON_MONTH[month]
# exit criteria
if seconds - add_month < 0:
break
seconds -= add_month
month += 1
print(f"months calculated = {month}")
# calculate day
while True:
if seconds - DAY < 0:
break
seconds -= DAY
day += 1
print(f"day calculated = {day}")
print()
return str(twoDigitInt(month)) + "-" + \
str(twoDigitInt(day)) + "-" + \
str(year)
Upvotes: 0
Views: 134
Reputation: 433
Your leap year calculation is wrong. Years 2100 and 2200 are not leap years. Years divisible by 100 are not leap years unless they are also divisible by 400.
Upvotes: 1