How to represent variable offset time zones in REST XML web service?
I've come across an interesting problem regarding Rails REST XML and the way datetime values are serialized. Namely, datetime values are represented as constant offset values like so:
<model>
<date type="datetime">2010-07-21T16:38:03-05:00</date>
</model>
Note the datetime value plus a constant offset of -0500. When consuming information from this REST web service, such an offset works perfectly. But suppose I wanted to POST information to this web service, and I wanted Rails to account for daylight savings much like it would do when a user submits a web form. I've found I can do this:
<model>
<date type="datetime">2010-07-21 16:38:03</date>
</model>
and the time will be correctly interpreted as the local user's time zone preference. This is, in effect, what is happening with a regular form submission. So far so good.
Also suppose that I need the ability to directly specify the time zone in the request. The reasoning is that a specific user might change their time zone preference at any time, but the API requests comin开发者_StackOverflow中文版g on their behalf are always in a fixed location (and thus a fixed time zone).
This seems simple enough, but is complicated by a few factors:
- Time zone offsets generally change twice a year (i.e. from -0500 to -0400 and back).
- Rails always expects constant time zone offsets or the datetime will be interpreted as local time (or the user's time zone preference).
- Ruby's Time class doesn't understand variable offsets. For example, I can specify a time is Eastern Standard Time (EST) or Eastern Daylight Time (EDT), but
Time.parse
will fail to properly understand "Eastern Time", or ET. I can't specify one or the other because that will cause the time to be off by an hour half of the year.
I've considered the following solutions:
Add a time_zone virtual attribute to the model. I don't like this because it makes very little sense in the context of the model, and the setting of the time zone is prone to issues with parameter assignment (i.e. the model must exhibit different behaviors when time_zone is processed before the date, after the date, and when time_zone is nil).
Use a query string parameter in association with the POST'ed XML data. Many people seem to frown on query strings being used in HTTP POST requests, and even popular rest clients don't seem to support it.
Are there any other possible solutions to this problem? I wish I could specify variable offsets like these but none of them work:
<date>2010-07-21 16:38:03 Eastern Time</date>
<date>2010-07-21 16:38:03 Eastern Time (US & Canada)</date>
<date>2010-07-21 16:38:03 ET</date>
<date>2010-07-21 16:38:03 America/New York</date>
If you're using ActiveRecord with Postgres, you would first set up your database to store the times with timezones, but if you don't really care about the zones - just that you want accurate times your approach could be to store all times as UTC, which means you need to parse any submitted times appropriately.
Example parsing to UTC.
require 'time' # there is a gotcha here - make sure you have this line
Time.parse("2011-03-01 01:00:00 EST").utc
=> Tue Mar 01 06:00:00 UTC 2011
Time.parse("2011-03-01 01:00:00 GMT").utc
=> Tue Mar 01 01:00:00 UTC 2011
Note that the parsed time includes the timezone as a three letter code. If it does not it would use the server's preference. You could do some work here to decide what to do if it does not include a zone. You're into some string parsing there.
Also note that the .utc
method call converts the parsed timezone into UTC, so when the data hits the database all times are stored in the same format.
精彩评论