Created
September 12, 2022 01:31
-
-
Save Kelketek/dbfeb4568b5806fe0eabe5129211f09b to your computer and use it in GitHub Desktop.
Example game datetime functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import Literal, Dict | |
# Our lowest resolution is in hours. | |
HOUR_LENGTH = 1 | |
DAY_LENGTH = 24 | |
SEASON_LENGTH = DAY_LENGTH * 30 | |
YEAR_LENGTH = SEASON_LENGTH * 4 | |
TimeKey = Literal['year', 'season', 'day', 'hour'] | |
# Could use a DataClass or a TypedDict, but that would be distracting to the point I'm trying to show | |
# which is how the math works and how this approach handles edge cases. | |
DateDict = Dict[TimeKey, int] | |
def time_delta(*, hours: int = 0, days: int = 0, seasons: int = 0, years: int = 0) -> int: | |
""" | |
Return a value that represents the number of hours for however many hours, days, seasons, and years | |
forward we wish to travel. | |
""" | |
return sum([ | |
hours, | |
days * DAY_LENGTH, | |
seasons * SEASON_LENGTH, | |
years * YEAR_LENGTH, | |
]) | |
def break_down_time(time_value: int) -> DateDict: | |
""" | |
Break time down into a dict of integer values. | |
""" | |
resolved: Dict[TimeKey, int] = {} | |
remainder = time_value | |
key: TimeKey | |
for key, divisor in [('year', YEAR_LENGTH), ('season', SEASON_LENGTH), ('day', DAY_LENGTH)]: | |
resolved[key] = (remainder // divisor) + 1 # The date begins at year 1, Not year 0. | |
remainder = remainder % divisor | |
resolved['hour'] = remainder | |
return resolved | |
def date_dict_to_string(date_dict: DateDict) -> str: | |
""" | |
Given a current time value, return the resolved datetime. | |
""" | |
# We can remove this if we decide to do military time. | |
post_time_marker = 'AM' | |
hours = date_dict['hour'] | |
if hours > 12: | |
post_time_marker = 'PM' | |
hours -= 12 | |
if hours == 0: | |
# Midnight. | |
hours = 12 | |
return f'Year {date_dict["year"]}, Season {date_dict["season"]}, Day {date_dict["day"]}, {hours} {post_time_marker}' | |
def timestamp_to_string(timestamp: int) -> str: | |
"""Given an integer timestamp, return the display string.""" | |
return date_dict_to_string(break_down_time(timestamp)) | |
if __name__ == '__main__': | |
current_time = 0 | |
print(timestamp_to_string(current_time)) | |
current_time += time_delta(hours=5, days=3, seasons=0, years=1) | |
print(timestamp_to_string(current_time)) | |
current_time += time_delta(seasons=5) | |
print(timestamp_to_string(current_time)) | |
current_time += time_delta(days=45, hours=12) | |
print(timestamp_to_string(current_time)) | |
arbitrary_date = {'year': 1, 'season': 2, 'day': 5, 'hour': 3} | |
print(date_dict_to_string({'hour': 3, 'day': 5, 'year': 1, 'season': 2})) | |
# Turning a date dict back into an int is an exercise left to the reader, but time_delta is 90% of the way there | |
# already. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment