A Zoned Defense

Tháng Hai 17, 2009

Source: http://errtheblog.com/posts/49-a-zoned-defense

Supporting timezones is a pain in the ass, but it’s a necessary evil for some sites and there are two working solutions as I see it.

Observe:

  • caboose “the official way”
  • why “the slick way”

The first one involves a fair amount of setup including one gem and two plugins, and the second one is too slow.

Err’s gonna give you a third option: zoned

We take the best of both worlds and mash them together into a plugin that consists of about 10 lines of ruby and the same amount of javascript.

We’ve been using it on Chowhound for the past month with positive results, even through the dreaded DST change. Here’s how it works:

The Javascript

var Timezone = {
  set : function() {
    var date = new Date();
    date.setTime(date.getTime() + (1000*24*60*60*1000));
    var expires = "; expires=" + date.toGMTString();
    document.cookie = "timezone=" + (-date.getTimezoneOffset() * 60) + expires + "; path=/";
  }
}

This sets a timezone cookie with the value returned from the essential date.getTimezoneOffset() function. This is important because you need the client’s offset, ruby can’t help you here.

The Ruby

module Zoned
  mattr_reader :server_offset
  @@server_offset = Time.now.gmtoff

  def zoned(date)
    return date unless timezone = controller.send(:cookies)[:timezone]
    date - (server_offset - timezone.to_i)
  end
  alias :z :zoned
end

All this does:

  • Returns the date untouched if the cookie isn’t set
  • Determines the server’s GMT offset
  • Takes the difference of the server’s offset with the client’s offset and the date passed

The second bullet point is unnecessary, but an added bonus for anyone with a server not running UTC which is a requirement for almost all other timezone solutions.

How we’re using it

Login/Signup:

<% form_for @login, { :html => { :onsubmit => "Timezone.set()" } %>

Logout:

cookies.delete(:timezone)

Views:

<%= z(post.created_at).to_s(:long) %>

Final thoughts

There are some issues you have to be cool with if you use this plugin (or come up with a solution):

  • None of the dates will convert if the client’s javascript is disabled
  • When the date is converted, it will still think it’s in the original timezone
  • If DST happens or they change their computer’s timezone, they will need to log out and log back in to update their timezone cookie
  • If their computer’s timezone is set incorrectly, so will the updated time

In the case of something major like Daylight Saving Time, making sure their timezone cookie has been reset is as easy as changing the salt value used in our cookies to invalidate all of the existing ones, thus forcing them to log back in.

Per usual, install via:

./script/plugin install svn://errtheblog.com/svn/plugins/zoned

Overtime

You can convert everyone’s timezone (not just those logged in) via:

window.onload = Timezone.set

On the first page load it will show the server’s timezone, but on any subsequent loads the time will convert correctly.

Another idea is just to make an Ajax.Request in Timezone.set call an action that will save the user’s offset in the database so you don’t have to rely on a cookie.

Think of this plugin more as the building block that’ll cater to whatever suits your site best. Let us know how you’re using it.

Gửi phản hồi

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s

%d bloggers like this: