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