Skip to content

Commit

Permalink
[Issue savonrb#22] consider time as local if no offset is given
Browse files Browse the repository at this point in the history
  • Loading branch information
robuye committed Jun 18, 2013
1 parent c51eaa6 commit 505e68f
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 3 deletions.
10 changes: 9 additions & 1 deletion lib/nori.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require "nori/version"
require "nori/core_ext"
require "nori/xml_utility_node"
require "facets/date"

class Nori

Expand All @@ -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)
Expand All @@ -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]
Expand Down
13 changes: 11 additions & 2 deletions lib/nori/xml_utility_node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions nori.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
51 changes: 51 additions & 0 deletions spec/nori/nori_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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 = '<time type="datetime">2013-06-01 12:00:01 +01:00</time>'
parse(xml).should == { 'time' => time_in_utc }
end

it "it respects notation +0100" do
xml = '<time type="datetime">2013-06-01 12:00:01 +0100</time>'
parse(xml).should == { 'time' => time_in_utc }
end

it "it respects notation +01" do
xml = '<time type="datetime">2013-06-01 12:00:01 +01</time>'
parse(xml).should == { 'time' => time_in_utc }
end

it "it respects notation -01" do
xml = '<time type="datetime">2013-06-01 10:00:01 -01</time>'
parse(xml).should == { 'time' => time_in_utc }
end

it "it respects notation Z" do
xml = '<time type="datetime">2013-06-01 11:00:01Z</time>'
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 = '<time type="datetime">2013-06-01 14:00:01</time>'
parse(xml).should == { 'time' => time_in_utc }
end

it "accepts passing timezone via options" do
xml = '<time type="datetime">2013-06-01 14:00:01</time>'
Nori.new(time_zone: 'Asia/Dushanbe')
ENV['TZ'].should == 'Asia/Dushanbe'
end

it "treats unknown timezone as UTC" do
xml = '<time type="datetime">2013-06-01 11:00:01</time>'
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 = '<root>&amp;</root>'
parse(xml).should == { 'root' => "&" }
Expand Down
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
require "bundler"
require 'pry'
Bundler.require :default, :development

0 comments on commit 505e68f

Please sign in to comment.