TimeZone, TZInfo, daylight savings, and composed_of


#1

Does anyone know the best way to track time zone information. There
doesn’t
seem to be much documentation on this. So far it seems like a simple db
field like

create table accounts (
id int unsigned not null auto_increment,
name varchar(50) not null,
time_zone varchar(50) not null,

primary key (id)
)

and a class like

class Account < AR

composed_of :time_zone, :class_name => TimeZone, :mapping =>
%w(time_zone
name)
end

There also seems to be a TZInfo library that supports daylight savings.
It
seems strange that the TimeZone class in rails doesn’t support daylight
savings as Basecamp from 37Signals uses timezones and I’m sure they
would
have to support it… interesting.

Can anyone shed some light on this. :slight_smile:

Thanks,
Zack


#2

I don’t know if this helps much, but that’s basically what I’m doing,
and it
seems to work. Doing the timezone conversions is a pain, but it works.
It’s also kinda slow :frowning:


#3

The Pragmatic Rails Recipes book includes:

Recipe 23: Dealing With Time-zones


– Tom M.


#4

Thanks Tom - I’ll check it out.


#5

Thanks for sharing the code Dan!


#6

For what it’s worth (I haven’t read the book), here’s my way of
handling timezones using TZinfo… Extra stuff such as relationships
and so on removed for clarity.

–snip–
require_gem ‘tzinfo’
class Timezone < ActiveRecord::Base
extend Forwardable

validates_presence_of :name, :display_name

validates_each :name do |record, attribute|
unless TZInfo::Timezone.get(self.name)
record.errors.add attribute, “Invalid Timezone”
end
end

Forward these methods to the TZInfo::Timezone class

def_delegator(:tz, :utc_to_local, :utc_to_local)
def_delegator(:tz, :local_to_utc, :local_to_utc)
def_delegator(:tz, :identifier, :identifier)

End forward

def name=(value)
write_attribute(:name, value)
@tz = nil
end

def now
tz().now()
end

def today
Date.parse(now().strftime(DATEFORMAT_YYYYMMDD))
end

private

This method caches the TZInfo::Timezone class unless it is

flushed by the +name=+ method above.

def tz()
@tz.nil? ? @tz = TZInfo::Timezone.get(self.name) : @tz
end

end
–/snip–

Cheers,
Dan
www.peoplehub.com.au