I know the problem. In my programmer life I wrote more than one calendar application spreading multiple timezones. Anyway, I agree with all you write, except the stored timezone does not matter to be UTC and similar for all users. It best just reflects the intended timezone of the editor of the data. Then all computations for output can be done from there. UTC is also just a timezone, so it really does not matter. Thus, a second field is not needed. While creating plone.app.event we had this discussion in depth and in fact this was the conclusion. In between we had indeed an implementation with timezone stored separate, but it made all more difficult so we ditched it.
Now the killer argument: If it comes to recurring events you really need to store a date with the original editors timezone. Imagine a user in some US timezone schedules a daily event at 10am DST. Now it is converted to UTC. UTC has no DST. All calculations are done on the stored date, the information of the intended timezone is lost. Now, if in autumn we no no longer have DST or vice versa in spring, one day need to have 23 or 25 hours added for recurring dates. With UTC it is impossible to know when, the date of change in US is different from Europe or other parts in the world. Thus, timezone is essential information of a date. For the user the output date can be always calculated to reflect the its timezone, so weekly at 10am might mean mostly at 15pm for someone else, but at some weeks at 14pm. This can only be done at output rendering, never by unifying the input to an arbitrary timezone.