I have a method that takes a datetime and returns what period of time this datetime belongs to, for example "yesterday" or "a month ago".
from datetime import datetime
difference = datetime.now() - basetime
days = difference.days
seconds = difference.seconds
hours = seconds / 3600
minutes = seconds / 60
if days and days == 1:
elif days and days != 1 and days < 7:
return '%s days ago' % days
elif days and days != 1 and 7 < days < 31:
return 'Within this month'
elif days and days != 1 and 30 < days < 365:
return '%s months ago' % (days / 30)
elif days and days != 1 and 365 <= days < 730:
return 'A year ago'
elif days and days != 1 and days >= 730:
return '%s years ago' % (days / 365)
elif hours and hours == 1:
return 'An hour ago'
elif hours and hours != 1:
return '%s hours ago' % hours
elif minutes and minutes == 1:
return 'A minute ago'
elif minutes and minutes != 1:
return '%s minutes ago' % minutes
elif seconds and seconds == 1:
return 'A second ago'
elif seconds and seconds != 1:
return '%s seconds ago' % seconds
return '0 second ago'
a_year_ago = datetime(2015, 5, 12, 23, 15, 15, 53000)
assert tell_time_ago(a_year_ago) == 'A year ago'
In general, I think it's a good idea to make your nontrivial functions and classes as close to mathematical functions (e.g.,
sin(x)), as possible. Given the same input, a mathematical function gives the same output each time, irrespective of the current date, random choices, and so forth.
If your function performs nontrivial logic dependent on the current date or time, pass the current date or time externally to it.
If your function performs random choices, pass it a pseudo-random number generator.
So, for example, instead of:
import datetime def foo(): ... now = datetime.datetime.now() ... foo()
import datetime def foo(now): ... ... foo(datetime.datetime.now())
This makes your nontrivial code consistent across multiple executions.
You can predictably test it.
If it fails in production, it is easier to reconstruct the problem.