If I were doing this, I'd create a templatetag that formats the datetime
object into the appropriate timezone. You could use, say, a context
processor or some consistent thing you call from your views to populate
the context with the user's timezone.
You could also use a filter for this, although the design has to be
slightly different. Filters are unaware of the template they're
rendering in, so they don't have access to the context. Therefore, you'd
have to pass the appropriate timezone (or an object containing the
timezone) to the filter as an argument.
So it's a choice between a couple of possibilities, at least:
(1) {% tz_convert obj as obj2 %}
Accepts "obj" (a date or datetime object), uses something in the
context to work out the timezone and then creates a new object
in the context ("obj2") that you can use later and which has the
right timezone value.
(2) {{ obj|tz_convert:tz }}
Converts a date or datetime object to an equivalent object in
the right timezone, the timezone being passed in via the "tz"
variable, in this case.
I can imagine either solution being more appropriate than the other in
different circumstances, so I'd just go for whichever approach seems
best, rather than worrying too much about whether there's a single best
answer here. There's no doubt other possibilities as well; the above
were the two I could come up with quickly that seem to hold up against a
few hypothetical usages I threw at them.
Regards,
Malcolm