lib/barometer/data/zone.rb in attack-barometer-0.5.0 vs lib/barometer/data/zone.rb in attack-barometer-0.6.0

- old
+ new

@@ -9,242 +9,133 @@ # Really, these are just wrappers for TZInfo conversions plus # some extras. # class Data::Zone - attr_accessor :timezone, :tz + @@zone_codes_file = File.expand_path( + File.join(File.dirname(__FILE__), '..', 'translations', 'zone_codes.yml')) + @@zone_codes = nil + + attr_accessor :zone_full, :zone_code, :zone_offset, :tz - def initialize(timezone) - @timezone = timezone - @tz = TZInfo::Timezone.get(timezone) + def initialize(zone) + if Data::Zone.is_zone_full?(zone) + @zone_full = zone + @tz = TZInfo::Timezone.get(zone) + elsif Data::Zone.is_zone_offset?(zone) + @zone_offset = zone + elsif Data::Zone.is_zone_code?(zone) + @zone_code = zone + else + raise(ArgumentError, "invalid time zone") + end end + def current + @zone_full || @zone_offset || @zone_code + end + # what is the Timezone Short Code for the current timezone def code - return "" unless @tz + return @zone_code if @zone_code + return nil unless @tz @tz.period_for_utc(Time.now.utc).zone_identifier.to_s end + def full + @zone_full || nil + end + + def offset + if @zone_offset + @zone_offset.to_f * 60 * 60 + elsif @zone_code + Data::Zone.zone_to_offset(@zone_code) + elsif @zone_full + end + end + # is the current timezone in daylights savings mode? def dst? return nil unless @tz @tz.period_for_utc(Time.now.utc).dst? end # return Time.now.utc for the set timezone - def now - Data::Zone.now(@timezone) + def now(convert=false) + if @zone_full + now = @tz.utc_to_local(Time.now.utc) + elsif @zone_offset || @zone_code + now = Time.now.utc + self.offset + end + convert ? Data::LocalTime.parse(now) : now end # return Date.today for the set timezone def today - Data::Zone.today(@timezone) + now = self.now + Date.new(now.year, now.month, now.day) end def local_to_utc(local_time) - @tz.local_to_utc(local_time) + if @zone_full + @tz.local_to_utc(local_time) + elsif @zone_offset || @zone_code + local_time -= self.offset + Time.utc(local_time.year,local_time.month,local_time.day, + local_time.hour,local_time.min,local_time.sec) + end end def utc_to_local(utc_time) - @tz.utc_to_local(utc_time) + if @zone_full + @tz.utc_to_local(utc_time) + elsif @zone_offset || @zone_code + utc_time + self.offset + end end # # Class Methods # - # return the local current time, providing a timezone - # (ie 'Europe/Paris') will give the local time for the - # timezone, otherwise it will be Time.now - def self.now(timezone=nil) - if timezone - utc = Time.now.utc - tz = TZInfo::Timezone.get(timezone) - tz.utc_to_local(utc) - else - Time.now - end + def self.is_zone_code?(zone) + return false unless (zone && zone.is_a?(String)) + _load_zone_codes unless @@zone_codes + Time.zone_offset(zone) || (@@zone_codes && @@zone_codes.has_key?(zone)) end - # return the local current date, providing a timezone - # (ie 'Europe/Paris') will give the local date for the - # timezone, otherwise it will be Date.today - def self.today(timezone=nil) - if timezone - utc = Time.now.utc - tz = TZInfo::Timezone.get(timezone) - now = tz.utc_to_local(utc) - Date.new(now.year, now.month, now.day) - else - Date.today - end + def self.is_zone_full?(zone) + return false unless (zone && zone.is_a?(String)) + zone.match(/[A-Za-z]+\/[A-Za-z]+/) ? true : false end - # takes a time (any timezone), and a TimeZone Short Code (ie PST) or - # the number of hours offset from UTC time and - # converts the time to UTC according to that time_zone - # NOTE: No Tests - def self.code_to_utc(time, timezone) - raise ArgumentError unless time.is_a?(Time) - - offset = self.zone_to_offset(timezone) - - Time.utc( - time.year, time.month, time.day, - time.hour, time.min, time.sec, time.usec - ) - offset + def self.is_zone_offset?(zone) + return false unless (zone && (zone.is_a?(Fixnum) || zone.is_a?(Float))) + zone.to_f.abs <= 14 end - - # takes a string with TIME only information and merges it with a string that - # has DATE only information and creates a UTC TIME object with time and date - # info. if you supply the timezone code (ie PST), it will apply the timezone - # offset to the final time - def self.merge(time, date, timezone_code=nil) - raise ArgumentError unless (time.is_a?(Time) || time.is_a?(String)) - raise ArgumentError unless (date.is_a?(Time) || date.is_a?(Date) || date.is_a?(String)) - - if time.is_a?(String) - reference_time = Time.parse(time) - elsif time.is_a?(Time) - reference_time = time - end - - if date.is_a?(String) - reference_date = Date.parse(date) - elsif date.is_a?(Time) - reference_date = Date.new(date.year, date.month, date.day) - elsif date.is_a?(Date) - reference_date = date - end - - new_time = Time.utc( - reference_date.year, reference_date.month, reference_date.day, - reference_time.hour, reference_time.min, reference_time.sec - ) - timezone_code ? Data::Zone.code_to_utc(new_time,timezone_code) : new_time - end - + # # Known conflicts # IRT (ireland and india) # CST (central standard time, china standard time) # def self.zone_to_offset(timezone) offset = 0 seconds_in_hour = 60*60 - # do we have a short_timezone code, or an offset? - if timezone.is_a?(Fixnum) || - (timezone.is_a?(String) && timezone.to_i.to_s == timezone) - # we have an offset, convert to second - offset = timezone.to_i * seconds_in_hour - else - # try to use Time - unless offset = Time.zone_offset(timezone) - # that would have been too easy, do it manually - # http://www.timeanddate.com/library/abbreviations/timezones/ - # http://www.worldtimezone.com/wtz-names/timezonenames.html - zone_offsets = { - :A => 1, :ACDT => 10.5, :ACST => 9.5, :ADT => -3, :AEDT => 11, - :AEST => 10, :AFT => 4.5, :AHDT => -9, :AHST => -10, :AKDT => -8, - :AKST => -9, :AMST => 5, :AMT => 4, :ANAST => 13, :ANAT => 12, - :ART => -3, :AST => -4, :AT => -1, :AWDT => 9, :AWST => 8, - :AZOST => 0, :AZOT => -1, :AZST => 5, :AZT => 4, - - :B => 2, :BADT => 4, :BAT => 6, :BDST => 2, :BDT => 6, :BET => -11, - :BNT => 8, :BORT => 8, :BOT => -4, :BRA => -3, :BST => 1, :BT => 6, - :BTT => 6, - - :C => 3, :CAT => 2, :CCT => 8, :CEST => 2, :CET => 1, :CHADT => 13.75, - :CHAST => 12.75, :CHST => 10, :CKT => -10, :CLST => -3, :CLT => -4, - :COT => -5, :CUT => 0, :CVT => -1, :CWT => 8.75, :CXT => 7, :CEDT => 2, - - :D => 4, :DAVT => 7, :DDUT => 10, :DNT => 1, :DST => 2, - - :E => 5, :EASST => -5, :EAST => -6, :EAT => 3, :ECT => -5, :EEST => 3, - :EET => 2, :EGST => 0, :EGT => -1, :EMT => 1, :EEDT => 3, - - :F => 6, :FDT => -1, :FJST => 13, :FJT => 12, :FKST => -3, :FKT => -4, - :FST => 2, :FWT => 1, - - :G => 7, :GALT => -6, :GAMT => -9, :GEST => 5, :GET => 4, :GFT => -3, - :GILT => 12, :GST => 4, :GT => 0, :GYT => -4, :GZ => 0, - - :H => 8, :HAA => -3, :HAC => -5, :HADT => -9, :HAE => -4, :HAP => -7, - :HAR => -6, :HAST => -10, :HAT => -2.5, :HAY => -8, :HDT => -9.5, - :HFE => 2, :HFH => 1, :HG => 0, :HKT => 8, :HNA => -4, :HNC => -6, - :HNE => -5, :HNP => -8, :HNR => -7, :HNT => -3.5, :HNY => -9, - :HOE => 1, :HST => -10, - - :I => 9, :ICT => 4, :IDLE => 12, :IDLW => -12, :IDT => 1, :IOT => 5, - :IRDT => 4.5, :IRKST => 9, :IRKT => 8, :IRST => 3.5, :IRT => 3.5, - :IST => 1, :IT => 3.5, :ITA => 1, - - :JAVT => 7, :JAYT => 9, :JFDT => -3, :JFST => -4, :JST => 9, :JT => 7, - - :K => 10, :KDT => 10, :KGST => 6, :KGT => 5, :KOST => 12, :KOVT => 7, - :KOVST => 8, :KRAST => 8, :KRAT => 7, :KST => 9, - - :L => 11, :LHDT => 11, :LHST => 10.5, :LIGT => 10, :LINT => 14, :LKT => 6, - :LST => 1, - - :M => 12, :MAGST => 12, :MAGT => 11, :MAL => 8, :MART => -9.5, :MAT => 3, - :MAWT => 6, :MBT => 8, :MED => 2, :MEDST => 2, :MEST => 2, :MESZ => 2, - :MET => 1, :MEWT => 1, :MEX => -6, :MEZ => 1, :MHT => 12, :MIT => 9.5, - :MMT => 6.5, :MNT => 8, :MNST => 9, :MPT => 10, :MSD => 4, :MSK => 3, - :MSKS => 4, :MT => 8.5, :MUT => 4, :MUST => 5, :MVT => 5, :MYT => 8, - :MFPT => -10, - - :N => -1, :NCT => 11, :NDT => -2.5, :NFT => 11.5, :NOR => 1, :NOVST => 7, - :NOVT => 6, :NPT => 5.75, :NRT => 12, :NST => -3.5, :NSUT => 6.5, - :NT => -11, :NUT => -11, :NZDT => 13, :NZST => 12, :NZT => 12, - - :O => -2, :OESZ => 3, :OEZ => 2, :OMSK => 7, :OMSST => 7, :OMST => 6, - - :P => -3, :PET => -5, :PETST => 13, :PETT => 12, :PGT => 10, :PHOT => 13, - :PHT => 8, :PIT => 8, :PKT => 5, :PKST => 6, :PMDT => -2, :PMST => -3, - :PMT => -3, :PNT => -8.5, :PONT => 11, :PYST => -3, :PYT => -4, :PWT => 9, - - :Q => -4, - - :R => -5, :R1T => 2, :R2T => 3, :RET => 4, :ROK => 9, :ROTT => -3, - - :S => -6, :SADT => 10.5, :SAMST => 5, :SAMT => 4, :SAST => 2, :SBT => 11, - :SCT => 4, :SCDT => 13, :SCST => 12, :SET => 1, :SGT => 8, :SIT => 8, - :SLT => -4, :SLST => -3, :SRT => -3, :SST => -11, :SYST => 3, :SWT => 1, - :SYT => 2, - - :T => -7, :TAHT => -10, :TFT => 5, :THA => 7, :THAT => -10, :TJT => 5, - :TKT => -10, :TMT => 5, :TOT => 13, :TRUK => 10, :TPT => 9, :TRUT => 10, - :TST => 3, :TUC => 0, :TVT => 12, :TWT => 8, - - :U => -8, :ULAST => 9, :ULAT => 8, :USZ1 => 2, :USZ1S => 3, :USZ3 => 4, - :USZ3S => 5, :USZ4 => 5, :USZ4S => 6, :USZ5 => 6, :USZ5S => 7, :USZ6 => 7, - :USZ6S => 8, :USZ7 => 8, :USZ7S => 9, :USZ8 => 9, :USZ8S => 10, :USZ9 => 10, - :USZ9S => 11, :UTZ => -3, :UYT => -3, :UYST => -2, :UZ10 => 11, :UZ10S => 12, - :UZ11 => 12, :UZ11S => 13, :UZ12 => 12, :UZ12S => 13, :UZT => 5, - - :V => -9, :VET => -4.5, :VLAST => 11, :VLAT => 10, :VOST => 6, :VST => -4.5, - :VTZ => -2, :VUT => 11, - - :W => -10, :WAKT => 12, :WAST => 2, :WAT => 1, :WCT => 8.75, :WEST => 1, - :WESZ => 1, :WET => 0, :WEZ => 0, :WFT => 12, :WGST => -2, :WGT => -3, - :WIB => 7, :WITA => 8, :WIT => 9, :WST => 8, :WKST => 5, :WTZ => -1, - :WUT => 1, :WEDT => 1, :WDT => 9, - - :X => -11, - - :Y => -12, :YAKST => 10, :YAKT => 9, :YAPT => 10, :YDT => -8, :YEKST => 6, - :YEKT => 5, :YST => -9, - - :Z => 0 - } - # unknown - # :HL => X, :LST => X, :LT => X, :OZ => X :SZ => X :TAI => X :UT => X :WZ => X - - offset = (zone_offsets[timezone.to_s.upcase.to_sym] || 0) * seconds_in_hour - end + # try to use Time + unless offset = Time.zone_offset(timezone) + # that would have been too easy, do it manually + # http://www.timeanddate.com/library/abbreviations/timezones/ + # http://www.worldtimezone.com/wtz-names/timezonenames.html + offset = (@@zone_codes[timezone.to_s.upcase] || 0) * seconds_in_hour end - return offset + offset + end + + def self._load_zone_codes + $:.unshift(File.dirname(__FILE__)) + @@zone_codes ||= YAML.load_file(@@zone_codes_file) end end end \ No newline at end of file