This pull request completely revamps date and time handling in both the backend and frontend to adhere to industry best practices and fix time errors. The most important changes involve storing dates in the database in UTC for consistency, using the dateutil library for smarter parsing, and updating the event display logic in the templates.
The material referenced to create this pull request was challenging to find and apply, so a summary of the most important ideas are listed below for future reference of @TairanJ, @liamjdavis, @DhyeyMavani2003
Important ideas in datetime handling in for Django projects:
Always store data in UTC form in the database: This best practice should be followed even if the website is only available in one time zone because of daylight saving time; if date times are stored in local time, errors are likely to occur twice a year during the transitions to and from daylight saving time. Storing data in UTC also makes support for more timezones in the future easier.
Use timezone.activate(timezone) to handle timezones for rendering: When timezone.activate(timezone) (documentation here) is called in views that display time information, where timezone is a pytz timezone object, Django sets the local time to timezone. Then, in the templates corresponding to the views, adding {% load tz %} followed by {{ datetime|localtime }}, where localtime is a keyword, automatically converts datetime to the correct timezone and displays it. For more information on this see this. One special note is that calling timezone.activate()does not change the behavior of timezone.now(), which still returns the current time in the project default timezone.
Use dateutil.parser.parse for parsing: In contrast to our previous method, dateutil.parser.parse seems to be much better for datetime parsing as we only need to pass in the datetime string and it will handle everything else (no need to specify format, worry about timezone handling, etc.)
.astimezone(timezone) is your friend: Since all datetimes are stored in UTC and timezone.now() returns UTC (project default) but all user-facing logic must be in the local time zone (e.g., to get the appropriate default date range for the date selector on the home page, we needed to get the current date in the local timezone and increment by seven days), we need to call .astimezone(timezone) frequently to change from the current time zone (UTC or local) to the desired timezone (local or UTC)
Convert dates and times into full datetime objects before changing their timezones: We cannot directly change the timezones of "incomplete" datetimes (e.g., we only have the hour), so we want to create a full datetime object by combining information from the incomplete datetime and filler values (e.g., start_time = datetime( start_time.year, start_time.month, start_time.day, 0, 0, 0, tzinfo=pytz.timezone("America/New_York") )), convert the object to the correct time zone, and then get the field we're interested in (e.g., hour) from the object.
This pull request completely revamps date and time handling in both the backend and frontend to adhere to industry best practices and fix time errors. The most important changes involve storing dates in the database in UTC for consistency, using the
dateutil
library for smarter parsing, and updating the event display logic in the templates.Date and Time Handling Improvements:
access_amherst_backend/access_amherst_algo/generate_map.py
: Added conversion of user-specified hours to UTC for database queries in thegenerate_heatmap
function.access_amherst_backend/access_amherst_algo/management/commands/remove_old_events.py
: Converted the threshold time to UTC before querying old events.access_amherst_backend/access_amherst_algo/rss_scraper/parse_rss.py
: Replaced manual date parsing and timezone conversion with thedateutil
parser to ensure all dates are stored in UTC. [1] [2]User Interface Enhancements:
access_amherst_backend/access_amherst_algo/templates/access_amherst_algo/home.html
: Loaded thetz
template tag and applied thelocaltime
filter to display event times in the local timezone.access_amherst_backend/access_amherst_algo/views.py
: Activated the EST timezone and converted user-provided dates to UTC for database queries in thehome
andcalendar_view
functions. [1] [2]The material referenced to create this pull request was challenging to find and apply, so a summary of the most important ideas are listed below for future reference of @TairanJ, @liamjdavis, @DhyeyMavani2003
Important ideas in datetime handling in for Django projects:
timezone.activate(timezone)
to handle timezones for rendering: Whentimezone.activate(timezone)
(documentation here) is called in views that display time information, where timezone is a pytz timezone object, Django sets the local time to timezone. Then, in the templates corresponding to the views, adding{% load tz %}
followed by{{ datetime|localtime }}
, where localtime is a keyword, automatically converts datetime to the correct timezone and displays it. For more information on this see this. One special note is that callingtimezone.activate()
does not change the behavior of timezone.now(), which still returns the current time in the project default timezone.dateutil.parser.parse
for parsing: In contrast to our previous method,dateutil.parser.parse
seems to be much better for datetime parsing as we only need to pass in the datetime string and it will handle everything else (no need to specify format, worry about timezone handling, etc.)start_time = datetime( start_time.year, start_time.month, start_time.day, 0, 0, 0, tzinfo=pytz.timezone("America/New_York") )
), convert the object to the correct time zone, and then get the field we're interested in (e.g., hour) from the object.