From 505e68f03676cf82dd90a262015c21d2589979ab Mon Sep 17 00:00:00 2001 From: robuye Date: Tue, 18 Jun 2013 21:27:43 +0000 Subject: [PATCH 1/3] [Issue #22] consider time as local if no offset is given --- lib/nori.rb | 10 ++++++- lib/nori/xml_utility_node.rb | 13 +++++++-- nori.gemspec | 2 ++ spec/nori/nori_spec.rb | 51 ++++++++++++++++++++++++++++++++++++ spec/spec_helper.rb | 1 + 5 files changed, 74 insertions(+), 3 deletions(-) diff --git a/lib/nori.rb b/lib/nori.rb index 7854a37..446f4a0 100644 --- a/lib/nori.rb +++ b/lib/nori.rb @@ -1,6 +1,7 @@ require "nori/version" require "nori/core_ext" require "nori/xml_utility_node" +require "facets/date" class Nori @@ -19,11 +20,14 @@ def initialize(options = {}) :delete_namespace_attributes => false, :convert_tags_to => nil, :advanced_typecasting => true, - :parser => :nokogiri + :parser => :nokogiri, + :time_zone => nil } validate_options! defaults.keys, options.keys @options = defaults.merge(options) + + update_timezone(@options.delete(:time_zone)) end def find(hash, *path) @@ -46,6 +50,10 @@ def parse(xml) private + def update_timezone(tz) + tz ? ENV['TZ'] = tz : false + end + def load_parser(parser) require "nori/parser/#{parser}" Parser.const_get PARSERS[parser] diff --git a/lib/nori/xml_utility_node.rb b/lib/nori/xml_utility_node.rb index 1b68946..df32a4f 100644 --- a/lib/nori/xml_utility_node.rb +++ b/lib/nori/xml_utility_node.rb @@ -72,9 +72,9 @@ def self.available_typecasts=(obj) self.typecasts = {} self.typecasts["integer"] = lambda { |v| v.nil? ? nil : v.to_i } self.typecasts["boolean"] = lambda { |v| v.nil? ? nil : (v.strip != "false") } - self.typecasts["datetime"] = lambda { |v| v.nil? ? nil : Time.parse(v).utc } + self.typecasts["datetime"] = lambda { |v| v.nil? ? nil : parse_time(v) } self.typecasts["date"] = lambda { |v| v.nil? ? nil : Date.parse(v) } - self.typecasts["dateTime"] = lambda { |v| v.nil? ? nil : Time.parse(v).utc } + self.typecasts["dateTime"] = lambda { |v| v.nil? ? nil : parse_time(v) } self.typecasts["decimal"] = lambda { |v| v.nil? ? nil : BigDecimal(v.to_s) } self.typecasts["double"] = lambda { |v| v.nil? ? nil : v.to_f } self.typecasts["float"] = lambda { |v| v.nil? ? nil : v.to_f } @@ -250,6 +250,15 @@ def to_html private + def self.parse_time(input) + if (input =~ /(((\+|\-)\d\d(:)?(\d\d)?)|Z)\Z/) + input.to_time + else + input.to_time(:local) + end + end + self.typecasts["datetime"] = lambda { |v| v.nil? ? nil : Time.parse(v).utc } + # TODO: replace REXML def unnormalize_xml_entities value REXML::Text.unnormalize(value) diff --git a/nori.gemspec b/nori.gemspec index 24d084b..a9c0a04 100644 --- a/nori.gemspec +++ b/nori.gemspec @@ -16,6 +16,8 @@ Gem::Specification.new do |s| s.add_development_dependency "rake", "~> 10.0" s.add_development_dependency "nokogiri", ">= 1.4.0" s.add_development_dependency "rspec", "~> 2.12" + s.add_development_dependency "pry" + s.add_dependency "facets" s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") diff --git a/spec/nori/nori_spec.rb b/spec/nori/nori_spec.rb index 7c84320..2e35515 100644 --- a/spec/nori/nori_spec.rb +++ b/spec/nori/nori_spec.rb @@ -7,6 +7,57 @@ let(:parser) { parser } + context "when parsing times" do + let(:time_in_utc) { Time.new(2013,06,01,11,00,01, '+00:00') } + + context "when timezone is given" do + it "it respects notation +01:00" do + xml = '' + parse(xml).should == { 'time' => time_in_utc } + end + + it "it respects notation +0100" do + xml = '' + parse(xml).should == { 'time' => time_in_utc } + end + + it "it respects notation +01" do + xml = '' + parse(xml).should == { 'time' => time_in_utc } + end + + it "it respects notation -01" do + xml = '' + parse(xml).should == { 'time' => time_in_utc } + end + + it "it respects notation Z" do + xml = '' + parse(xml).should == { 'time' => time_in_utc } + end + end + + context "when timezone is not given" do + before(:each) { ENV['TZ'] = 'Europe/Minsk' } # its +03:00, no DST :) + it "treats the input as local time" do + xml = '' + parse(xml).should == { 'time' => time_in_utc } + end + + it "accepts passing timezone via options" do + xml = '' + Nori.new(time_zone: 'Asia/Dushanbe') + ENV['TZ'].should == 'Asia/Dushanbe' + end + + it "treats unknown timezone as UTC" do + xml = '' + Nori.new(time_zone: 'Incorrect Timezone').parse(xml) + parse(xml).should == { 'time' => time_in_utc.utc } + end + end + end + it "should work with unnormalized characters" do xml = '&' parse(xml).should == { 'root' => "&" } diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index dadf6cb..ab112a5 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,2 +1,3 @@ require "bundler" +require 'pry' Bundler.require :default, :development From 8c5dda0f9b1009cf47d5554d153458efb118420f Mon Sep 17 00:00:00 2001 From: robuye Date: Wed, 19 Jun 2013 00:13:13 +0000 Subject: [PATCH 2/3] #update_timezone does not return meaningful value --- lib/nori.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nori.rb b/lib/nori.rb index 446f4a0..8abe667 100644 --- a/lib/nori.rb +++ b/lib/nori.rb @@ -51,7 +51,7 @@ def parse(xml) private def update_timezone(tz) - tz ? ENV['TZ'] = tz : false + ENV['TZ'] = tz if tz end def load_parser(parser) From 3fe7bafa724480a20bf9f61211e0ae07c3ff6f64 Mon Sep 17 00:00:00 2001 From: robuye Date: Wed, 19 Jun 2013 00:30:15 +0000 Subject: [PATCH 3/3] remove accidential line --- lib/nori/xml_utility_node.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/nori/xml_utility_node.rb b/lib/nori/xml_utility_node.rb index df32a4f..cd6de47 100644 --- a/lib/nori/xml_utility_node.rb +++ b/lib/nori/xml_utility_node.rb @@ -257,7 +257,6 @@ def self.parse_time(input) input.to_time(:local) end end - self.typecasts["datetime"] = lambda { |v| v.nil? ? nil : Time.parse(v).utc } # TODO: replace REXML def unnormalize_xml_entities value