TimeZone helper methods...

I was having a bitch of a time trying to set these new TZ aware attributes from a string. I've added this helper method to my app, and thought there might be some interest in adding it to the core.

It parses a time string and returns a proper time instance set in the right zone. I'm calling it Time.parse_with_zone

Thoughts?

module ActiveSupport #:nodoc:   module CoreExtensions #:nodoc:     module Time #:nodoc:       # Enables the use of time calculations within Time itself       module Calculations         module ClassMethods

          def parse_with_zone(time_str)             d = parse(time_str)             t = utc_time(d.year, d.month, d.day, d.hour, d.min)             begin               result = zone.local_to_utc(t)             rescue TZInfo::PeriodNotFound               t += 1.hour               retry             end             result.in_time_zone(self.zone)           end

        end       end     end   end end

Time.zone.parse() should do the trick.

...better docs and a thorough writeup of the new time zone features coming soon. In the meantime, here's a quick overview of the api:

Rails initializer option for turning on ActiveRecord's automatic time zone conversions for datetime/timestamp columns, and setting a default zone for Time.zone (which can be overridden per request, if necessary):

  # No need to set config.active_record.default_timezone when you set this:   config.time_zone = 'Eastern Time (US & Canada)'

Set Time.zone per request:

  class ApplicationController < ActionController::Base     before_filter :set_time_zone

    protected       def set_time_zone         Time.zone = current_user.time_zone       end   end

Methods for creating TimeWithZone instances in Time.zone:

  Time.zone.local(*values)   Time.zone.at(secs)   Time.zone.parse(str)   Time.zone.now   Time.zone.today #returns a Date instance

  Time#in_time_zone   Time#in_time_zone("Alaska") #use this zone instead of Time.zone

Opt out of automatic time zone conversions for specific ActiveRecord model attributes:

  class Task < ActiveRecord::Base     skip_time_zone_conversion_for_attributes = :alert_at, :alert_at2   end

That doesn't work for me because I'm using TZInfo::Timezones

There is no parse for that class AFAIK. Since Rails accepts that as a zone, it'd be nice if you included that method for those of us stuck on TZInfo::Timezone.

Unless there's a way to automatically convert that to a Rails TimeZone object when setting Time.zone? Might be a better idea...

Unless there's a way to automatically convert that to a Rails TimeZone object when setting Time.zone? Might be a better idea...

That's not a bad idea -- the Time.zone setter method could wrap TZInfo::Timezone instances in a Rails TimeZone object, and that would allow you to use parse, local, at, now and today methods, plus any other methods that we might add to TimeZone instances in the future. Should be easy enough to implement this.

Opt out of automatic time zone conversions for specific ActiveRecord model attributes:

  class Task < ActiveRecord::Base     skip_time_zone_conversion_for_attributes = :alert_at, :alert_at2   end

...correction, the call to skip_time_zone_conversion_for_attributes needs to have an explicit +self+:

class Task < ActiveRecord::Base   self.skip_time_zone_conversion_for_attributes = :alert_at, :alert_at2 end

That would save a ton of headaches. A lot of these issues I've run into seem to be because of TZInfo::LinkedTimezone / TZInfo::Timezone. Wrapping that class would be beautiful.

I'd make the switch to TimeZone but I can't seem to find a proper translation for the identifier strings already stored in my DB. I'm willing to bet a lot of other people are in the same boat.

Please keep us posted...

I'd make the switch to TimeZone but I can't seem to find a proper translation for the identifier strings already stored in my DB. I'm willing to bet a lot of other people are in the same boat.

You can find the mapping between TimeZone and TZInfo indentifiers in the TimeZone::MAPPING hash. Converting over should be straightforward, just be aware of the following:

1. TZInfo defines more zones than TimeZone does, so some TZInfo identifiers have no TimeZone equivalent 2. some TZInfo identifiers map to more than one TimeZone (e.g., "America/Mexico_City" maps to both "Guadalajara" and "Mexico City")

That would save a ton of headaches. A lot of these issues I've run into seem to be because of TZInfo::LinkedTimezone / TZInfo::Timezone. Wrapping that class would be beautiful.

Added in [9107] -- in addition to recognizing Rails TimeZone instances and identifiers, Time.zone= now accepts a TZInfo::Timezone instance, or a TZInfo/Olson identifier string (e.g., "America/New_York"). TZInfo::Timezones are then wrapped on the fly in a Rails TimeZone.

Glad you're putting the new time zone features through the paces -- keep us posted if you run into any more issues.

Geoff

Not sure where this comment should go, but a fresh rails command generates a configuration in environment.rb that attempts :timezone= on the Rails::Configuration object. (NoMethodError) Result: rails does not generate a working app!

Make sure you have vendor/rails set to edge - (run rake rails:freeze:edge) - and you’ll be up and running.

Hi Chris: Thanks for your reply, but I'm afraid I don't understand: If I do: 1> gem install rails #( rails (2.0.2.9129) 2> rails mysite 3> cd mysite 4> (placeholder) 5> ruby script\about (NoMethodError)

but if I insert in placeholder 4> rake rails:freeze:edge

I get a good result?

But why should the generator packed with the gem, generate edge-only code? I didn't really want to run on the edge. Why would the gem-generator anticipate an edge installation?

Geoff, wanted to chime in and thank you for rolling that in.

I just upped to edge and tested with the new changes. Solved a few bugs I've been having issues with for a looooooong time that were maddening.

Great work on this.