CAT-SOOP is a flexible, programmable learning management system based on the Python programming language. https://catsoop.mit.edu
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.
 
 
 

162 lines
5.0 KiB

  1. # This file is part of CAT-SOOP
  2. # Copyright (c) 2011-2020 by The CAT-SOOP Developers <catsoop-dev@mit.edu>
  3. #
  4. # This program is free software: you can redistribute it and/or modify it under
  5. # the terms of the GNU Affero General Public License as published by the Free
  6. # Software Foundation, either version 3 of the License, or (at your option) any
  7. # later version.
  8. #
  9. # This program is distributed in the hope that it will be useful, but WITHOUT
  10. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  12. # details.
  13. #
  14. # You should have received a copy of the GNU Affero General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. """Utilities for dealing with time"""
  17. import time
  18. from datetime import datetime, timedelta, MAXYEAR
  19. _nodoc = {"datetime", "timedelta", "MAXYEAR"}
  20. days = ["M", "T", "W", "R", "F", "S", "U"]
  21. "List used for mapping weekday numbers to weekday letters"
  22. def realize_time(context, timestring):
  23. """
  24. Return an appropriate `datetime.datetime` object based on the given
  25. timestring.
  26. The timestring can have one of the following forms:
  27. * `'NEVER'`: resolves to the maximum date that `datetime` can represent
  28. * `'ALWAYS'`: resolves to the minimum date that `datetime can represent
  29. * `'YYYY-MM-DD:HH:MM'` resolves to a particular time (minute resolution)
  30. * `'W:HH:MM`, where `W` is a letter representing a day of the week,
  31. resolves to the given time in the week number given by `cs_week_number`,
  32. starting from `cs_first_monday`. For example, `'T:09:00'` represents
  33. Tuesday morning at 9 o'clock.
  34. **Parameters:**
  35. * `context`: the context associated with this request (from which
  36. `cs_first_monday` and `cs_week_number` are read)
  37. * `timestring`: a string representing the desired time (see above)
  38. **Returns:** a `datetime.datetime` object corresponding to the time given
  39. by `timestring`
  40. """
  41. if timestring == "NEVER":
  42. return datetime(year=MAXYEAR, month=12, day=31, hour=23, minute=59, second=59)
  43. elif timestring == "ALWAYS":
  44. return datetime(year=1900, month=1, day=1, hour=0, minute=0, second=0)
  45. elif timestring[0].isdigit():
  46. # absolute times are specified as strings 'YYYY-MM-DD:HH:MM'
  47. return datetime.strptime(timestring, "%Y-%m-%d:%H:%M")
  48. elif timestring[0].isalpha():
  49. # this is a day and a time
  50. day, hour, minute = timestring.split(":")
  51. while len(hour) > 1 and all(i == "0" for i in hour):
  52. hour = hour[1:]
  53. while len(minute) > 1 and all(i == "0" for i in minute):
  54. minute = minute[1:]
  55. start_date = context["cs_first_monday"]
  56. wknum = context["cs_week_number"]
  57. while len(day) > 1:
  58. if day[-1] == "+":
  59. wknum += 1
  60. elif day[-1] == "-":
  61. wknum -= 1
  62. day = day[:-1]
  63. start = realize_time(context, start_date)
  64. return start + timedelta(
  65. weeks=(wknum - 1),
  66. days=days.index(day),
  67. hours=int(hour),
  68. minutes=int(minute),
  69. )
  70. else:
  71. raise Exception("invalid time style: %s" % timestring)
  72. def unix(dt):
  73. """
  74. Generate a Unix timestamp from an instance of datetime.
  75. **Parameters:**
  76. * `dt`: an instance of `datetime.datetime`
  77. **Returns:** the Unix timestamp corresponding to the given time
  78. """
  79. return time.mktime(dt.timetuple())
  80. def now():
  81. """
  82. Wraps datetime.now.
  83. **Returns:** the current time, as an instance of `datetime.datetime`
  84. """
  85. return datetime.now()
  86. def long_timestamp(time):
  87. """
  88. Generate a (long) human-readable timestamp
  89. (e.g., `"Wednesday June 05, 2013; 02:58:21 PM"`)
  90. **Parameters:**
  91. * `time`: an instance of `datetime.datetime`
  92. **Returns:** a string containing a human-readable representation of the
  93. given time
  94. """
  95. return time.strftime("%A %B %d, %Y; %I:%M:%S %p")
  96. def short_timestamp(time):
  97. """
  98. Generate a (short) human-readable timestamp
  99. (e.g. `"Jun 05, 2013; 02:58 PM"`)
  100. **Parameters:**
  101. * `time`: an instance of `datetime.datetime`
  102. **Returns:** a string containing a human-readable representation of the
  103. given time
  104. """
  105. return time.strftime("%b %d, %Y; %I:%M %p")
  106. def detailed_timestamp(time=None):
  107. """
  108. Generate a detailed timestamp.
  109. (e.g. `"2013-06-05:14:58:21.024717"`)
  110. **Parameters:**
  111. * `time`: an instance of `datetime.datetime`
  112. **Returns:** a string containing a representation of the given time
  113. """
  114. return time.strftime("%Y-%m-%d:%H:%M:%S.%f")
  115. def from_detailed_timestamp(time):
  116. """
  117. Generate an instance of datetime from a detailed timestamp.
  118. **Parameters:**
  119. * `time`: a string of the same form as the output from
  120. `catsoop.time.detailed_timestamp`
  121. **Returns:** a `datetime.datetime` instance representing the given time
  122. """
  123. return datetime.strptime(time, "%Y-%m-%d:%H:%M:%S.%f")