diff --git a/app/templates/main.html b/app/templates/main.html
index 51f513b8a87a1d8948b001232a1b349c08d4f95e..552babf43f278fff505ed164a73d099d59d30ef8 100644
--- a/app/templates/main.html
+++ b/app/templates/main.html
@@ -28,6 +28,14 @@
 		.meeting:hover {
 			background-color: #aaaaff;
 		}
+		.collision {
+			border: 1px solid red;
+			font-size: smaller;
+			background-color: #ffcccc;
+		}
+		.collision:hover {
+			background-color: #ffaaaa;
+		}
 
 	</style>
 </head>
@@ -60,7 +68,7 @@
 		<div class=hour style='position: absolute; left: {{ h.x }}px; top: {{ h.y }}px; width: {{ h.w }}px; height: {{ h.h }}px;'></div>
 {% endfor %}
 {% for m in g.meetings %}
-		<div class=meeting style='position: absolute; left: {{ m.x }}px; top: {{ m.y }}px; width: {{ m.w }}px; height: {{ m.h }}px;' title='{{ m.topic|e }}'>
+		<div class={{ "collision" if m.coll else "meeting" }} style='position: absolute; left: {{ m.x }}px; top: {{ m.y }}px; width: {{ m.w }}px; height: {{ m.h }}px;' title='{{ m.start + "–" + m.end + ": " + m.topic|e }}'>
 			{{ m.start }} – {{ m.end }}
 		</div>
 {% endfor %}
diff --git a/app/zoom.py b/app/zoom.py
index 2c471e01c46a1acd60d70a8dd790ca0cda9d1c8f..159769933ab54a275f87143f0f284c1f6eebd47f 100644
--- a/app/zoom.py
+++ b/app/zoom.py
@@ -3,7 +3,10 @@ from flask import Flask, render_template, request, g
 import psycopg2
 import psycopg2.extras
 import time
+from datetime import datetime
 import sys
+import dateutil
+import dateutil.tz
 
 ### Flask app object ###
 
@@ -42,11 +45,14 @@ def db_query(query, args=()):
 ### Schedule ###
 
 def get_date():
+    """Return a datetime object corresponding to the start of the given date."""
     try:
         d = request.args.get('date', "")
-        return time.strptime(d, "%Y-%m-%d")
+        dt = datetime.strptime(d, "%Y-%m-%d")
     except ValueError:
-        return time.localtime()
+        dt = datetime.today()
+    tz = dateutil.tz.tzlocal()
+    return dt.replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=tz)
 
 rooms = [
     ('Z1', 'zoom-1@d3s.mff.cuni.cz'),
@@ -62,11 +68,8 @@ rooms = [
 @app.route('/')
 def main_page():
     dt = get_date()
-    date = time.strftime("%Y-%m-%d", dt)
-    # FIXME: Broken time zones!!!
-    t = time.mktime(dt)
-    g.date = date
-    g.dow = time.strftime("%A", dt)
+    g.date = dt.strftime("%Y-%m-%d")
+    g.dow = dt.strftime("%A")
 
     hours_arg = request.args.get("hours", "")
     if hours_arg in ["0", "1"]:
@@ -107,23 +110,28 @@ def main_page():
             SELECT m.meeting_id, m.topic, m.start_time, m.duration, u.email, u.full_name
             FROM zoom_meetings m
             JOIN zoom_users u ON u.id = m.host_id
-            WHERE start_time >= DATE %s - INTERVAL '1 day'
-              AND start_time <  DATE %s + INTERVAL '1 day'
+            WHERE m.start_time >= DATE %s - INTERVAL '1 day'
+              AND m.start_time <  DATE %s + INTERVAL '1 day'
+            ORDER BY u.email, m.start_time
         """,
-        (date, date))
+        (dt, dt))
 
     g.meetings = []
+    prev_room_i = -1
+    prev_end_t = None
     for r in db.fetchall():
         i = email_to_room_index.get(r.email, -1)
         if i < 0:
             continue
-        start_t = int(r.start_time.timestamp())
+        # Datetime in the DB is in UTC, but psycopg2 interprets it as local time
+        start_dt = r.start_time.replace(tzinfo=dateutil.tz.tz.tzutc())
+        start_t = int(start_dt.timestamp())
         end_t = start_t + r.duration*60
-        rel_start = start_t - t - hour_min*3600
+        rel_start = start_t - dt.timestamp() - hour_min*3600
         rel_end = rel_start + r.duration*60
         start = max(0, int(rel_start))
         end = min(num_hours * 3600, int(rel_end))
-        app.logger.debug("Meeting: %s start=%s end=%s room_i=%s", r, start, end, i)
+        app.logger.debug("Meeting: %s start_t=%s start=%s end=%s room_i=%s", r, start_t, start, end, i)
         if start < end:
             g.meetings.append({
                 "x": i * room_box_width + 4,
@@ -133,6 +141,9 @@ def main_page():
                 "start": time.strftime("%H:%M", time.localtime(start_t)),
                 "end": time.strftime("%H:%M", time.localtime(end_t)),
                 "topic": r.topic,
+                "coll": (i == prev_room_i and start_t < prev_end_t),
             })
+            prev_room_i = i
+            prev_end_t = end_t
 
     return render_template('main.html')