I think you're on the right track with using the built in TimeZoneInfo class. The ID should never change, but the name will (I learned that lesson the hard way when several changed between xp and vista). I have used a virtually identical approach (UTC only at the service and db layers, local time on the web server & client) and it worked just fine.
One thing I suggest is to wrap the various TimeZoneInfo methods you intend to use with an interface ITimeZoneConverter
or something of that nature, that way if you need to change your implementation later, it should be easier to do.
Random Annoyance: The .Net TimeZoneInfo class can't give you an abbreviation given a timezone. IE: No "EST" for "Eastern Standard Time", so if you need that, plan on having a lookup into some sort of resource file or table for that.
Javascript won't actually be able to tell you the timezone, just the timezone offset from UTC. It's a subtle difference, and in your case it sounds like it won't matter, but it's something to keep in mind when looking at what timezones get assigned to your users.
I have seen some JS libraries such as this one which attempt to guess the timezone on the client side based on offset and most populated timezones. It is an interesting approach, but I don't know how well it would work in production.
Finally, one thing that bit me in the past was that JSON doesn't actually specify anything about how to format datetimes. (related reading) If you're doing a lot of ajax/async requests and intend to convert back and forth between utc & local times, this can be painful. Make sure you write some good common parsing/offsetting functions and make sure everyone on your team is aware of them and doesn't re-invent the wheel every time when dealing with these issues.
Dates and timezones are tricky things, and generally no matter what kind of technology stack you are working on there is rarely a turn key solution.
Most databases will store a date or timestamp as little more than the exact date or timestamp that was given to it. When talking with a database through queries they are generally under the assumption that all dates and timestamps represent a point in time under the same time zone. In other words, if I write a query to see if Aug 2nd 2012 4:10pm is before the same date at 5:10pm then that will evaluate to true returning me that record. Suppose the record was saved as 4:10pm Eastern Standard Time when my database server is in Pacific Standard Time. The database is time zone agnostic and now my query is not returning the data I expect.
Convert all application dates and times to UTC or GMT before persisting
Languages like Java, Javascript and C# treat dates and times a bit differently. They will generally measure time as a number of milliseconds from a given universal point in time. This is the universal time as that specific number of milliseconds from 0 represents a number of different dates or times in different timezones at any given point. Most of these languages generally have a solid Date and Time API or a good third party library can be found that make viewing this millisecond count in a number of timezones as painless as possible.
Unless otherwise specified, if I use a standard data access API in a common language, most will take a date object and convert it into the date and time of the servers default timezone in the specified database format. Figure out how your language data access API and database stores dates and how it interprets them from the database and try to store your dates at the database level in GMT. Likewise when querying make sure that Date objects or variables in your language are representing a millisecond count that is equivalent to the GMT date time stored in the database.
Persist Time Zones for Dates that are used in Business Logic
What I mean by this is that perhaps if you have a Modified Date column in your database, then it may not be important to business logic, however a column Appointment Date probably will be important.
Somewhere in your schema you need to determine where locale specific data is stored and store the Time Zone to define that locale in the appropriate parent table. Your business logic that is considering dates, or your presentation logic that is preparing dates for display must be able to fetch the appropriate Time Zone so that when I am comparing 4:10pm to 5:10pm, that I am comparing dates from the appropriate universal time. 4:10pm EST and 4:10pm PST are seperate points in universal time. Again a good Date and Time API or third party library makes date comparisons easy, when you understand the underlying nature of how dates work in that programming language.
Business Logic Should be refactored to be time zone aware.
Presentation Logic Should be refactored to present a display value that is appropriately displaying the correct data per the appropriate given Time Zone.
One final thought to consider when performing this work is to write exhaustive unit tests that thoroughly exhaust many types of Date and Time combinations to make sure that all business logic works as expected.
Best Answer
I believe the answer is no although I think it is more about usage. There can be multiple time zones in a single zip. As an example look at the rules for military mail on usps (https://pe.usps.com/text/pub28/28c2_010.htm). There are a few specific zips that include many different time zones around the world.