Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

timesince.py 3.6KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import calendar
  2. import datetime
  3. from django.utils.html import avoid_wrapping
  4. from django.utils.timezone import is_aware
  5. from django.utils.translation import gettext, ngettext_lazy
  6. TIME_STRINGS = {
  7. "year": ngettext_lazy("%(num)d year", "%(num)d years", "num"),
  8. "month": ngettext_lazy("%(num)d month", "%(num)d months", "num"),
  9. "week": ngettext_lazy("%(num)d week", "%(num)d weeks", "num"),
  10. "day": ngettext_lazy("%(num)d day", "%(num)d days", "num"),
  11. "hour": ngettext_lazy("%(num)d hour", "%(num)d hours", "num"),
  12. "minute": ngettext_lazy("%(num)d minute", "%(num)d minutes", "num"),
  13. }
  14. TIMESINCE_CHUNKS = (
  15. (60 * 60 * 24 * 365, "year"),
  16. (60 * 60 * 24 * 30, "month"),
  17. (60 * 60 * 24 * 7, "week"),
  18. (60 * 60 * 24, "day"),
  19. (60 * 60, "hour"),
  20. (60, "minute"),
  21. )
  22. def timesince(d, now=None, reversed=False, time_strings=None, depth=2):
  23. """
  24. Take two datetime objects and return the time between d and now as a nicely
  25. formatted string, e.g. "10 minutes". If d occurs after now, return
  26. "0 minutes".
  27. Units used are years, months, weeks, days, hours, and minutes.
  28. Seconds and microseconds are ignored. Up to `depth` adjacent units will be
  29. displayed. For example, "2 weeks, 3 days" and "1 year, 3 months" are
  30. possible outputs, but "2 weeks, 3 hours" and "1 year, 5 days" are not.
  31. `time_strings` is an optional dict of strings to replace the default
  32. TIME_STRINGS dict.
  33. `depth` is an optional integer to control the number of adjacent time
  34. units returned.
  35. Adapted from
  36. https://web.archive.org/web/20060617175230/http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
  37. """
  38. if time_strings is None:
  39. time_strings = TIME_STRINGS
  40. if depth <= 0:
  41. raise ValueError("depth must be greater than 0.")
  42. # Convert datetime.date to datetime.datetime for comparison.
  43. if not isinstance(d, datetime.datetime):
  44. d = datetime.datetime(d.year, d.month, d.day)
  45. if now and not isinstance(now, datetime.datetime):
  46. now = datetime.datetime(now.year, now.month, now.day)
  47. now = now or datetime.datetime.now(datetime.timezone.utc if is_aware(d) else None)
  48. if reversed:
  49. d, now = now, d
  50. delta = now - d
  51. # Deal with leapyears by subtracing the number of leapdays
  52. leapdays = calendar.leapdays(d.year, now.year)
  53. if leapdays != 0:
  54. if calendar.isleap(d.year):
  55. leapdays -= 1
  56. elif calendar.isleap(now.year):
  57. leapdays += 1
  58. delta -= datetime.timedelta(leapdays)
  59. # ignore microseconds
  60. since = delta.days * 24 * 60 * 60 + delta.seconds
  61. if since <= 0:
  62. # d is in the future compared to now, stop processing.
  63. return avoid_wrapping(time_strings["minute"] % {"num": 0})
  64. for i, (seconds, name) in enumerate(TIMESINCE_CHUNKS):
  65. count = since // seconds
  66. if count != 0:
  67. break
  68. else:
  69. return avoid_wrapping(time_strings["minute"] % {"num": 0})
  70. result = []
  71. current_depth = 0
  72. while i < len(TIMESINCE_CHUNKS) and current_depth < depth:
  73. seconds, name = TIMESINCE_CHUNKS[i]
  74. count = since // seconds
  75. if count == 0:
  76. break
  77. result.append(avoid_wrapping(time_strings[name] % {"num": count}))
  78. since -= seconds * count
  79. current_depth += 1
  80. i += 1
  81. return gettext(", ").join(result)
  82. def timeuntil(d, now=None, time_strings=None, depth=2):
  83. """
  84. Like timesince, but return a string measuring the time until the given time.
  85. """
  86. return timesince(d, now, reversed=True, time_strings=time_strings, depth=depth)