# --------------------------------------------------------------------------- # Copyright (c) 2007, 37signals # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # --------------------------------------------------------------------------- # A wrapper class that quacks like a Time instance, but which remembers its # local time zone. Most operations work like normal, but some will automatically # convert the object to utc, like #to_s(:db). class TzTime include Comparable # Like the Time class, the TzTime class is its own factory. You will almost # never create a TzTime instance via +new+. Instead, you will use something # like TzTime.now (etc.) class <(value) time.to_time <=> value.to_time end # This TzTime object always represents the local time in the associated # timezone. Thus, #utc? should always return false, unless the zone is the # UTC zone. def utc? zone.name == "UTC" end # Returns the underlying TZInfo::TimeZonePeriod instance for the wrapped # time. def period(dst=true) t = time begin @period ||= zone.tzinfo.period_for_local(t, dst) rescue TZInfo::PeriodNotFound t -= 1.hour retry end end # Returns true if the current time is adjusted for daylight savings. def dst? period.dst? end # Returns a string repersentation of the time. For the specific case where # +mode+ is :db or :rfc822, this will return the UTC # representation of the time. All other conversions will use the local time. def to_s(mode = :normal) case mode when :db, :rfc822 then utc.to_s(mode) else time.to_s(mode) end end # Return a reasonable representation of this TzTime object for inspection. def inspect "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{period.abbreviation}" end # Because of the method_missing proxy, we want to make sure we report this # object as responding to a method as long as the method is defined directly # on TzTime, or if the underlying Time instance responds to the method. def respond_to?(sym) #:nodoc: super || @time.respond_to?(sym) end # Proxy anything else through to the underlying Time instance. def method_missing(sym, *args, &block) #:nodoc: result = @time.send(sym, *args, &block) result = TzTime.new(result, zone) if result.is_a? Time result end end