0001"""Date/Time Helpers"""
0002
0003
0004
0005
0006from datetime import datetime
0007import time
0008
0009DEFAULT_PREFIX = 'date'
0010
0011def distance_of_time_in_words(from_time, to_time=0, include_seconds=False):
0012 """
0013 Reports the approximate distance in time between two datetime objects or
0014 integers as seconds.
0015
0016 Set ``include_seconds`` to True for more more detailed approximations when
0017 distance < 1 min, 29 secs
0018
0019 Distances are reported based on the following table:
0020
0021 0 <-> 29 secs => less than a minute
0022 30 secs <-> 1 min, 29 secs => 1 minute
0023 1 min, 30 secs <-> 44 mins, 29 secs => [2..44] minutes
0024 44 mins, 30 secs <-> 89 mins, 29 secs => about 1 hour
0025 89 mins, 29 secs <-> 23 hrs, 59 mins, 29 secs => about [2..24] hours
0026 23 hrs, 59 mins, 29 secs <-> 47 hrs, 59 mins, 29 secs => 1 day
0027 47 hrs, 59 mins, 29 secs <-> 29 days, 23 hrs, 59 mins, 29 secs => [2..29] days
0028 29 days, 23 hrs, 59 mins, 30 secs <-> 59 days, 23 hrs, 59 mins, 29 secs => about 1 month
0029 59 days, 23 hrs, 59 mins, 30 secs <-> 1 yr minus 31 secs => [2..12] months
0030 1 yr minus 30 secs <-> 2 yrs minus 31 secs => about 1 year
0031 2 yrs minus 30 secs <-> max time or date => over [2..X] years
0032
0033 With ``include_seconds`` set to True and the difference < 1 minute 29
0034 seconds:
0035
0036 0-4 secs => less than 5 seconds
0037 5-9 secs => less than 10 seconds
0038 10-19 secs => less than 20 seconds
0039 20-39 secs => half a minute
0040 40-59 secs => less than a minute
0041 60-89 secs => 1 minute
0042
0043 Examples:
0044
0045 >>> from datetime import datetime, timedelta
0046 >>> from_time = datetime.now()
0047 >>> distance_of_time_in_words(from_time, from_time + timedelta(minutes=50))
0048 'about 1 hour'
0049 >>> distance_of_time_in_words(from_time, from_time + timedelta(seconds=15))
0050 'less than a minute'
0051 >>> distance_of_time_in_words(from_time, from_time + timedelta(seconds=15), include_seconds=True)
0052 'less than 20 seconds'
0053
0054 Note: ``distance_of_time_in_words`` calculates one year as 365.25 days.
0055 """
0056 if isinstance(from_time, int):
0057 from_time = time.time()+from_time
0058 else:
0059 from_time = time.mktime(from_time.timetuple())
0060 if isinstance(to_time, int):
0061 to_time = time.time()+to_time
0062 else:
0063 to_time = time.mktime(to_time.timetuple())
0064
0065 distance_in_minutes = int(round(abs(to_time-from_time)/60))
0066 distance_in_seconds = int(round(abs(to_time-from_time)))
0067
0068 if distance_in_minutes <= 1:
0069 if include_seconds:
0070 for remainder in [5, 10, 20]:
0071 if distance_in_seconds < remainder:
0072 return "less than %s seconds" % remainder
0073 if distance_in_seconds < 40:
0074 return "half a minute"
0075 elif distance_in_seconds < 60:
0076 return "less than a minute"
0077 else:
0078 return "1 minute"
0079 else:
0080 if distance_in_minutes == 0:
0081 return "less than a minute"
0082 else:
0083 return "1 minute"
0084 elif distance_in_minutes < 45:
0085 return "%s minutes" % distance_in_minutes
0086 elif distance_in_minutes < 90:
0087 return "about 1 hour"
0088 elif distance_in_minutes < 1440:
0089 return "about %d hours" % (round(distance_in_minutes / 60.0))
0090 elif distance_in_minutes < 2880:
0091 return "1 day"
0092 elif distance_in_minutes < 43220:
0093 return "%d days" % (round(distance_in_minutes / 1440))
0094 elif distance_in_minutes < 86400:
0095 return "about 1 month"
0096 elif distance_in_minutes < 525600:
0097 return "%d months" % (round(distance_in_minutes / 43200))
0098 elif distance_in_minutes < 1051200:
0099 return "about 1 year"
0100 else:
0101 return "over %d years" % (round(distance_in_minutes / 525600))
0102
0103def time_ago_in_words(from_time, include_seconds=False):
0104 """
0105 Like distance_of_time_in_words, but where ``to_time`` is fixed to ``datetime.now()``.
0106 """
0107 return distance_of_time_in_words(from_time, datetime.now(), include_seconds)
0108
0109__all__ = ['distance_of_time_in_words', 'time_ago_in_words']