diff --git a/lib/creek/styles/converter.rb b/lib/creek/styles/converter.rb index 01a54e6..459d3fc 100644 --- a/lib/creek/styles/converter.rb +++ b/lib/creek/styles/converter.rb @@ -60,8 +60,10 @@ def self.call(value, type, style, options = {}) value.to_i when :float, :percentage value.to_f - when :date, :time, :date_time + when :date convert_date(value, options) + when :time, :date_time + convert_datetime(value, options) when :bignum convert_bignum(value) @@ -71,22 +73,17 @@ def self.call(value, type, style, options = {}) end end - # the trickiest. note that all these formats can vary on - # whether they actually contain a date, time, or datetime. def self.convert_date(value, options) - value = value.to_f - days_since_date_system_start = value.to_i - fraction_of_24 = value - days_since_date_system_start + date = base_date(options) + value.to_i + yyyy, mm, dd = date.strftime('%Y-%m-%d').split('-') - # http://stackoverflow.com/questions/10559767/how-to-convert-ms-excel-date-from-float-to-date-format-in-ruby - date = options.fetch(:base_date, Date.new(1899, 12, 30)) + days_since_date_system_start + ::Date.new(yyyy.to_i, mm.to_i, dd.to_i) + end - if fraction_of_24 > 0 # there is a time associated - seconds = (fraction_of_24 * 86400).round - return Time.utc(date.year, date.month, date.day) + seconds - else - return date - end + def self.convert_datetime(value, options) + date = base_date(options) + value.to_f.round(6) + + round_datetime(date.strftime('%Y-%m-%d %H:%M:%S.%N')) end def self.convert_bignum(value) @@ -96,6 +93,18 @@ def self.convert_bignum(value) value.to_f end end + + private + + def self.base_date(options) + options.fetch(:base_date, Date.new(1899, 12, 30)) + end + + def self.round_datetime(datetime_string) + /(?\d+)-(?\d+)-(?
\d+) (?\d+):(?\d+):(?\d+.\d+)/ =~ datetime_string + + ::Time.new(yyyy.to_i, mm.to_i, dd.to_i, hh.to_i, mi.to_i, ss.to_r).round(0) + end end end end diff --git a/spec/fixtures/sample_dates.xlsx b/spec/fixtures/sample_dates.xlsx new file mode 100644 index 0000000..e4edea5 Binary files /dev/null and b/spec/fixtures/sample_dates.xlsx differ diff --git a/spec/fixtures/sheets/sample_dates.xlsx b/spec/fixtures/sheets/sample_dates.xlsx new file mode 100644 index 0000000..0a5d92f Binary files /dev/null and b/spec/fixtures/sheets/sample_dates.xlsx differ diff --git a/spec/fixtures/sheets/single_data_programme.xlsx b/spec/fixtures/sheets/single_data_programme.xlsx new file mode 100644 index 0000000..468537f Binary files /dev/null and b/spec/fixtures/sheets/single_data_programme.xlsx differ diff --git a/spec/styles/converter_spec.rb b/spec/styles/converter_spec.rb index 270c9ad..a86e75c 100644 --- a/spec/styles/converter_spec.rb +++ b/spec/styles/converter_spec.rb @@ -3,13 +3,20 @@ describe Creek::Styles::Converter do describe :call do + def convert(value, type, style) Creek::Styles::Converter.call(value, type, style) end + describe :date do + it "works" do + expect(convert('41275', 'n', :date)).to eq(Date.new(2013,01,01)) + end + end + describe :date_time do it "works" do - expect(convert('41275', 'n', :date_time)).to eq(Date.new(2013,01,01)) + expect(convert('41275', 'n', :date_time)).to eq(Time.new(2013,01,01)) end end end diff --git a/spec/test_spec.rb b/spec/test_spec.rb index 062e6b3..d1f648a 100644 --- a/spec/test_spec.rb +++ b/spec/test_spec.rb @@ -26,6 +26,34 @@ end end +describe 'Creek parsing dates on a sample XLSX file' do + before(:all) do + @creek = Creek::Book.new 'spec/fixtures/sample_dates.xlsx' + + @expected_datetime_rows = [ + {'A3' => 'Date', 'B3' => Date.parse('2018-01-01')}, + {'A4' => 'Datetime 00:00:00', 'B4' => Time.parse('2018-01-01 00:00:00')}, + {'A5' => 'Datetime', 'B5' => Time.parse('2018-01-01 23:59:59')}] + end + + after(:all) do + @creek.close + end + + it 'parses dates successfully' do + rows = Array.new + row_count = 0 + @creek.sheets[0].rows.each do |row| + rows << row + row_count += 1 + end + + (2..5).each do |number| + expect(rows[number]).to eq(@expected_datetime_rows[number-2]) + end + end +end + describe 'Creek parsing a sample XLSX file' do before(:all) do @creek = Creek::Book.new 'spec/fixtures/sample.xlsx' @@ -63,15 +91,9 @@ row_count += 1 end - expect(rows[0]).to eq(@expected_rows[0]) - expect(rows[1]).to eq(@expected_rows[1]) - expect(rows[2]).to eq(@expected_rows[2]) - expect(rows[3]).to eq(@expected_rows[3]) - expect(rows[4]).to eq(@expected_rows[4]) - expect(rows[5]).to eq(@expected_rows[5]) - expect(rows[6]).to eq(@expected_rows[6]) - expect(rows[7]).to eq(@expected_rows[7]) - expect(rows[8]).to eq(@expected_rows[8]) + (0..8).each do |number| + expect(rows[number]).to eq(@expected_rows[number]) + end expect(row_count).to eq(9) end