aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@ubuntu.com>2019-01-14 01:40:56 -0500
committerLibravatarUnit 193 <unit193@ubuntu.com>2019-01-14 01:40:56 -0500
commitdddfa903d2b856146f05ffb4415c31d6127bb5bf (patch)
treee38c2aca92b54f06ccd0185f48dc47e3e1b3d77e
parent8280a21a23d44aa90177e2bc041d0b8dc8556f4b (diff)
downloadruby-roo-dddfa903d2b856146f05ffb4415c31d6127bb5bf.tar.bz2
ruby-roo-dddfa903d2b856146f05ffb4415c31d6127bb5bf.tar.xz
ruby-roo-dddfa903d2b856146f05ffb4415c31d6127bb5bf.tar.zst
New upstream version 2.8.0upstream/2.8.0
-rw-r--r--.github/ISSUE_TEMPLATE10
-rw-r--r--.github/issue_template.md16
-rw-r--r--.github/pull_request_template.md14
-rw-r--r--.rubocop.yml186
-rw-r--r--.travis.yml19
-rw-r--r--CHANGELOG.md31
-rw-r--r--Gemfile_ruby230
-rw-r--r--LICENSE2
-rw-r--r--README.md37
-rw-r--r--lib/roo.rb5
-rw-r--r--lib/roo/base.rb121
-rw-r--r--lib/roo/constants.rb8
-rw-r--r--lib/roo/csv.rb32
-rwxr-xr-x[-rw-r--r--]lib/roo/excelx.rb58
-rw-r--r--lib/roo/excelx/cell.rb16
-rw-r--r--lib/roo/excelx/cell/base.rb38
-rw-r--r--lib/roo/excelx/cell/boolean.rb15
-rw-r--r--lib/roo/excelx/cell/date.rb14
-rw-r--r--lib/roo/excelx/cell/datetime.rb32
-rw-r--r--lib/roo/excelx/cell/empty.rb5
-rw-r--r--lib/roo/excelx/cell/number.rb69
-rw-r--r--lib/roo/excelx/cell/string.rb6
-rw-r--r--lib/roo/excelx/cell/time.rb7
-rw-r--r--lib/roo/excelx/comments.rb6
-rw-r--r--lib/roo/excelx/coordinate.rb15
-rwxr-xr-x[-rw-r--r--]lib/roo/excelx/extractor.rb24
-rw-r--r--lib/roo/excelx/format.rb69
-rw-r--r--lib/roo/excelx/images.rb26
-rw-r--r--lib/roo/excelx/relationships.rb6
-rwxr-xr-x[-rw-r--r--]lib/roo/excelx/shared.rb13
-rwxr-xr-xlib/roo/excelx/shared_strings.rb24
-rw-r--r--lib/roo/excelx/sheet.rb59
-rwxr-xr-xlib/roo/excelx/sheet_doc.rb134
-rw-r--r--lib/roo/excelx/styles.rb6
-rw-r--r--lib/roo/excelx/workbook.rb10
-rw-r--r--lib/roo/helpers/default_attr_reader.rb20
-rw-r--r--lib/roo/helpers/weak_instance_cache.rb41
-rw-r--r--lib/roo/open_office.rb14
-rw-r--r--lib/roo/spreadsheet.rb2
-rw-r--r--lib/roo/utils.rb67
-rw-r--r--lib/roo/version.rb2
-rw-r--r--roo.gemspec24
-rw-r--r--spec/lib/roo/base_spec.rb48
-rwxr-xr-xspec/lib/roo/excelx_spec.rb156
-rw-r--r--spec/lib/roo/strict_spec.rb43
-rw-r--r--spec/lib/roo/utils_spec.rb15
-rw-r--r--spec/lib/roo/weak_instance_cache_spec.rb92
-rw-r--r--spec/lib/roo_spec.rb0
-rw-r--r--test/excelx/cell/test_attr_reader_default.rb72
-rw-r--r--test/excelx/cell/test_base.rb5
-rw-r--r--test/excelx/cell/test_datetime.rb12
-rw-r--r--test/excelx/cell/test_empty.rb11
-rw-r--r--test/excelx/cell/test_number.rb9
-rw-r--r--test/excelx/cell/test_string.rb20
-rw-r--r--test/excelx/cell/test_time.rb8
-rw-r--r--test/excelx/test_coordinate.rb51
-rw-r--r--test/files/datetime_timezone_ist_offset_change.odsbin0 -> 37034 bytes
-rw-r--r--test/files/datetime_timezone_ist_offset_change.xlsxbin0 -> 22650 bytes
-rw-r--r--test/files/images.xlsxbin0 -> 1665748 bytes
-rw-r--r--test/files/link_with_location.xlsxbin0 -> 8943 bytes
-rw-r--r--test/files/number_with_zero_prefix.xlsxbin0 -> 108222 bytes
-rw-r--r--test/files/simple_spreadsheet.csv13
-rw-r--r--test/files/so_datetime_timezone_ist_offset_change.csv864
-rw-r--r--test/files/strict.xlsxbin0 -> 9353 bytes
-rw-r--r--test/formatters/test_csv.rb17
-rw-r--r--test/formatters/test_xml.rb8
-rw-r--r--test/roo/test_base.rb4
-rw-r--r--test/roo/test_csv.rb28
-rw-r--r--test/test_helper.rb13
-rw-r--r--test/test_roo.rb14
70 files changed, 2373 insertions, 463 deletions
diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE
deleted file mode 100644
index 186ffc1..0000000
--- a/.github/ISSUE_TEMPLATE
+++ /dev/null
@@ -1,10 +0,0 @@
-Thanks for filing an issue. Following these instructions will help us solve your problem sooner.
-
-1. Describe the issue.
-2. Create a gist for this issue (Sample gist: https://gist.github.com/stevendaniels/98a05849036e99bb8b3c)?
-
-Here are some instructions for creating such a gist.
-
-1. Create a gist (https://gist.github.com) with code that creates the error.
-2. Clone the gist repo locally, add a stripped down version of the offending spreadsheet to the gist repo, and push the gist's changes master.
-3. Paste the gist url here.
diff --git a/.github/issue_template.md b/.github/issue_template.md
new file mode 100644
index 0000000..b2bfc6d
--- /dev/null
+++ b/.github/issue_template.md
@@ -0,0 +1,16 @@
+Thanks for filing an issue. Following these instructions will help us solve your problem sooner.
+
+### Steps to reproduce
+
+1. Create an executable test case for this issue ([sample test case](https://gist.github.com/tgturner/e4b7f491639b8a6dd883fe2ace408652))
+2. You can share your executable test case as a [gist](https://gist.github.com), or simply paste the content into the issue description.
+ - You can execute the test case by running `ruby the_file.rb` in your terminal. If all goes well, you should see your test case failing.
+3. Please provide a stripped down version of the offending spreadsheet.
+
+### Issue
+Describe the issue
+
+### System configuration
+**Roo version**:
+
+**Ruby version**: \ No newline at end of file
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000..a0d7f6e
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,14 @@
+### Summary
+
+Provide a general description of the code changes in your pull
+request... were there any bugs you had fixed? If so, mention them. If
+these bugs have open GitHub issues, be sure to tag them here as well,
+to keep the conversation linked together.
+
+### Other Information
+
+If there's anything else that's important and relevant to your pull
+request, mention that information here. This could include
+benchmarks, or other information.
+
+Thanks for contributing to Roo! \ No newline at end of file
diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000..e6ce1a7
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,186 @@
+AllCops:
+ TargetRubyVersion: 2.4
+ # RuboCop has a bunch of cops enabled by default. This setting tells RuboCop
+ # to ignore them, so only the ones explicitly set in this file are enabled.
+ DisabledByDefault: true
+
+Performance:
+ Exclude:
+ - '**/test/**/*'
+ - '**/spec/**/*'
+
+# Prefer &&/|| over and/or.
+Style/AndOr:
+ Enabled: true
+
+# Do not use braces for hash literals when they are the last argument of a
+# method call.
+Style/BracesAroundHashParameters:
+ Enabled: true
+ EnforcedStyle: context_dependent
+
+# Align `when` with `case`.
+Layout/CaseIndentation:
+ Enabled: true
+
+# Align comments with method definitions.
+Layout/CommentIndentation:
+ Enabled: true
+
+Layout/ElseAlignment:
+ Enabled: true
+
+# Align `end` with the matching keyword or starting expression except for
+# assignments, where it should be aligned with the LHS.
+Layout/EndAlignment:
+ Enabled: true
+ EnforcedStyleAlignWith: variable
+ AutoCorrect: true
+
+Layout/EmptyLineAfterMagicComment:
+ Enabled: true
+
+Layout/EmptyLinesAroundBlockBody:
+ Enabled: true
+
+# In a regular class definition, no empty lines around the body.
+Layout/EmptyLinesAroundClassBody:
+ Enabled: true
+
+# In a regular method definition, no empty lines around the body.
+Layout/EmptyLinesAroundMethodBody:
+ Enabled: true
+
+# In a regular module definition, no empty lines around the body.
+Layout/EmptyLinesAroundModuleBody:
+ Enabled: true
+
+Layout/FirstParameterIndentation:
+ Enabled: true
+
+# Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
+Style/HashSyntax:
+ Enabled: true
+
+# Method definitions after `private` or `protected` isolated calls need one
+# extra level of indentation.
+Layout/IndentationConsistency:
+ Enabled: true
+
+# Two spaces, no tabs (for indentation).
+Layout/IndentationWidth:
+ Enabled: true
+
+Layout/LeadingCommentSpace:
+ Enabled: true
+
+Layout/SpaceAfterColon:
+ Enabled: true
+
+Layout/SpaceAfterComma:
+ Enabled: true
+
+Layout/SpaceAroundEqualsInParameterDefault:
+ Enabled: true
+
+Layout/SpaceAroundKeyword:
+ Enabled: true
+
+Layout/SpaceAroundOperators:
+ Enabled: true
+
+Layout/SpaceBeforeComma:
+ Enabled: true
+
+Layout/SpaceBeforeFirstArg:
+ Enabled: true
+
+Style/DefWithParentheses:
+ Enabled: true
+
+# Defining a method with parameters needs parentheses.
+Style/MethodDefParentheses:
+ Enabled: true
+
+Style/FrozenStringLiteralComment:
+ Enabled: true
+ EnforcedStyle: always
+
+# Use `foo {}` not `foo{}`.
+Layout/SpaceBeforeBlockBraces:
+ Enabled: true
+
+# Use `foo { bar }` not `foo {bar}`.
+Layout/SpaceInsideBlockBraces:
+ Enabled: true
+
+# Use `{ a: 1 }` not `{a:1}`.
+Layout/SpaceInsideHashLiteralBraces:
+ Enabled: true
+
+Layout/SpaceInsideParens:
+ Enabled: true
+
+# Check quotes usage according to lint rule below.
+Style/StringLiterals:
+ Enabled: true
+ EnforcedStyle: double_quotes
+
+# Detect hard tabs, no hard tabs.
+Layout/Tab:
+ Enabled: true
+
+# Blank lines should not have any spaces.
+Layout/TrailingBlankLines:
+ Enabled: true
+
+# No trailing whitespace.
+Layout/TrailingWhitespace:
+ Enabled: true
+
+# Use quotes for string literals when they are enough.
+Style/UnneededPercentQ:
+ Enabled: true
+
+# Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
+Lint/RequireParentheses:
+ Enabled: true
+
+Lint/StringConversionInInterpolation:
+ Enabled: true
+
+Lint/UriEscapeUnescape:
+ Enabled: true
+
+Style/ParenthesesAroundCondition:
+ Enabled: true
+
+Style/RedundantReturn:
+ Enabled: true
+ AllowMultipleReturnValues: true
+
+Style/Semicolon:
+ Enabled: true
+ AllowAsExpressionSeparator: true
+
+# Prefer Foo.method over Foo::method
+Style/ColonMethodCall:
+ Enabled: true
+
+Style/TrivialAccessors:
+ Enabled: true
+
+Performance/FlatMap:
+ Enabled: true
+
+Performance/RedundantMerge:
+ Enabled: true
+
+Performance/StartWith:
+ Enabled: true
+
+Performance/EndWith:
+ Enabled: true
+
+Performance/RegexpMatch:
+ Enabled: true \ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index e40d15e..4dc862b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,17 +1,22 @@
language: ruby
rvm:
- - 2.2.4
- - 2.3.1
- - 2.4.0
+ - 2.3
+ - 2.4
+ - 2.5
+ - 2.6
- ruby-head
- jruby-9.1.6.0
+env:
+ - LONG_RUN=true
matrix:
include:
- - rvm: 2.0.0
- gemfile: Gemfile_ruby2
- - rvm: 2.1.8
- gemfile: Gemfile_ruby2
+ - rvm: 2.6
+ env: RUBYOPT=--jit LONG_RUN=true
+ - rvm: ruby-head
+ env: RUBYOPT=--jit LONG_RUN=true
allow_failures:
- rvm: ruby-head
+ - rvm: ruby-head
+ env: RUBYOPT=--jit LONG_RUN=true
- rvm: jruby-9.1.6.0
bundler_args: --without local_development
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2a89cab..d93da95 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,33 @@
## Unreleased
+### Fixed
+- Fixed inconsistent column length for CSV [375](https://github.com/roo-rb/roo/pull/375)
+- Fixed formatted_value with `%` for Excelx [416](https://github.com/roo-rb/roo/pull/416)
+- Improved Memory consumption and performance [434](https://github.com/roo-rb/roo/pull/434) [449](https://github.com/roo-rb/roo/pull/449) [454](https://github.com/roo-rb/roo/pull/454) [456](https://github.com/roo-rb/roo/pull/456) [458](https://github.com/roo-rb/roo/pull/458) [462](https://github.com/roo-rb/roo/pull/462) [466](https://github.com/roo-rb/roo/pull/466)
+- Accept both Transitional and Strict Type for Excelx's worksheets [441](https://github.com/roo-rb/roo/pull/441)
+- Fixed ruby warnings [442](https://github.com/roo-rb/roo/pull/442) [476](https://github.com/roo-rb/roo/pull/476)
+- Restore support for URL as file identifier for CSV [462](https://github.com/roo-rb/roo/pull/462)
+- Fixed missing location for Excelx's links [482](https://github.com/roo-rb/roo/pull/482)
+
+### Changed / Added
+- Drop support for ruby 2.2.x and lower
+- Updated rubyzip version for fixing security issue. Now minimal version is 1.2.1
+- Roo::Excelx::Coordinate now inherits Array [458](https://github.com/roo-rb/roo/pull/458)
+- Improved Roo::HeaderRowNotFoundError exception's message [461](https://github.com/roo-rb/roo/pull/461)
+- Added `empty_cell` option which by default disable allocation for Roo::Excelx::Cell::Empty [464](https://github.com/roo-rb/roo/pull/464)
+- Added support for variable number of decimals for Excelx's formatted_value [387](https://github.com/roo-rb/roo/pull/387)
+- Added `disable_html_injection` option to disable html injection for shared string in `Roo::Excelx` [392](https://github.com/roo-rb/roo/pull/392)
+- Added image extraction for Excelx [414](https://github.com/roo-rb/roo/pull/414) [397](https://github.com/roo-rb/roo/pull/397)
+- Added support for `1e6` as scientific notation for Excelx [433](https://github.com/roo-rb/roo/pull/433)
+- Added support for Integer as 0 based index for Excelx's `sheet_for` [455](https://github.com/roo-rb/roo/pull/455)
+- Extended `no_hyperlinks` option for non streaming Excelx methods [459](https://github.com/roo-rb/roo/pull/459)
+- Added `empty_cell` option to disable Roo::Excelx::Cell::Empty allocation for Excelx [464](https://github.com/roo-rb/roo/pull/464)
+- Added support for Integer with leading zero for Roo:Excelx [479](https://github.com/roo-rb/roo/pull/479)
+- Refactored Excelx code [453](https://github.com/roo-rb/roo/pull/453) [477](https://github.com/roo-rb/roo/pull/477) [483](https://github.com/roo-rb/roo/pull/483) [484](https://github.com/roo-rb/roo/pull/484)
+
+### Deprecations
+- Roo::Excelx::Sheet#present_cells is deprecated [454](https://github.com/roo-rb/roo/pull/454)
+- Roo::Utils.split_coordinate is deprecated [458](https://github.com/roo-rb/roo/pull/458)
+- Roo::Excelx::Cell::Base#link is deprecated [457](https://github.com/roo-rb/roo/pull/457)
## [2.7.1] 2017-01-03
### Fixed
@@ -48,7 +77,7 @@
- Discard hyperlinks lookups to allow streaming parsing without loading whole files
## [2.4.0] 2016-05-14
-### Fixed
+### Fixed
- Fixed opening spreadsheets with charts [315](https://github.com/roo-rb/roo/pull/315)
- Fixed memory issues for Roo::Utils.number_to_letter [308](https://github.com/roo-rb/roo/pull/308)
- Fixed Roo::Excelx::Cell::Number to recognize floating point numbers [306](https://github.com/roo-rb/roo/pull/306)
diff --git a/Gemfile_ruby2 b/Gemfile_ruby2
deleted file mode 100644
index 20bcade..0000000
--- a/Gemfile_ruby2
+++ /dev/null
@@ -1,30 +0,0 @@
-source 'https://rubygems.org'
-
-gemspec
-
-gem 'nokogiri', "< 1.7.0"
-
-group :test do
- # additional testing libs
- gem 'shoulda'
- gem 'rspec', '>= 3.0.0'
- gem 'simplecov', '>= 0.9.0', require: false
- gem 'coveralls', require: false
- gem "activesupport", "~> 4.2.0"
- gem "tins", '~> 1.6.0'
- gem "term-ansicolor", "~> 1.3.2"
- gem "minitest-reporters"
-end
-
-group :local_development do
- gem "listen", "~> 3.0.6"
- gem 'terminal-notifier-guard', require: false if RUBY_PLATFORM.downcase.include?('darwin')
- gem 'guard-rspec', '>= 4.3.1', require: false
- gem 'guard-minitest', require: false
- gem 'guard-bundler', require: false
- gem 'guard-preek', require: false
- gem 'guard-rubocop', require: false
- gem 'guard-reek', github: 'pericles/guard-reek', require: false
- gem 'rb-readline'
- gem 'pry'
-end
diff --git a/LICENSE b/LICENSE
index 182b747..3dad4df 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,6 @@
Copyright (c) 2008-2014 Thomas Preymesser, Ben Woosley
+Copyright (c) 2014-2017 Ben Woosley
+Copyright (c) 2015-2017 Oleksandr Simonov, Steven Daniels
MIT License
diff --git a/README.md b/README.md
index 00a9ad9..0b18055 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Roo
-[![Build Status](https://img.shields.io/travis/roo-rb/roo.svg?style=flat-square)](https://travis-ci.org/roo-rb/roo) [![Code Climate](https://img.shields.io/codeclimate/github/roo-rb/roo.svg?style=flat-square)](https://codeclimate.com/github/roo-rb/roo) [![Coverage Status](https://img.shields.io/coveralls/roo-rb/roo.svg?style=flat-square)](https://coveralls.io/r/roo-rb/roo) [![Gem Version](https://img.shields.io/gem/v/roo.svg?style=flat-square)](https://rubygems.org/gems/roo)
+[![Build Status](https://img.shields.io/travis/roo-rb/roo.svg?style=flat-square)](https://travis-ci.org/roo-rb/roo) [![Maintainability](https://api.codeclimate.com/v1/badges/be8d7bf34e2aeaf67c62/maintainability)](https://codeclimate.com/github/roo-rb/roo/maintainability) [![Coverage Status](https://img.shields.io/coveralls/roo-rb/roo.svg?style=flat-square)](https://coveralls.io/r/roo-rb/roo) [![Gem Version](https://img.shields.io/gem/v/roo.svg?style=flat-square)](https://rubygems.org/gems/roo)
Roo implements read access for all common spreadsheet types. It can handle:
* Excel 2007 - 2013 formats (xlsx, xlsm)
@@ -89,13 +89,13 @@ sheet.last_column
You can access the top-left cell in the following ways
```ruby
-s.cell(1,1)
-s.cell('A',1)
-s.cell(1,'A')
-s.a1
+sheet.cell(1,1)
+sheet.cell('A',1)
+sheet.cell(1,'A')
+sheet.a1
# Access the second sheet's top-left cell.
-s.cell(1,'A',s.sheets[1])
+sheet.cell(1,'A',sheet.sheets[1])
```
#### Querying a spreadsheet
@@ -117,6 +117,12 @@ sheet.parse(id: /UPC|SKU/, qty: /ATS*\sATP\s*QTY\z/)
# => [{:id => 727880013358, :qty => 12}, ...]
```
+Use the ``:headers`` option to include the header row in the parsed content.
+
+```ruby
+sheet.parse(headers: true)
+```
+
Use the ``:header_search`` option to locate the header row and assign the header names.
```ruby
@@ -129,6 +135,16 @@ Use the ``:clean`` option to strip out control characters and surrounding white
sheet.parse(clean: true)
```
+#### Options
+
+When opening the file you can add a hash of options.
+
+##### expand_merged_ranges
+If you open a document with merged cells and do not want to end up with nil values for the rows after the first one.
+```ruby
+xlsx = Roo::Excelx.new('./roo_error.xlsx', {:expand_merged_ranges => true})
+```
+
### Exporting spreadsheets
Roo has the ability to export sheets using the following formats. It
will only export the ``default_sheet``.
@@ -230,7 +246,7 @@ ods.formula('A', 2)
```ruby
# Load a CSV file
-s = Roo::CSV.new("mycsv.csv")
+csv = Roo::CSV.new("mycsv.csv")
```
Because Roo uses the [standard CSV library](), you can use options available to that library to parse csv files. You can pass options using the ``csv_options`` key.
@@ -240,10 +256,10 @@ For instance, you can load tab-delimited files (``.tsv``), and you can use a par
```ruby
# Load a tab-delimited csv
-s = Roo::CSV.new("mytsv.tsv", csv_options: {col_sep: "\t"})
+csv = Roo::CSV.new("mytsv.tsv", csv_options: {col_sep: "\t"})
# Load a csv with an explicit encoding
-s = Roo::CSV.new("mycsv.csv", csv_options: {encoding: Encoding::ISO_8859_1})
+csv = Roo::CSV.new("mycsv.csv", csv_options: {encoding: Encoding::ISO_8859_1})
```
## Upgrading from Roo 1.13.x
@@ -272,9 +288,6 @@ You can run the tests/examples with Rspec like reporters by running
Roo also has a few tests that take a long time (5+ seconds). To run these, use
`LONG_RUN=true bundle exec rake`
-When testing using Ruby 2.0 or 2.1, use this command:
-`BUNDLE_GEMFILE=Gemfile_ruby2 bundle exec rake`
-
### Issues
If you find an issue, please create a gist and refer to it in an issue ([sample gist](https://gist.github.com/stevendaniels/98a05849036e99bb8b3c)). Here are some instructions for creating such a gist.
diff --git a/lib/roo.rb b/lib/roo.rb
index ec8eb42..add1e4a 100644
--- a/lib/roo.rb
+++ b/lib/roo.rb
@@ -1,3 +1,6 @@
+# frozen_string_literal: true
+
+require 'roo/version'
require 'roo/constants'
require 'roo/errors'
require 'roo/spreadsheet'
@@ -9,7 +12,7 @@ module Roo
autoload :Excelx, 'roo/excelx'
autoload :CSV, 'roo/csv'
- TEMP_PREFIX = 'roo_'.freeze
+ TEMP_PREFIX = 'roo_'
CLASS_FOR_EXTENSION = {
ods: Roo::OpenOffice,
diff --git a/lib/roo/base.rb b/lib/roo/base.rb
index 53e4075..19eb844 100644
--- a/lib/roo/base.rb
+++ b/lib/roo/base.rb
@@ -1,9 +1,7 @@
-# encoding: utf-8
-
-require 'tmpdir'
-require 'stringio'
-require 'nokogiri'
-require 'roo/utils'
+require "tmpdir"
+require "stringio"
+require "nokogiri"
+require "roo/utils"
require "roo/formatters/base"
require "roo/formatters/csv"
require "roo/formatters/matrix"
@@ -19,8 +17,8 @@ class Roo::Base
include Roo::Formatters::XML
include Roo::Formatters::YAML
- MAX_ROW_COL = 999_999.freeze
- MIN_ROW_COL = 0.freeze
+ MAX_ROW_COL = 999_999
+ MIN_ROW_COL = 0
attr_reader :headers
@@ -28,7 +26,7 @@ class Roo::Base
attr_accessor :header_line
def self.TEMP_PREFIX
- warn '[DEPRECATION] please access TEMP_PREFIX via Roo::TEMP_PREFIX'
+ warn "[DEPRECATION] please access TEMP_PREFIX via Roo::TEMP_PREFIX"
Roo::TEMP_PREFIX
end
@@ -56,6 +54,11 @@ class Roo::Base
if self.class.respond_to?(:finalize_tempdirs)
self.class.finalize_tempdirs(object_id)
end
+
+ instance_variables.each do |instance_variable|
+ instance_variable_set(instance_variable, nil)
+ end
+
nil
end
@@ -64,10 +67,10 @@ class Roo::Base
end
# sets the working sheet in the document
- # 'sheet' can be a number (1 = first sheet) or the name of a sheet.
+ # 'sheet' can be a number (0 = first sheet) or the name of a sheet.
def default_sheet=(sheet)
validate_sheet!(sheet)
- @default_sheet = sheet
+ @default_sheet = sheet.is_a?(String) ? sheet : sheets[sheet]
@first_row[sheet] = @last_row[sheet] = @first_column[sheet] = @last_column[sheet] = nil
@cells_read[sheet] = false
end
@@ -100,7 +103,7 @@ class Roo::Base
def collect_last_row_col_for_sheet(sheet)
first_row = first_column = MAX_ROW_COL
last_row = last_column = MIN_ROW_COL
- @cell[sheet].each_pair do|key, value|
+ @cell[sheet].each_pair do |key, value|
next unless value
first_row = [first_row, key.first.to_i].min
last_row = [last_row, key.first.to_i].max
@@ -110,13 +113,12 @@ class Roo::Base
{ first_row: first_row, first_column: first_column, last_row: last_row, last_column: last_column }
end
- %w(first_row last_row first_column last_column).each do |key|
- class_eval <<-EOS, __FILE__, __LINE__ + 1
- def #{key}(sheet = default_sheet) # def first_row(sheet = default_sheet)
- read_cells(sheet) # read_cells(sheet)
- @#{key}[sheet] ||= first_last_row_col_for_sheet(sheet)[:#{key}] # @first_row[sheet] ||= first_last_row_col_for_sheet(sheet)[:first_row]
- end # end
- EOS
+ %i(first_row last_row first_column last_column).each do |key|
+ ivar = "@#{key}".to_sym
+ define_method(key) do |sheet = default_sheet|
+ read_cells(sheet)
+ instance_variable_get(ivar)[sheet] ||= first_last_row_col_for_sheet(sheet)[key]
+ end
end
def inspect
@@ -203,16 +205,16 @@ class Roo::Base
"Number of sheets: #{sheets.size}\n"\
"Sheets: #{sheets.join(', ')}\n"
n = 1
- sheets.each do|sheet|
+ sheets.each do |sheet|
self.default_sheet = sheet
- result << 'Sheet ' + n.to_s + ":\n"
+ result << "Sheet " + n.to_s + ":\n"
if first_row
result << " First row: #{first_row}\n"
result << " Last row: #{last_row}\n"
result << " First column: #{::Roo::Utils.number_to_letter(first_column)}\n"
result << " Last column: #{::Roo::Utils.number_to_letter(last_column)}"
else
- result << ' - empty -'
+ result << " - empty -"
end
result << "\n" if sheet != sheets.last
n += 1
@@ -286,12 +288,12 @@ class Roo::Base
clean_sheet_if_need(options)
search_or_set_header(options)
headers = @headers ||
- Hash[(first_column..last_column).map do |col|
- [cell(@header_line, col), col]
- end]
+ (first_column..last_column).each_with_object({}) do |col, hash|
+ hash[cell(@header_line, col)] = col
+ end
@header_line.upto(last_row) do |line|
- yield(Hash[headers.map { |k, v| [k, cell(line, v)] }])
+ yield(headers.each_with_object({}) { |(k, v), hash| hash[k] = cell(line, v) })
end
end
end
@@ -306,18 +308,22 @@ class Roo::Base
def row_with(query, return_headers = false)
line_no = 0
+ closest_mismatched_headers = []
each do |row|
line_no += 1
headers = query.map { |q| row.grep(q)[0] }.compact
-
if headers.length == query.length
@header_line = line_no
return return_headers ? headers : line_no
- elsif line_no > 100
- raise Roo::HeaderRowNotFoundError
+ else
+ closest_mismatched_headers = headers if headers.length > closest_mismatched_headers.length
+ if line_no > 100
+ break
+ end
end
end
- raise Roo::HeaderRowNotFoundError
+ missing_headers = query.select { |q| closest_mismatched_headers.grep(q).empty? }
+ raise Roo::HeaderRowNotFoundError, missing_headers
end
protected
@@ -330,7 +336,7 @@ class Roo::Base
filename = File.basename(filename, File.extname(filename))
end
- if uri?(filename) && (qs_begin = filename.rindex('?'))
+ if uri?(filename) && (qs_begin = filename.rindex("?"))
filename = filename[0..qs_begin - 1]
end
exts = Array(exts)
@@ -356,7 +362,7 @@ class Roo::Base
# Diese Methode ist eine temp. Loesung, um zu erforschen, ob der
# Zugriff mit numerischen Keys schneller ist.
def key_to_num(str)
- r, c = str.split(',')
+ r, c = str.split(",")
[r.to_i, c.to_i]
end
@@ -418,9 +424,9 @@ class Roo::Base
def find_by_conditions(options)
rows = first_row.upto(last_row)
- header_for = Hash[1.upto(last_column).map do |col|
- [col, cell(@header_line, col)]
- end]
+ header_for = 1.upto(last_column).each_with_object({}) do |col, hash|
+ hash[col] = cell(@header_line, col)
+ end
# are all conditions met?
conditions = options[:conditions]
@@ -435,9 +441,9 @@ class Roo::Base
rows.map { |i| row(i) }
else
rows.map do |i|
- Hash[1.upto(row(i).size).map do |j|
- [header_for.fetch(j), cell(i, j)]
- end]
+ 1.upto(row(i).size).each_with_object({}) do |j, hash|
+ hash[header_for.fetch(j)] = cell(i, j)
+ end
end
end
end
@@ -455,7 +461,7 @@ class Roo::Base
def find_basename(filename)
if uri?(filename)
- require 'uri'
+ require "uri"
uri = URI.parse filename
File.basename(uri.path)
elsif !is_stream?(filename)
@@ -464,9 +470,9 @@ class Roo::Base
end
def make_tmpdir(prefix = nil, root = nil, &block)
- warn '[DEPRECATION] extend Roo::Tempdir and use its .make_tempdir instead'
+ warn "[DEPRECATION] extend Roo::Tempdir and use its .make_tempdir instead"
prefix = "#{Roo::TEMP_PREFIX}#{prefix}"
- root ||= ENV['ROO_TMP']
+ root ||= ENV["ROO_TMP"]
if block_given?
# folder is deleted at end of block
@@ -485,14 +491,17 @@ class Roo::Base
end
def sanitize_value(v)
- v.gsub(/[[:cntrl:]]|^[\p{Space}]+|[\p{Space}]+$/, '')
+ v.gsub(/[[:cntrl:]]|^[\p{Space}]+|[\p{Space}]+$/, "")
end
def set_headers(hash = {})
# try to find header row with all values or give an error
# then create new hash by indexing strings and keeping integers for header array
- @headers = row_with(hash.values, true)
- @headers = Hash[hash.keys.zip(@headers.map { |x| header_index(x) })]
+ header_row = row_with(hash.values, true)
+ @headers = {}
+ hash.each_with_index do |(key, _), index|
+ @headers[key] = header_index(header_row[index])
+ end
end
def header_index(query)
@@ -525,17 +534,17 @@ class Roo::Base
end
def uri?(filename)
- filename.start_with?('http://', 'https://', 'ftp://')
+ filename.start_with?("http://", "https://", "ftp://")
rescue
false
end
def download_uri(uri, tmpdir)
- require 'open-uri'
+ require "open-uri"
tempfilename = File.join(tmpdir, find_basename(uri))
begin
- File.open(tempfilename, 'wb') do |file|
- open(uri, 'User-Agent' => "Ruby/#{RUBY_VERSION}") do |net|
+ File.open(tempfilename, "wb") do |file|
+ open(uri, "User-Agent" => "Ruby/#{RUBY_VERSION}") do |net|
file.write(net.read)
end
end
@@ -546,15 +555,15 @@ class Roo::Base
end
def open_from_stream(stream, tmpdir)
- tempfilename = File.join(tmpdir, 'spreadsheet')
- File.open(tempfilename, 'wb') do |file|
+ tempfilename = File.join(tmpdir, "spreadsheet")
+ File.open(tempfilename, "wb") do |file|
file.write(stream[7..-1])
end
- File.join(tmpdir, 'spreadsheet')
+ File.join(tmpdir, "spreadsheet")
end
def unzip(filename, tmpdir)
- require 'zip/filesystem'
+ require "zip/filesystem"
Zip::File.open(filename) do |zip|
process_zipfile_packed(zip, tmpdir)
@@ -567,7 +576,7 @@ class Roo::Base
when nil
fail ArgumentError, "Error: sheet 'nil' not valid"
when Integer
- sheets.fetch(sheet - 1) do
+ sheets.fetch(sheet) do
fail RangeError, "sheet index #{sheet} not found"
end
when String
@@ -579,16 +588,16 @@ class Roo::Base
end
end
- def process_zipfile_packed(zip, tmpdir, path = '')
+ def process_zipfile_packed(zip, tmpdir, path = "")
if zip.file.file? path
# extract and return filename
- File.open(File.join(tmpdir, path), 'wb') do |file|
+ File.open(File.join(tmpdir, path), "wb") do |file|
file.write(zip.read(path))
end
File.join(tmpdir, path)
else
ret = nil
- path += '/' unless path.empty?
+ path += "/" unless path.empty?
zip.dir.foreach(path) do |filename|
ret = process_zipfile_packed(zip, tmpdir, path + filename)
end
diff --git a/lib/roo/constants.rb b/lib/roo/constants.rb
index 90d54ee..1ae5ca7 100644
--- a/lib/roo/constants.rb
+++ b/lib/roo/constants.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
module Roo
- ROO_EXCEL_NOTICE = "Excel support has been extracted to roo-xls due to its dependency on the GPL'd spreadsheet gem. Install roo-xls to use Roo::Excel.".freeze
- ROO_EXCELML_NOTICE = "Excel SpreadsheetML support has been extracted to roo-xls. Install roo-xls to use Roo::Excel2003XML.".freeze
- ROO_GOOGLE_NOTICE = "Google support has been extracted to roo-google. Install roo-google to use Roo::Google.".freeze
+ ROO_EXCEL_NOTICE = "Excel support has been extracted to roo-xls due to its dependency on the GPL'd spreadsheet gem. Install roo-xls to use Roo::Excel."
+ ROO_EXCELML_NOTICE = "Excel SpreadsheetML support has been extracted to roo-xls. Install roo-xls to use Roo::Excel2003XML."
+ ROO_GOOGLE_NOTICE = "Google support has been extracted to roo-google. Install roo-google to use Roo::Google."
end \ No newline at end of file
diff --git a/lib/roo/csv.rb b/lib/roo/csv.rb
index c161c64..516def6 100644
--- a/lib/roo/csv.rb
+++ b/lib/roo/csv.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "csv"
require "time"
@@ -63,25 +65,31 @@ module Roo
def read_cells(sheet = default_sheet)
sheet ||= default_sheet
return if @cells_read[sheet]
- set_row_count(sheet)
- set_column_count(sheet)
- row_num = 1
+ row_num = 0
+ max_col_num = 0
each_row csv_options do |row|
- row.each_with_index do |elem, col_num|
- coordinate = [row_num, col_num + 1]
+ row_num += 1
+ col_num = 0
+
+ row.each do |elem|
+ col_num += 1
+ coordinate = [row_num, col_num]
@cell[coordinate] = elem
@cell_type[coordinate] = celltype_class(elem)
end
- row_num += 1
+
+ max_col_num = col_num if col_num > max_col_num
end
+ set_row_count(sheet, row_num)
+ set_column_count(sheet, max_col_num)
@cells_read[sheet] = true
end
def each_row(options, &block)
if uri?(filename)
- each_row_using_temp_dir(filename)
+ each_row_using_tempdir(options, &block)
elsif is_stream?(filename_or_stream)
::CSV.new(filename_or_stream, options).each(&block)
else
@@ -89,24 +97,24 @@ module Roo
end
end
- def each_row_using_tempdir
+ def each_row_using_tempdir(options, &block)
::Dir.mktmpdir(Roo::TEMP_PREFIX, ENV["ROO_TMP"]) do |tmpdir|
tmp_filename = download_uri(filename, tmpdir)
::CSV.foreach(tmp_filename, options, &block)
end
end
- def set_row_count(sheet)
+ def set_row_count(sheet, last_row)
@first_row[sheet] = 1
- @last_row[sheet] = ::CSV.readlines(@filename, csv_options).size
+ @last_row[sheet] = last_row
@last_row[sheet] = @first_row[sheet] if @last_row[sheet].zero?
nil
end
- def set_column_count(sheet)
+ def set_column_count(sheet, last_col)
@first_column[sheet] = 1
- @last_column[sheet] = (::CSV.readlines(@filename, csv_options).first || []).size
+ @last_column[sheet] = last_col
@last_column[sheet] = @first_column[sheet] if @last_column[sheet].zero?
nil
diff --git a/lib/roo/excelx.rb b/lib/roo/excelx.rb
index 82c1431..f9f0ee2 100644..100755
--- a/lib/roo/excelx.rb
+++ b/lib/roo/excelx.rb
@@ -24,8 +24,9 @@ module Roo
require 'roo/excelx/sheet_doc'
require 'roo/excelx/coordinate'
require 'roo/excelx/format'
+ require 'roo/excelx/images'
- delegate [:styles, :workbook, :shared_strings, :rels_files, :sheet_files, :comments_files] => :@shared
+ delegate [:styles, :workbook, :shared_strings, :rels_files, :sheet_files, :comments_files, :image_rels, :image_files] => :@shared
ExceedsMaxError = Class.new(StandardError)
# initialization and opening of a spreadsheet file
@@ -39,7 +40,10 @@ module Roo
sheet_options = {}
sheet_options[:expand_merged_ranges] = (options[:expand_merged_ranges] || false)
sheet_options[:no_hyperlinks] = (options[:no_hyperlinks] || false)
+ sheet_options[:empty_cell] = (options[:empty_cell] || false)
+ shared_options = {}
+ shared_options[:disable_html_wrapper] = (options[:disable_html_wrapper] || false)
unless is_stream?(filename_or_stream)
file_type_check(filename_or_stream, %w[.xlsx .xlsm], 'an Excel 2007', file_warning, packed)
basename = find_basename(filename_or_stream)
@@ -52,7 +56,7 @@ module Roo
@tmpdir = self.class.make_tempdir(self, basename, options[:tmpdir_root])
ObjectSpace.define_finalizer(self, self.class.finalize(object_id))
- @shared = Shared.new(@tmpdir)
+ @shared = Shared.new(@tmpdir, shared_options)
@filename = local_filename(filename_or_stream, @tmpdir, packed)
process_zipfile(@filename || filename_or_stream)
@@ -62,10 +66,10 @@ module Roo
end
end.compact
@sheets = []
- @sheets_by_name = Hash[@sheet_names.map.with_index do |sheet_name, n|
- @sheets[n] = Sheet.new(sheet_name, @shared, n, sheet_options)
- [sheet_name, @sheets[n]]
- end]
+ @sheets_by_name = {}
+ @sheet_names.each_with_index do |sheet_name, n|
+ @sheets_by_name[sheet_name] = @sheets[n] = Sheet.new(sheet_name, @shared, n, sheet_options)
+ end
if cell_max
cell_count = ::Roo::Utils.num_cells_in_range(sheet_for(options.delete(:sheet)).dimensions)
@@ -94,7 +98,12 @@ module Roo
def sheet_for(sheet)
sheet ||= default_sheet
validate_sheet!(sheet)
- @sheets_by_name[sheet]
+ @sheets_by_name[sheet] || @sheets[sheet]
+ end
+
+ def images(sheet = nil)
+ images_names = sheet_for(sheet).images.map(&:last)
+ images_names.map { |iname| image_files.find { |ifile| ifile[iname] } }
end
# Returns the content of a spreadsheet-cell.
@@ -325,7 +334,7 @@ module Roo
wb.extract(path)
workbook_doc = Roo::Utils.load_xml(path).remove_namespaces!
- workbook_doc.xpath('//sheet').map { |s| s.attributes['id'].value }
+ workbook_doc.xpath('//sheet').map { |s| s['id'] }
end
# Internal
@@ -349,17 +358,13 @@ module Roo
wb_rels.extract(path)
rels_doc = Roo::Utils.load_xml(path).remove_namespaces!
- worksheet_type = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet'
relationships = rels_doc.xpath('//Relationship').select do |relationship|
- relationship.attributes['Type'].value == worksheet_type
+ worksheet_types.include? relationship['Type']
end
- relationships.inject({}) do |hash, relationship|
- attributes = relationship.attributes
- id = attributes['Id']
- hash[id.value] = attributes['Target'].value
- hash
+ relationships.each_with_object({}) do |relationship, hash|
+ hash[relationship['Id']] = relationship['Target']
end
end
@@ -376,6 +381,15 @@ module Roo
end
end
+ def extract_images(entries, tmpdir)
+ img_entries = entries.select { |e| e.name[/media\/image([0-9]+)/] }
+ img_entries.each do |entry|
+ path = "#{@tmpdir}/roo#{entry.name.gsub(/xl\/|\//, "_")}"
+ image_files << path
+ entry.extract(path)
+ end
+ end
+
# Extracts all needed files from the zip file
def process_zipfile(zipfilename_or_stream)
@sheet_files = []
@@ -409,6 +423,7 @@ module Roo
sheet_ids = extract_worksheet_ids(entries, "#{@tmpdir}/roo_workbook.xml")
sheets = extract_worksheet_rels(entries, "#{@tmpdir}/roo_workbook.xml.rels")
extract_sheets_in_order(entries, sheet_ids, sheets, @tmpdir)
+ extract_images(entries, @tmpdir)
entries.each do |entry|
path =
@@ -435,6 +450,10 @@ module Roo
# drawings, etc.
nr = Regexp.last_match[1].to_i
rels_files[nr - 1] = "#{@tmpdir}/roo_rels#{nr}"
+ when /drawing([0-9]+).xml.rels$/
+ # Extracting drawing relationships to make images lists for each sheet
+ nr = Regexp.last_match[1].to_i
+ image_rels[nr - 1] = "#{@tmpdir}/roo_image_rels#{nr}"
end
entry.extract(path) if path
@@ -442,7 +461,14 @@ module Roo
end
def safe_send(object, method, *args)
- object.send(method, *args) if object && object.respond_to?(method)
+ object.send(method, *args) if object&.respond_to?(method)
+ end
+
+ def worksheet_types
+ [
+ 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet', # OOXML Transitional
+ 'http://purl.oclc.org/ooxml/officeDocument/relationships/worksheet' # OOXML Strict
+ ]
end
end
end
diff --git a/lib/roo/excelx/cell.rb b/lib/roo/excelx/cell.rb
index 2fc78e1..7abd074 100644
--- a/lib/roo/excelx/cell.rb
+++ b/lib/roo/excelx/cell.rb
@@ -40,19 +40,23 @@ module Roo
end
def self.create_cell(type, *values)
+ cell_class(type)&.new(*values)
+ end
+
+ def self.cell_class(type)
case type
when :string
- Cell::String.new(*values)
+ Cell::String
when :boolean
- Cell::Boolean.new(*values)
+ Cell::Boolean
when :number
- Cell::Number.new(*values)
+ Cell::Number
when :date
- Cell::Date.new(*values)
+ Cell::Date
when :datetime
- Cell::DateTime.new(*values)
+ Cell::DateTime
when :time
- Cell::Time.new(*values)
+ Cell::Time
end
end
diff --git a/lib/roo/excelx/cell/base.rb b/lib/roo/excelx/cell/base.rb
index aea8808..51fc75f 100644
--- a/lib/roo/excelx/cell/base.rb
+++ b/lib/roo/excelx/cell/base.rb
@@ -1,13 +1,18 @@
+# frozen_string_literal: true
+
+require "roo/helpers/default_attr_reader"
+
module Roo
class Excelx
class Cell
class Base
+ extend Roo::Helpers::DefaultAttrReader
attr_reader :cell_type, :cell_value, :value
# FIXME: I think style should be deprecated. Having a style attribute
# for a cell doesn't really accomplish much. It seems to be used
# when you want to export to excelx.
- attr_reader :style
+ attr_reader_with_default default_type: :base, style: 1
# FIXME: Updating a cell's value should be able tochange the cell's type,
@@ -34,14 +39,12 @@ module Roo
attr_writer :value
def initialize(value, formula, excelx_type, style, link, coordinate)
- @link = !!link
@cell_value = value
- @cell_type = excelx_type
- @formula = formula
- @style = style
+ @cell_type = excelx_type if excelx_type
+ @formula = formula if formula
+ @style = style unless style == 1
@coordinate = coordinate
- @type = :base
- @value = link? ? Roo::Link.new(link, value) : value
+ @value = link ? Roo::Link.new(link, value) : value
end
def type
@@ -50,16 +53,16 @@ module Roo
elsif link?
:link
else
- @type
+ default_type
end
end
def formula?
- !!@formula
+ !!(defined?(@formula) && @formula)
end
def link?
- !!@link
+ Roo::Link === @value
end
alias_method :formatted_value, :value
@@ -68,9 +71,16 @@ module Roo
formatted_value
end
- # DEPRECATED: Please use link instead.
+ # DEPRECATED: Please use link? instead.
def hyperlink
- warn '[DEPRECATION] `hyperlink` is deprecated. Please use `link` instead.'
+ warn '[DEPRECATION] `hyperlink` is deprecated. Please use `link?` instead.'
+ link?
+ end
+
+ # DEPRECATED: Please use link? instead.
+ def link
+ warn '[DEPRECATION] `link` is deprecated. Please use `link?` instead.'
+ link?
end
# DEPRECATED: Please use cell_value instead.
@@ -88,6 +98,10 @@ module Roo
def empty?
false
end
+
+ def presence
+ empty? ? nil : self
+ end
end
end
end
diff --git a/lib/roo/excelx/cell/boolean.rb b/lib/roo/excelx/cell/boolean.rb
index fe1f691..2cdfc22 100644
--- a/lib/roo/excelx/cell/boolean.rb
+++ b/lib/roo/excelx/cell/boolean.rb
@@ -1,17 +1,20 @@
+# frozen_string_literal: true
+
module Roo
class Excelx
class Cell
class Boolean < Cell::Base
- attr_reader :value, :formula, :format, :cell_type, :cell_value, :link, :coordinate
+ attr_reader :value, :formula, :format, :cell_value, :coordinate
+
+ attr_reader_with_default default_type: :boolean, cell_type: :boolean
def initialize(value, formula, style, link, coordinate)
- super(value, formula, nil, style, link, coordinate)
- @type = @cell_type = :boolean
- @value = link? ? Roo::Link.new(link, value) : create_boolean(value)
+ super(value, formula, nil, style, nil, coordinate)
+ @value = link ? Roo::Link.new(link, value) : create_boolean(value)
end
def formatted_value
- value ? 'TRUE'.freeze : 'FALSE'.freeze
+ value ? 'TRUE' : 'FALSE'
end
private
@@ -19,7 +22,7 @@ module Roo
def create_boolean(value)
# FIXME: Using a boolean will cause methods like Base#to_csv to fail.
# Roo is using some method to ignore false/nil values.
- value.to_i == 1 ? true : false
+ value.to_i == 1
end
end
end
diff --git a/lib/roo/excelx/cell/date.rb b/lib/roo/excelx/cell/date.rb
index 8e2c6cb..8627bc5 100644
--- a/lib/roo/excelx/cell/date.rb
+++ b/lib/roo/excelx/cell/date.rb
@@ -4,23 +4,23 @@ module Roo
class Excelx
class Cell
class Date < Roo::Excelx::Cell::DateTime
- attr_reader :value, :formula, :format, :cell_type, :cell_value, :link, :coordinate
+ attr_reader :value, :formula, :format, :cell_type, :cell_value, :coordinate
+
+ attr_reader_with_default default_type: :date
def initialize(value, formula, excelx_type, style, link, base_date, coordinate)
# NOTE: Pass all arguments to the parent class, DateTime.
super
- @type = :date
@format = excelx_type.last
- @value = link? ? Roo::Link.new(link, value) : create_date(base_date, value)
+ @value = link ? Roo::Link.new(link, value) : create_date(base_date, value)
end
private
- def create_date(base_date, value)
- date = base_date + value.to_i
- yyyy, mm, dd = date.strftime('%Y-%m-%d').split('-')
+ def create_datetime(_,_); end
- ::Date.new(yyyy.to_i, mm.to_i, dd.to_i)
+ def create_date(base_date, value)
+ base_date + value.to_i
end
end
end
diff --git a/lib/roo/excelx/cell/datetime.rb b/lib/roo/excelx/cell/datetime.rb
index 35d93ac..63f3260 100644
--- a/lib/roo/excelx/cell/datetime.rb
+++ b/lib/roo/excelx/cell/datetime.rb
@@ -1,16 +1,21 @@
+# frozen_string_literal: true
+
require 'date'
module Roo
class Excelx
class Cell
class DateTime < Cell::Base
- attr_reader :value, :formula, :format, :cell_value, :link, :coordinate
+ SECONDS_IN_DAY = 60 * 60 * 24
+
+ attr_reader :value, :formula, :format, :cell_value, :coordinate
- def initialize(value, formula, excelx_type, style, link, base_date, coordinate)
- super(value, formula, excelx_type, style, link, coordinate)
- @type = :datetime
+ attr_reader_with_default default_type: :datetime
+
+ def initialize(value, formula, excelx_type, style, link, base_timestamp, coordinate)
+ super(value, formula, excelx_type, style, nil, coordinate)
@format = excelx_type.last
- @value = link? ? Roo::Link.new(link, value) : create_datetime(base_date, value)
+ @value = link ? Roo::Link.new(link, value) : create_datetime(base_timestamp, value)
end
# Public: Returns formatted value for a datetime. Format's can be an
@@ -78,7 +83,7 @@ module Roo
TIME_FORMATS = {
'hh' => '%H', # Hour (24): 01
- 'h' => '%-k'.freeze, # Hour (24): 1
+ 'h' => '%-k', # Hour (24): 1
# 'hh'.freeze => '%I'.freeze, # Hour (12): 08
# 'h'.freeze => '%-l'.freeze, # Hour (12): 8
'mm' => '%M', # Minute: 01
@@ -92,18 +97,9 @@ module Roo
'0' => '%1N' # Fractional Seconds: tenths.
}
- def create_datetime(base_date, value)
- date = base_date + value.to_f.round(6)
- datetime_string = date.strftime('%Y-%m-%d %H:%M:%S.%N')
- t = round_datetime(datetime_string)
-
- ::DateTime.civil(t.year, t.month, t.day, t.hour, t.min, t.sec)
- end
-
- def round_datetime(datetime_string)
- /(?<yyyy>\d+)-(?<mm>\d+)-(?<dd>\d+) (?<hh>\d+):(?<mi>\d+):(?<ss>\d+.\d+)/ =~ datetime_string
-
- ::Time.new(yyyy, mm, dd, hh, mi, ss.to_r).round(0)
+ def create_datetime(base_timestamp, value)
+ timestamp = (base_timestamp + (value.to_f.round(6) * SECONDS_IN_DAY)).round(0)
+ ::Time.at(timestamp).utc.to_datetime
end
end
end
diff --git a/lib/roo/excelx/cell/empty.rb b/lib/roo/excelx/cell/empty.rb
index 49a20e7..f0c683c 100644
--- a/lib/roo/excelx/cell/empty.rb
+++ b/lib/roo/excelx/cell/empty.rb
@@ -3,10 +3,11 @@ module Roo
class Excelx
class Cell
class Empty < Cell::Base
- attr_reader :value, :formula, :format, :cell_type, :cell_value, :hyperlink, :coordinate
+ attr_reader :value, :formula, :format, :cell_type, :cell_value, :coordinate
+
+ attr_reader_with_default default_type: nil, style: nil
def initialize(coordinate)
- @value = @formula = @format = @cell_type = @cell_value = @hyperlink = nil
@coordinate = coordinate
end
diff --git a/lib/roo/excelx/cell/number.rb b/lib/roo/excelx/cell/number.rb
index 2015562..9f23c4f 100644
--- a/lib/roo/excelx/cell/number.rb
+++ b/lib/roo/excelx/cell/number.rb
@@ -1,16 +1,19 @@
+# frozen_string_literal: true
+
module Roo
class Excelx
class Cell
class Number < Cell::Base
- attr_reader :value, :formula, :format, :cell_value, :link, :coordinate
+ attr_reader :value, :formula, :format, :cell_value, :coordinate
+
+ # FIXME: change default_type to number. This will break brittle tests.
+ attr_reader_with_default default_type: :float
def initialize(value, formula, excelx_type, style, link, coordinate)
super
- # FIXME: change @type to number. This will break brittle tests.
# FIXME: Excelx_type is an array, but the first value isn't used.
- @type = :float
@format = excelx_type.last
- @value = link? ? Roo::Link.new(link, value) : create_numeric(value)
+ @value = link ? Roo::Link.new(link, value) : create_numeric(value)
end
def create_numeric(number)
@@ -21,48 +24,50 @@ module Roo
when /\.0/
Float(number)
else
- (number.include?('.') || (/\A[-+]?\d+E[-+]\d+\z/i =~ number)) ? Float(number) : Integer(number)
+ (number.include?('.') || (/\A[-+]?\d+E[-+]?\d+\z/i =~ number)) ? Float(number) : Integer(number, 10)
end
end
def formatted_value
return @cell_value if Excelx::ERROR_VALUES.include?(@cell_value)
- formatter = formats[@format]
+ formatter = generate_formatter(@format)
if formatter.is_a? Proc
formatter.call(@cell_value)
- elsif zero_padded_number?
- "%0#{@format.size}d" % @cell_value
else
Kernel.format(formatter, @cell_value)
end
end
- def formats
+ def generate_formatter(format)
# FIXME: numbers can be other colors besides red:
# [BLACK], [BLUE], [CYAN], [GREEN], [MAGENTA], [RED], [WHITE], [YELLOW], [COLOR n]
- {
- 'General' => '%.0f',
- '0' => '%.0f',
- '0.00' => '%.2f',
- '0.000000' => '%.6f',
- '#,##0' => number_format('%.0f'),
- '#,##0.00' => number_format('%.2f'),
- '0%' => proc do |number|
- Kernel.format('%d%', number.to_f * 100)
- end,
- '0.00%' => proc do |number|
- Kernel.format('%.2f%', number.to_f * 100)
- end,
- '0.00E+00' => '%.2E',
- '#,##0 ;(#,##0)' => number_format('%.0f', '(%.0f)'),
- '#,##0 ;[Red](#,##0)' => number_format('%.0f', '[Red](%.0f)'),
- '#,##0.00;(#,##0.00)' => number_format('%.2f', '(%.2f)'),
- '#,##0.00;[Red](#,##0.00)' => number_format('%.2f', '[Red](%.2f)'),
+ case format
+ when /^General$/i then '%.0f'
+ when '0' then '%.0f'
+ when /^(0+)$/ then "%0#{$1.size}d"
+ when /^0\.(0+)$/ then "%.#{$1.size}f"
+ when '#,##0' then number_format('%.0f')
+ when '#,##0.00' then number_format('%.2f')
+ when '0%'
+ proc do |number|
+ Kernel.format('%d%%', number.to_f * 100)
+ end
+ when '0.00%'
+ proc do |number|
+ Kernel.format('%.2f%%', number.to_f * 100)
+ end
+ when '0.00E+00' then '%.2E'
+ when '#,##0 ;(#,##0)' then number_format('%.0f', '(%.0f)')
+ when '#,##0 ;[Red](#,##0)' then number_format('%.0f', '[Red](%.0f)')
+ when '#,##0.00;(#,##0.00)' then number_format('%.2f', '(%.2f)')
+ when '#,##0.00;[Red](#,##0.00)' then number_format('%.2f', '[Red](%.2f)')
# FIXME: not quite sure what the format should look like in this case.
- '##0.0E+0' => '%.1E',
- '@' => proc { |number| number }
- }
+ when '##0.0E+0' then '%.1E'
+ when '@' then proc { |number| number }
+ else
+ raise "Unknown format: #{format.inspect}"
+ end
end
private
@@ -77,10 +82,6 @@ module Roo
Kernel.format(formatter, number).reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
end
end
-
- def zero_padded_number?
- @format[/0+/] == @format
- end
end
end
end
diff --git a/lib/roo/excelx/cell/string.rb b/lib/roo/excelx/cell/string.rb
index 7967806..dacf0b6 100644
--- a/lib/roo/excelx/cell/string.rb
+++ b/lib/roo/excelx/cell/string.rb
@@ -2,12 +2,12 @@ module Roo
class Excelx
class Cell
class String < Cell::Base
- attr_reader :value, :formula, :format, :cell_type, :cell_value, :link, :coordinate
+ attr_reader :value, :formula, :format, :cell_value, :coordinate
+
+ attr_reader_with_default default_type: :string, cell_type: :string
def initialize(value, formula, style, link, coordinate)
super(value, formula, nil, style, link, coordinate)
- @type = @cell_type = :string
- @value = link? ? Roo::Link.new(link, value) : value
end
def empty?
diff --git a/lib/roo/excelx/cell/time.rb b/lib/roo/excelx/cell/time.rb
index d661ab8..a1f0864 100644
--- a/lib/roo/excelx/cell/time.rb
+++ b/lib/roo/excelx/cell/time.rb
@@ -4,15 +4,16 @@ module Roo
class Excelx
class Cell
class Time < Roo::Excelx::Cell::DateTime
- attr_reader :value, :formula, :format, :cell_value, :link, :coordinate
+ attr_reader :value, :formula, :format, :cell_value, :coordinate
+
+ attr_reader_with_default default_type: :time
def initialize(value, formula, excelx_type, style, link, base_date, coordinate)
# NOTE: Pass all arguments to DateTime super class.
super
- @type = :time
@format = excelx_type.last
@datetime = create_datetime(base_date, value)
- @value = link? ? Roo::Link.new(link, value) : (value.to_f * 86_400).to_i
+ @value = link ? Roo::Link.new(link, value) : (value.to_f * 86_400).to_i
end
def formatted_value
diff --git a/lib/roo/excelx/comments.rb b/lib/roo/excelx/comments.rb
index 1a89908..65044a9 100644
--- a/lib/roo/excelx/comments.rb
+++ b/lib/roo/excelx/comments.rb
@@ -12,10 +12,10 @@ module Roo
def extract_comments
return {} unless doc_exists?
- Hash[doc.xpath('//comments/commentList/comment').map do |comment|
+ doc.xpath('//comments/commentList/comment').each_with_object({}) do |comment, hash|
value = (comment.at_xpath('./text/r/t') || comment.at_xpath('./text/t')).text
- [::Roo::Utils.ref_to_key(comment.attributes['ref'].to_s), value]
- end]
+ hash[::Roo::Utils.ref_to_key(comment['ref'].to_s)] = value
+ end
end
end
end
diff --git a/lib/roo/excelx/coordinate.rb b/lib/roo/excelx/coordinate.rb
index 53b24ba..4f61b17 100644
--- a/lib/roo/excelx/coordinate.rb
+++ b/lib/roo/excelx/coordinate.rb
@@ -1,11 +1,18 @@
module Roo
class Excelx
- class Coordinate
- attr_accessor :row, :column
+ class Coordinate < ::Array
def initialize(row, column)
- @row = row
- @column = column
+ super() << row << column
+ freeze
+ end
+
+ def row
+ self[0]
+ end
+
+ def column
+ self[1]
end
end
end
diff --git a/lib/roo/excelx/extractor.rb b/lib/roo/excelx/extractor.rb
index 1cdd13b..b87a84e 100644..100755
--- a/lib/roo/excelx/extractor.rb
+++ b/lib/roo/excelx/extractor.rb
@@ -1,16 +1,34 @@
+# frozen_string_literal: true
+
+require "roo/helpers/weak_instance_cache"
+
module Roo
class Excelx
class Extractor
- def initialize(path)
+ include Roo::Helpers::WeakInstanceCache
+
+ COMMON_STRINGS = {
+ t: "t",
+ r: "r",
+ s: "s",
+ ref: "ref",
+ html_tag_open: "<html>",
+ html_tag_closed: "</html>"
+ }
+
+ def initialize(path, options = {})
@path = path
+ @options = options
end
private
def doc
- raise FileNotFound, "#{@path} file not found" unless doc_exists?
+ instance_cache(:@doc) do
+ raise FileNotFound, "#{@path} file not found" unless doc_exists?
- ::Roo::Utils.load_xml(@path).remove_namespaces!
+ ::Roo::Utils.load_xml(@path).remove_namespaces!
+ end
end
def doc_exists?
diff --git a/lib/roo/excelx/format.rb b/lib/roo/excelx/format.rb
index 72b36d9..1c1968a 100644
--- a/lib/roo/excelx/format.rb
+++ b/lib/roo/excelx/format.rb
@@ -1,49 +1,57 @@
+# frozen_string_literal: true
+
module Roo
class Excelx
module Format
+ extend self
EXCEPTIONAL_FORMATS = {
'h:mm am/pm' => :date,
'h:mm:ss am/pm' => :date
}
STANDARD_FORMATS = {
- 0 => 'General'.freeze,
- 1 => '0'.freeze,
- 2 => '0.00'.freeze,
- 3 => '#,##0'.freeze,
- 4 => '#,##0.00'.freeze,
- 9 => '0%'.freeze,
- 10 => '0.00%'.freeze,
- 11 => '0.00E+00'.freeze,
- 12 => '# ?/?'.freeze,
- 13 => '# ??/??'.freeze,
- 14 => 'mm-dd-yy'.freeze,
- 15 => 'd-mmm-yy'.freeze,
- 16 => 'd-mmm'.freeze,
- 17 => 'mmm-yy'.freeze,
- 18 => 'h:mm AM/PM'.freeze,
- 19 => 'h:mm:ss AM/PM'.freeze,
- 20 => 'h:mm'.freeze,
- 21 => 'h:mm:ss'.freeze,
- 22 => 'm/d/yy h:mm'.freeze,
- 37 => '#,##0 ;(#,##0)'.freeze,
- 38 => '#,##0 ;[Red](#,##0)'.freeze,
- 39 => '#,##0.00;(#,##0.00)'.freeze,
- 40 => '#,##0.00;[Red](#,##0.00)'.freeze,
- 45 => 'mm:ss'.freeze,
- 46 => '[h]:mm:ss'.freeze,
- 47 => 'mmss.0'.freeze,
- 48 => '##0.0E+0'.freeze,
- 49 => '@'.freeze
+ 0 => 'General',
+ 1 => '0',
+ 2 => '0.00',
+ 3 => '#,##0',
+ 4 => '#,##0.00',
+ 9 => '0%',
+ 10 => '0.00%',
+ 11 => '0.00E+00',
+ 12 => '# ?/?',
+ 13 => '# ??/??',
+ 14 => 'mm-dd-yy',
+ 15 => 'd-mmm-yy',
+ 16 => 'd-mmm',
+ 17 => 'mmm-yy',
+ 18 => 'h:mm AM/PM',
+ 19 => 'h:mm:ss AM/PM',
+ 20 => 'h:mm',
+ 21 => 'h:mm:ss',
+ 22 => 'm/d/yy h:mm',
+ 37 => '#,##0 ;(#,##0)',
+ 38 => '#,##0 ;[Red](#,##0)',
+ 39 => '#,##0.00;(#,##0.00)',
+ 40 => '#,##0.00;[Red](#,##0.00)',
+ 45 => 'mm:ss',
+ 46 => '[h]:mm:ss',
+ 47 => 'mmss.0',
+ 48 => '##0.0E+0',
+ 49 => '@'
}
def to_type(format)
+ @to_type ||= {}
+ @to_type[format] ||= _to_type(format)
+ end
+
+ def _to_type(format)
format = format.to_s.downcase
if (type = EXCEPTIONAL_FORMATS[format])
type
elsif format.include?('#')
:float
- elsif !format.match(/d+(?![\]])/).nil? || format.include?('y')
+ elsif format.include?('y') || !format.match(/d+(?![\]])/).nil?
if format.include?('h') || format.include?('s')
:datetime
else
@@ -58,7 +66,6 @@ module Roo
end
end
- module_function :to_type
end
- end
+ end
end
diff --git a/lib/roo/excelx/images.rb b/lib/roo/excelx/images.rb
new file mode 100644
index 0000000..cf0221f
--- /dev/null
+++ b/lib/roo/excelx/images.rb
@@ -0,0 +1,26 @@
+require 'roo/excelx/extractor'
+
+module Roo
+ class Excelx
+ class Images < Excelx::Extractor
+
+ # Returns: Hash { id1: extracted_file_name1 },
+ # Example: { "rId1"=>"roo_media_image1.png",
+ # "rId2"=>"roo_media_image2.png",
+ # "rId3"=>"roo_media_image3.png" }
+ def list
+ @images ||= extract_images_names
+ end
+
+ private
+
+ def extract_images_names
+ return {} unless doc_exists?
+
+ doc.xpath('/Relationships/Relationship').each_with_object({}) do |rel, hash|
+ hash[rel['Id']] = "roo" + rel['Target'].gsub(/\.\.\/|\//, '_')
+ end
+ end
+ end
+ end
+end
diff --git a/lib/roo/excelx/relationships.rb b/lib/roo/excelx/relationships.rb
index 8a0ed97..19f9919 100644
--- a/lib/roo/excelx/relationships.rb
+++ b/lib/roo/excelx/relationships.rb
@@ -16,9 +16,9 @@ module Roo
def extract_relationships
return [] unless doc_exists?
- Hash[doc.xpath('/Relationships/Relationship').map do |rel|
- [rel.attribute('Id').text, rel]
- end]
+ doc.xpath('/Relationships/Relationship').each_with_object({}) do |rel, hash|
+ hash[rel['Id']] = rel
+ end
end
end
end
diff --git a/lib/roo/excelx/shared.rb b/lib/roo/excelx/shared.rb
index 3677fa2..bcd2c08 100644..100755
--- a/lib/roo/excelx/shared.rb
+++ b/lib/roo/excelx/shared.rb
@@ -4,12 +4,15 @@ module Roo
# reduce memory usage and reduce the number of objects being passed
# to various inititializers.
class Shared
- attr_accessor :comments_files, :sheet_files, :rels_files
- def initialize(dir)
+ attr_accessor :comments_files, :sheet_files, :rels_files, :image_rels, :image_files
+ def initialize(dir, options = {})
@dir = dir
@comments_files = []
@sheet_files = []
@rels_files = []
+ @options = options
+ @image_rels = []
+ @image_files = []
end
def styles
@@ -17,7 +20,7 @@ module Roo
end
def shared_strings
- @shared_strings ||= SharedStrings.new(File.join(@dir, 'roo_sharedStrings.xml'))
+ @shared_strings ||= SharedStrings.new(File.join(@dir, 'roo_sharedStrings.xml'), @options)
end
def workbook
@@ -27,6 +30,10 @@ module Roo
def base_date
workbook.base_date
end
+
+ def base_timestamp
+ workbook.base_timestamp
+ end
end
end
end
diff --git a/lib/roo/excelx/shared_strings.rb b/lib/roo/excelx/shared_strings.rb
index f7caf7c..e70b623 100755
--- a/lib/roo/excelx/shared_strings.rb
+++ b/lib/roo/excelx/shared_strings.rb
@@ -1,16 +1,10 @@
+# frozen_string_literal: true
+
require 'roo/excelx/extractor'
module Roo
class Excelx
class SharedStrings < Excelx::Extractor
-
- COMMON_STRINGS = {
- t: "t",
- r: "r",
- html_tag_open: "<html>",
- html_tag_closed: "</html>"
- }
-
def [](index)
to_a[index]
end
@@ -26,6 +20,7 @@ module Roo
# Use to_html or to_a for html returns
# See what is happening with commit???
def use_html?(index)
+ return false if @options[:disable_html_wrapper]
to_html[index][/<([biu]|sup|sub)>/]
end
@@ -45,7 +40,7 @@ module Roo
document = fix_invalid_shared_strings(doc)
# read the shared strings xml document
document.xpath('/sst/si').map do |si|
- shared_string = ''
+ shared_string = +""
si.children.each do |elem|
case elem.name
when 'r'
@@ -65,7 +60,7 @@ module Roo
fix_invalid_shared_strings(doc)
# read the shared strings xml document
doc.xpath('/sst/si').map do |si|
- html_string = '<html>'
+ html_string = '<html>'.dup
si.children.each do |elem|
case elem.name
when 'r'
@@ -95,7 +90,7 @@ module Roo
#
# Expected Output ::: "<html><sub|sup><b><i><u>TEXT</u></i></b></sub|/sup></html>"
def extract_html_r(r_elem)
- str = ''
+ str = +""
xml_elems = {
sub: false,
sup: false,
@@ -103,7 +98,6 @@ module Roo
i: false,
u: false
}
- b, i, u, sub, sup = false, false, false, false, false
r_elem.children.each do |elem|
case elem.name
when 'rPr'
@@ -141,13 +135,13 @@ module Roo
# This will return an html string
def create_html(text, formatting)
- tmp_str = ''
+ tmp_str = +""
formatting.each do |elem, val|
tmp_str << "<#{elem}>" if val
end
tmp_str << text
- reverse_format = Hash[formatting.to_a.reverse]
- reverse_format.each do |elem, val|
+
+ formatting.reverse_each do |elem, val|
tmp_str << "</#{elem}>" if val
end
tmp_str
diff --git a/lib/roo/excelx/sheet.rb b/lib/roo/excelx/sheet.rb
index add92f0..840a053 100644
--- a/lib/roo/excelx/sheet.rb
+++ b/lib/roo/excelx/sheet.rb
@@ -4,11 +4,15 @@ module Roo
class Sheet
extend Forwardable
- delegate [:styles, :workbook, :shared_strings, :rels_files, :sheet_files, :comments_files] => :@shared
+ delegate [:styles, :workbook, :shared_strings, :rels_files, :sheet_files, :comments_files, :image_rels] => :@shared
+
+ attr_reader :images
def initialize(name, shared, sheet_index, options = {})
@name = name
@shared = shared
+ @sheet_index = sheet_index
+ @images = Images.new(image_rels[sheet_index]).list
@rels = Relationships.new(rels_files[sheet_index])
@comments = Comments.new(comments_files[sheet_index])
@sheet = SheetDoc.new(sheet_files[sheet_index], @rels, shared, options)
@@ -19,7 +23,14 @@ module Roo
end
def present_cells
- @present_cells ||= cells.select { |_, cell| cell && !cell.empty? }
+ @present_cells ||= begin
+ warn %{
+[DEPRECATION] present_cells is deprecated. Alternate:
+ with activesupport => cells[key].presence
+ without activesupport => cells[key]&.presence
+ }
+ cells.select { |_, cell| cell&.presence }
+ end
end
# Yield each row as array of Excelx::Cell objects
@@ -39,33 +50,33 @@ module Roo
def row(row_number)
first_column.upto(last_column).map do |col|
- cells[[row_number, col]]
- end.map { |cell| cell && cell.value }
+ cells[[row_number, col]]&.value
+ end
end
def column(col_number)
first_row.upto(last_row).map do |row|
- cells[[row, col_number]]
- end.map { |cell| cell && cell.value }
+ cells[[row, col_number]]&.value
+ end
end
# returns the number of the first non-empty row
def first_row
- @first_row ||= present_cells.keys.map { |row, _| row }.min
+ @first_row ||= first_last_row_col[:first_row]
end
def last_row
- @last_row ||= present_cells.keys.map { |row, _| row }.max
+ @last_row ||= first_last_row_col[:last_row]
end
# returns the number of the first non-empty column
def first_column
- @first_column ||= present_cells.keys.map { |_, col| col }.min
+ @first_column ||= first_last_row_col[:first_column]
end
# returns the number of the last non-empty column
def last_column
- @last_column ||= present_cells.keys.map { |_, col| col }.max
+ @last_column ||= first_last_row_col[:last_column]
end
def excelx_format(key)
@@ -107,6 +118,34 @@ module Roo
(cell.coordinate.column - 1 - last_column).times { pad << nil }
pad
end
+
+ def first_last_row_col
+ @first_last_row_col ||= begin
+ first_row = last_row = first_col = last_col = nil
+
+ cells.each do |(row, col), cell|
+ next unless cell&.presence
+ first_row ||= row
+ last_row ||= row
+ first_col ||= col
+ last_col ||= col
+
+ if row > last_row
+ last_row = row
+ elsif row < first_row
+ first_row = row
+ end
+
+ if col > last_col
+ last_col = col
+ elsif col < first_col
+ first_col = col
+ end
+ end
+
+ {first_row: first_row, last_row: last_row, first_column: first_col, last_column: last_col}
+ end
+ end
end
end
end
diff --git a/lib/roo/excelx/sheet_doc.rb b/lib/roo/excelx/sheet_doc.rb
index a705958..8b0c686 100755
--- a/lib/roo/excelx/sheet_doc.rb
+++ b/lib/roo/excelx/sheet_doc.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'forwardable'
require 'roo/excelx/extractor'
@@ -5,7 +7,7 @@ module Roo
class Excelx
class SheetDoc < Excelx::Extractor
extend Forwardable
- delegate [:styles, :workbook, :shared_strings, :base_date] => :@shared
+ delegate [:workbook] => :@shared
def initialize(path, relationships, shared, options = {})
super(path)
@@ -19,7 +21,12 @@ module Roo
end
def hyperlinks(relationships)
- @hyperlinks ||= extract_hyperlinks(relationships)
+ # If you're sure you're not going to need this hyperlinks you can discard it
+ @hyperlinks ||= if @options[:no_hyperlinks]
+ {}
+ else
+ extract_hyperlinks(relationships)
+ end
end
# Get the dimensions for the sheet.
@@ -39,13 +46,10 @@ module Roo
def each_cell(row_xml)
return [] unless row_xml
row_xml.children.each do |cell_element|
- # If you're sure you're not going to need this hyperlinks you can discard it
- hyperlinks = unless @options[:no_hyperlinks]
- key = ::Roo::Utils.ref_to_key(cell_element['r'])
- hyperlinks(@relationships)[key]
- end
+ coordinate = ::Roo::Utils.extract_coordinate(cell_element["r"])
+ hyperlinks = hyperlinks(@relationships)[coordinate]
- yield cell_from_xml(cell_element, hyperlinks)
+ yield cell_from_xml(cell_element, hyperlinks, coordinate)
end
end
@@ -53,13 +57,13 @@ module Roo
def cell_value_type(type, format)
case type
- when 's'.freeze
+ when 's'
:shared
- when 'b'.freeze
+ when 'b'
:boolean
- when 'str'.freeze
+ when 'str'
:string
- when 'inlineStr'.freeze
+ when 'inlineStr'
:inlinestr
else
Excelx::Format.to_type(format)
@@ -74,42 +78,58 @@ module Roo
# </c>
# hyperlink - a String for the hyperlink for the cell or nil when no
# hyperlink is present.
+ # coordinate - a Roo::Excelx::Coordinate for the coordinate for the cell
+ # or nil to extract coordinate from cell_xml.
+ # empty_cell - an Optional Boolean value.
#
# Examples
#
- # cells_from_xml(<Nokogiri::XML::Element>, nil)
+ # cells_from_xml(<Nokogiri::XML::Element>, nil, nil)
# # => <Excelx::Cell::String>
#
# Returns a type of <Excelx::Cell>.
- def cell_from_xml(cell_xml, hyperlink)
- coordinate = extract_coordinate(cell_xml['r'])
- return Excelx::Cell::Empty.new(coordinate) if cell_xml.children.empty?
+ def cell_from_xml(cell_xml, hyperlink, coordinate, empty_cell=true)
+ coordinate ||= ::Roo::Utils.extract_coordinate(cell_xml["r"])
+ cell_xml_children = cell_xml.children
+ return create_empty_cell(coordinate, empty_cell) if cell_xml_children.empty?
# NOTE: This is error prone, to_i will silently turn a nil into a 0.
# This works by coincidence because Format[0] is General.
- style = cell_xml['s'].to_i
- format = styles.style_format(style)
- value_type = cell_value_type(cell_xml['t'], format)
+ style = cell_xml["s"].to_i
formula = nil
- cell_xml.children.each do |cell|
+ cell_xml_children.each do |cell|
case cell.name
when 'is'
- content_arr = cell.search('t').map(&:content)
- unless content_arr.empty?
- return Excelx::Cell.create_cell(:string, content_arr.join(''), formula, style, hyperlink, coordinate)
+ content = +""
+ cell.children.each do |inline_str|
+ if inline_str.name == 't'
+ content << inline_str.content
+ end
+ end
+ unless content.empty?
+ return Excelx::Cell.cell_class(:string).new(content, formula, style, hyperlink, coordinate)
end
when 'f'
formula = cell.content
when 'v'
- return create_cell_from_value(value_type, cell, formula, format, style, hyperlink, base_date, coordinate)
+ format = style_format(style)
+ value_type = cell_value_type(cell_xml["t"], format)
+
+ return create_cell_from_value(value_type, cell, formula, format, style, hyperlink, coordinate)
end
end
- Excelx::Cell::Empty.new(coordinate)
+ create_empty_cell(coordinate)
end
- def create_cell_from_value(value_type, cell, formula, format, style, hyperlink, base_date, coordinate)
+ def create_empty_cell(coordinate, empty_cell)
+ if empty_cell
+ Excelx::Cell::Empty.new(coordinate)
+ end
+ end
+
+ def create_cell_from_value(value_type, cell, formula, format, style, hyperlink, coordinate)
# NOTE: format.to_s can replace excelx_type as an argument for
# Cell::Time, Cell::DateTime, Cell::Date or Cell::Number, but
# it will break some brittle tests.
@@ -125,11 +145,12 @@ module Roo
# 3. formula
case value_type
when :shared
- value = shared_strings.use_html?(cell.content.to_i) ? shared_strings.to_html[cell.content.to_i] : shared_strings[cell.content.to_i]
- Excelx::Cell.create_cell(:string, value, formula, style, hyperlink, coordinate)
+ cell_content = cell.content.to_i
+ value = shared_strings.use_html?(cell_content) ? shared_strings.to_html[cell_content] : shared_strings[cell_content]
+ Excelx::Cell.cell_class(:string).new(value, formula, style, hyperlink, coordinate)
when :boolean, :string
value = cell.content
- Excelx::Cell.create_cell(value_type, value, formula, style, hyperlink, coordinate)
+ Excelx::Cell.cell_class(value_type).new(value, formula, style, hyperlink, coordinate)
when :time, :datetime
cell_content = cell.content.to_f
# NOTE: A date will be a whole number. A time will have be > 1. And
@@ -148,35 +169,32 @@ module Roo
else
:date
end
- Excelx::Cell.create_cell(cell_type, cell.content, formula, excelx_type, style, hyperlink, base_date, coordinate)
+ base_value = cell_type == :date ? base_date : base_timestamp
+ Excelx::Cell.cell_class(cell_type).new(cell_content, formula, excelx_type, style, hyperlink, base_value, coordinate)
when :date
- Excelx::Cell.create_cell(value_type, cell.content, formula, excelx_type, style, hyperlink, base_date, coordinate)
+ Excelx::Cell.cell_class(:date).new(cell.content, formula, excelx_type, style, hyperlink, base_date, coordinate)
else
- Excelx::Cell.create_cell(:number, cell.content, formula, excelx_type, style, hyperlink, coordinate)
+ Excelx::Cell.cell_class(:number).new(cell.content, formula, excelx_type, style, hyperlink, coordinate)
end
end
- def extract_coordinate(coordinate)
- row, column = ::Roo::Utils.split_coordinate(coordinate)
-
- Excelx::Coordinate.new(row, column)
- end
-
def extract_hyperlinks(relationships)
return {} unless (hyperlinks = doc.xpath('/worksheet/hyperlinks/hyperlink'))
- Hash[hyperlinks.map do |hyperlink|
- if hyperlink.attribute('id') && (relationship = relationships[hyperlink.attribute('id').text])
- [::Roo::Utils.ref_to_key(hyperlink.attributes['ref'].to_s), relationship.attribute('Target').text]
+ hyperlinks.each_with_object({}) do |hyperlink, hash|
+ if relationship = relationships[hyperlink['id']]
+ target_link = relationship['Target']
+ target_link += "##{hyperlink['location']}" if hyperlink['location']
+ hash[::Roo::Utils.ref_to_key(hyperlink["ref"].to_s)] = target_link
end
- end.compact]
+ end
end
def expand_merged_ranges(cells)
# Extract merged ranges from xml
merges = {}
doc.xpath('/worksheet/mergeCells/mergeCell').each do |mergecell_xml|
- tl, br = mergecell_xml['ref'].split(/:/).map { |ref| ::Roo::Utils.ref_to_key(ref) }
+ tl, br = mergecell_xml["ref"].split(/:/).map { |ref| ::Roo::Utils.ref_to_key(ref) }
for row in tl[0]..br[0] do
for col in tl[1]..br[1] do
next if row == tl[0] && col == tl[1]
@@ -191,10 +209,14 @@ module Roo
end
def extract_cells(relationships)
- extracted_cells = Hash[doc.xpath('/worksheet/sheetData/row/c').map do |cell_xml|
- key = ::Roo::Utils.ref_to_key(cell_xml['r'])
- [key, cell_from_xml(cell_xml, hyperlinks(relationships)[key])]
- end]
+ extracted_cells = {}
+ empty_cell = @options[:empty_cell]
+
+ doc.xpath('/worksheet/sheetData/row/c').each do |cell_xml|
+ coordinate = ::Roo::Utils.extract_coordinate(cell_xml["r"])
+ cell = cell_from_xml(cell_xml, hyperlinks(relationships)[coordinate], coordinate, empty_cell)
+ extracted_cells[coordinate] = cell if cell
+ end
expand_merged_ranges(extracted_cells) if @options[:expand_merged_ranges]
@@ -203,9 +225,25 @@ module Roo
def extract_dimensions
Roo::Utils.each_element(@path, 'dimension') do |dimension|
- return dimension.attributes['ref'].value
+ return dimension["ref"]
end
end
+
+ def style_format(style)
+ @shared.styles.style_format(style)
+ end
+
+ def base_date
+ @shared.base_date
+ end
+
+ def base_timestamp
+ @shared.base_timestamp
+ end
+
+ def shared_strings
+ @shared.shared_strings
+ end
end
end
end
diff --git a/lib/roo/excelx/styles.rb b/lib/roo/excelx/styles.rb
index 87f1713..25f0bf0 100644
--- a/lib/roo/excelx/styles.rb
+++ b/lib/roo/excelx/styles.rb
@@ -55,9 +55,9 @@ module Roo
end
def extract_num_fmts
- Hash[doc.xpath('//numFmt').map do |num_fmt|
- [num_fmt['numFmtId'], num_fmt['formatCode']]
- end]
+ doc.xpath('//numFmt').each_with_object({}) do |num_fmt, hash|
+ hash[num_fmt['numFmtId']] = num_fmt['formatCode']
+ end
end
end
end
diff --git a/lib/roo/excelx/workbook.rb b/lib/roo/excelx/workbook.rb
index 7ef841f..c21bb1f 100644
--- a/lib/roo/excelx/workbook.rb
+++ b/lib/roo/excelx/workbook.rb
@@ -29,13 +29,17 @@ module Roo
# aka labels
def defined_names
- Hash[doc.xpath('//definedName').map do |defined_name|
+ doc.xpath('//definedName').each_with_object({}) do |defined_name, hash|
# "Sheet1!$C$5"
sheet, coordinates = defined_name.text.split('!$', 2)
col, row = coordinates.split('$')
name = defined_name['name']
- [name, Label.new(name, sheet, row, col)]
- end]
+ hash[name] = Label.new(name, sheet, row, col)
+ end
+ end
+
+ def base_timestamp
+ @base_timestamp ||= base_date.to_datetime.to_time.to_i
end
def base_date
diff --git a/lib/roo/helpers/default_attr_reader.rb b/lib/roo/helpers/default_attr_reader.rb
new file mode 100644
index 0000000..a02ba84
--- /dev/null
+++ b/lib/roo/helpers/default_attr_reader.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Roo
+ module Helpers
+ module DefaultAttrReader
+ def attr_reader_with_default(attr_hash)
+ attr_hash.each do |attr_name, default_value|
+ instance_variable = :"@#{attr_name}"
+ define_method attr_name do
+ if instance_variable_defined? instance_variable
+ instance_variable_get instance_variable
+ else
+ default_value
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/roo/helpers/weak_instance_cache.rb b/lib/roo/helpers/weak_instance_cache.rb
new file mode 100644
index 0000000..db26de1
--- /dev/null
+++ b/lib/roo/helpers/weak_instance_cache.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require "weakref"
+
+module Roo
+ module Helpers
+ module WeakInstanceCache
+ private
+
+ def instance_cache(key)
+ object = nil
+
+ if instance_variable_defined?(key) && (ref = instance_variable_get(key)) && ref.weakref_alive?
+ begin
+ object = ref.__getobj__
+ rescue => e
+ unless (defined?(::WeakRef::RefError) && e.is_a?(::WeakRef::RefError)) || (defined?(RefError) && e.is_a?(RefError))
+ raise e
+ end
+ end
+ end
+
+ unless object
+ object = yield
+ ObjectSpace.define_finalizer(object, instance_cache_finalizer(key))
+ instance_variable_set(key, WeakRef.new(object))
+ end
+
+ object
+ end
+
+ def instance_cache_finalizer(key)
+ proc do |object_id|
+ if instance_variable_defined?(key) && (ref = instance_variable_get(key)) && (!ref.weakref_alive? || ref.__getobj__.object_id == object_id)
+ remove_instance_variable(key)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/roo/open_office.rb b/lib/roo/open_office.rb
index 6ccbe85..f172363 100644
--- a/lib/roo/open_office.rb
+++ b/lib/roo/open_office.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'date'
require 'nokogiri'
require 'cgi'
@@ -11,9 +13,9 @@ module Roo
class OpenOffice < Roo::Base
extend Roo::Tempdir
- ERROR_MISSING_CONTENT_XML = 'file missing required content.xml'.freeze
- XPATH_FIND_TABLE_STYLES = "//*[local-name()='automatic-styles']".freeze
- XPATH_LOCAL_NAME_TABLE = "//*[local-name()='table']".freeze
+ ERROR_MISSING_CONTENT_XML = 'file missing required content.xml'
+ XPATH_FIND_TABLE_STYLES = "//*[local-name()='automatic-styles']"
+ XPATH_LOCAL_NAME_TABLE = "//*[local-name()='table']"
# initialization and opening of a spreadsheet file
# values for packed: :zip
@@ -561,7 +563,7 @@ module Roo
end
def read_labels
- @label ||= Hash[doc.xpath('//table:named-range').map do |ne|
+ @label ||= doc.xpath('//table:named-range').each_with_object({}) do |ne, hash|
#-
# $Sheet1.$C$5
#+
@@ -569,8 +571,8 @@ module Roo
sheetname, coords = attribute(ne, 'cell-range-address').to_s.split('.$')
col, row = coords.split('$')
sheetname = sheetname[1..-1] if sheetname[0, 1] == '$'
- [name, [sheetname, row, col]]
- end]
+ hash[name] = [sheetname, row, col]
+ end
end
def read_styles(style_elements)
diff --git a/lib/roo/spreadsheet.rb b/lib/roo/spreadsheet.rb
index 1eef58d..cdc93f0 100644
--- a/lib/roo/spreadsheet.rb
+++ b/lib/roo/spreadsheet.rb
@@ -24,7 +24,7 @@ module Roo
options[:file_warning] = :ignore
extension.tr('.', '').downcase.to_sym
else
- res = ::File.extname((path =~ /\A#{::URI.regexp}\z/) ? ::URI.parse(::URI.encode(path)).path : path)
+ res = ::File.extname((path =~ /\A#{::URI::DEFAULT_PARSER.make_regexp}\z/) ? ::URI.parse(::URI.encode(path)).path : path)
res.tr('.', '').downcase.to_sym
end
end
diff --git a/lib/roo/utils.rb b/lib/roo/utils.rb
index 17b672d..dcaedde 100644
--- a/lib/roo/utils.rb
+++ b/lib/roo/utils.rb
@@ -4,27 +4,39 @@ module Roo
LETTERS = ('A'..'Z').to_a
- def split_coordinate(str)
- @split_coordinate ||= {}
+ def extract_coordinate(s)
+ num = letter_num = 0
+ num_only = false
- @split_coordinate[str] ||= begin
- letter, number = split_coord(str)
- x = letter_to_number(letter)
- y = number
- [y, x]
+ s.each_byte do |b|
+ if !num_only && (index = char_index(b))
+ letter_num *= 26
+ letter_num += index
+ elsif index = num_index(b)
+ num_only = true
+ num *= 10
+ num += index
+ else
+ fail ArgumentError
+ end
end
+ fail ArgumentError if letter_num == 0 || !num_only
+
+ Excelx::Coordinate.new(num, letter_num)
end
- alias_method :ref_to_key, :split_coordinate
+ alias_method :ref_to_key, :extract_coordinate
- def split_coord(s)
- if s =~ /([a-zA-Z]+)([0-9]+)/
- letter = Regexp.last_match[1]
- number = Regexp.last_match[2].to_i
- else
- fail ArgumentError
- end
- [letter, number]
+ def split_coordinate(str)
+ warn "[DEPRECATION] `Roo::Utils.split_coordinate` is deprecated. Please use `Roo::Utils.extract_coordinate` instead."
+ extract_coordinate(str)
+ end
+
+
+
+ def split_coord(str)
+ coord = extract_coordinate(str)
+ [number_to_letter(coord.column), coord.row]
end
# convert a number to something like 'AB' (1 => 'A', 2 => 'B', ...)
@@ -56,8 +68,8 @@ module Roo
cells = str.split(':')
return 1 if cells.count == 1
raise ArgumentError.new("invalid range string: #{str}. Supported range format 'A1:B2'") if cells.count != 2
- x1, y1 = split_coordinate(cells[0])
- x2, y2 = split_coordinate(cells[1])
+ x1, y1 = extract_coordinate(cells[0])
+ x2, y2 = extract_coordinate(cells[1])
(x2 - (x1 - 1)) * (y2 - (y1 - 1))
end
@@ -69,10 +81,27 @@ module Roo
# Yield each element of a given type ('row', 'c', etc.) to caller
def each_element(path, elements)
+ elements = Array(elements)
Nokogiri::XML::Reader(::File.open(path, 'rb'), nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).each do |node|
- next unless node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT && Array(elements).include?(node.name)
+ next unless node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT && elements.include?(node.name)
yield Nokogiri::XML(node.outer_xml).root if block_given?
end
end
+
+ private
+
+ def char_index(byte)
+ if byte >= 65 && byte <= 90
+ byte - 64
+ elsif byte >= 97 && byte <= 122
+ byte - 96
+ end
+ end
+
+ def num_index(byte)
+ if byte >= 48 && byte <= 57
+ byte - 48
+ end
+ end
end
end
diff --git a/lib/roo/version.rb b/lib/roo/version.rb
index bdd16dc..7fd96d7 100644
--- a/lib/roo/version.rb
+++ b/lib/roo/version.rb
@@ -1,3 +1,3 @@
module Roo
- VERSION = "2.7.1"
+ VERSION = "2.8.0"
end
diff --git a/roo.gemspec b/roo.gemspec
index a34accb..c674025 100644
--- a/roo.gemspec
+++ b/roo.gemspec
@@ -4,21 +4,23 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'roo/version'
Gem::Specification.new do |spec|
- spec.name = 'roo'
- spec.version = Roo::VERSION
- spec.authors = ['Thomas Preymesser', 'Hugh McGowan', 'Ben Woosley', 'Oleksandr Simonov', 'Steven Daniels']
- spec.email = ['ruby.ruby.ruby.roo@gmail.com', 'oleksandr@simonov.me']
- spec.summary = 'Roo can access the contents of various spreadsheet files.'
- spec.description = "Roo can access the contents of various spreadsheet files. It can handle\n* OpenOffice\n* Excelx\n* LibreOffice\n* CSV"
- spec.homepage = 'http://github.com/roo-rb/roo'
- spec.license = 'MIT'
+ spec.name = 'roo'
+ spec.version = Roo::VERSION
+ spec.authors = ['Thomas Preymesser', 'Hugh McGowan', 'Ben Woosley', 'Oleksandr Simonov', 'Steven Daniels', 'Anmol Chopra']
+ spec.email = ['ruby.ruby.ruby.roo@gmail.com', 'oleksandr@simonov.me']
+ spec.summary = 'Roo can access the contents of various spreadsheet files.'
+ spec.description = "Roo can access the contents of various spreadsheet files. It can handle\n* OpenOffice\n* Excelx\n* LibreOffice\n* CSV"
+ spec.homepage = 'https://github.com/roo-rb/roo'
+ spec.license = 'MIT'
- spec.files = `git ls-files -z`.split("\x0")
+ spec.files = `git ls-files -z`.split("\x0")
spec.files.reject! { |fn| fn.include?('test/files') }
- spec.require_paths = ['lib']
+ spec.require_paths = ['lib']
+
+ spec.required_ruby_version = ">= 2.3.0"
spec.add_dependency 'nokogiri', '~> 1'
- spec.add_dependency 'rubyzip', '~> 1.1', '< 2.0.0'
+ spec.add_dependency 'rubyzip', '>= 1.2.1', '< 2.0.0'
spec.add_development_dependency 'rake', '~> 10.1'
spec.add_development_dependency 'minitest', '~> 5.4', '>= 5.4.3'
diff --git a/spec/lib/roo/base_spec.rb b/spec/lib/roo/base_spec.rb
index d00025d..76cefcc 100644
--- a/spec/lib/roo/base_spec.rb
+++ b/spec/lib/roo/base_spec.rb
@@ -127,10 +127,22 @@ describe Roo::Base do
end
end
- describe '#row' do
- it 'should return the specified row' do
+ describe "#row" do
+ it "should return the specified row" do
expect(spreadsheet.row(12)).to eq([41.0, 42.0, 43.0, 44.0, 45.0, nil, nil])
- expect(spreadsheet.row(16)).to eq([nil, '"Hello world!"', 'forty-three', 'forty-four', 'forty-five', nil, nil])
+ expect(spreadsheet.row(16)).to eq([nil, '"Hello world!"', "forty-three", "forty-four", "forty-five", nil, nil])
+ end
+
+ it "should return the specified row if default_sheet is set by a string" do
+ spreadsheet.default_sheet = "my_sheet"
+ expect(spreadsheet.row(12)).to eq([41.0, 42.0, 43.0, 44.0, 45.0, nil, nil])
+ expect(spreadsheet.row(16)).to eq([nil, '"Hello world!"', "forty-three", "forty-four", "forty-five", nil, nil])
+ end
+
+ it "should return the specified row if default_sheet is set by an integer" do
+ spreadsheet.default_sheet = 0
+ expect(spreadsheet.row(12)).to eq([41.0, 42.0, 43.0, 44.0, 45.0, nil, nil])
+ expect(spreadsheet.row(16)).to eq([nil, '"Hello world!"', "forty-three", "forty-four", "forty-five", nil, nil])
end
end
@@ -146,6 +158,11 @@ describe Roo::Base do
expect { spreadsheet.row_with([/Missing Header/]) }.to \
raise_error(Roo::HeaderRowNotFoundError)
end
+
+ it 'returns missing headers' do
+ expect { spreadsheet.row_with([/Header/, /Missing Header 1/, /Missing Header 2/]) }.to \
+ raise_error(Roo::HeaderRowNotFoundError, '[/Missing Header 1/, /Missing Header 2/]')
+ end
end
end
@@ -173,6 +190,31 @@ describe Roo::Base do
end
end
+ describe "#default_sheet=" do
+ it "should correctly set the default sheet if passed a string" do
+ spreadsheet.default_sheet = "my_sheet"
+ expect(spreadsheet.default_sheet).to eq("my_sheet")
+ end
+
+ it "should correctly set the default sheet if passed an integer" do
+ spreadsheet.default_sheet = 0
+ expect(spreadsheet.default_sheet).to eq("my_sheet")
+ end
+
+ it "should correctly set the default sheet if passed an integer for the second sheet" do
+ spreadsheet.default_sheet = 1
+ expect(spreadsheet.default_sheet).to eq("blank sheet")
+ end
+
+ it "should raise an error if passed a sheet that does not exist as an integer" do
+ expect { spreadsheet.default_sheet = 10 }.to raise_error RangeError
+ end
+
+ it "should raise an error if passed a sheet that does not exist as a string" do
+ expect { spreadsheet.default_sheet = "does_not_exist" }.to raise_error RangeError
+ end
+ end
+
describe '#to_yaml' do
it 'should convert the spreadsheet to yaml' do
expect(spreadsheet.to_yaml({}, 5, 1, 5, 1)).to eq("--- \n" + yaml_entry(5, 1, 'date', '1961-11-21'))
diff --git a/spec/lib/roo/excelx_spec.rb b/spec/lib/roo/excelx_spec.rb
index 0ef0f19..6c2289f 100755
--- a/spec/lib/roo/excelx_spec.rb
+++ b/spec/lib/roo/excelx_spec.rb
@@ -151,6 +151,22 @@ describe Roo::Excelx do
it 'returns the expected result' do
expect(subject.sheet_for("Tabelle1").instance_variable_get("@name")).to eq "Tabelle1"
end
+
+ it 'returns the expected result when passed a number' do
+ expect(subject.sheet_for(0).instance_variable_get("@name")).to eq "Tabelle1"
+ end
+
+ it 'returns the expected result when passed a number that is not the first sheet' do
+ expect(subject.sheet_for(1).instance_variable_get("@name")).to eq "Name of Sheet 2"
+ end
+
+ it "should raise an error if passed a sheet that does not exist as an integer" do
+ expect { subject.sheet_for(10) }.to raise_error RangeError
+ end
+
+ it "should raise an error if passed a sheet that does not exist as a string" do
+ expect { subject.sheet_for("does_not_exist") }.to raise_error RangeError
+ end
end
describe '#row' do
@@ -304,6 +320,18 @@ describe Roo::Excelx do
end
end
+ describe '#row' do
+ context 'integers with leading zero'
+ let(:path) { 'test/files/number_with_zero_prefix.xlsx' }
+
+ it 'returns base 10 integer' do
+ (1..50).each do |row_index|
+ range_start = (row_index - 1) * 20 + 1
+ expect(subject.row(row_index)).to eq (range_start..(range_start+19)).to_a
+ end
+ end
+ end
+
describe '#excelx_format' do
let(:path) { 'test/files/style.xlsx' }
@@ -354,11 +382,22 @@ describe Roo::Excelx do
end
describe '#hyperlink' do
- let(:path) { 'test/files/link.xlsx' }
+ context 'without location' do
+ let(:path) { 'test/files/link.xlsx' }
- it 'returns the expected result' do
- expect(subject.hyperlink(1, 1)).to eq "http://www.google.com"
- expect(subject.hyperlink(1, 2)).to eq nil
+ it 'returns the expected result' do
+ expect(subject.hyperlink(1, 1)).to eq "http://www.google.com"
+ expect(subject.hyperlink(1, 2)).to eq nil
+ end
+ end
+
+ context 'with location' do
+ let(:path) { 'test/files/link_with_location.xlsx' }
+
+ it 'returns the expected result' do
+ expect(subject.hyperlink(1, 1)).to eq "http://www.google.com/#hey"
+ expect(subject.hyperlink(1, 2)).to eq nil
+ end
end
end
@@ -480,34 +519,36 @@ describe Roo::Excelx do
end
describe '#html_strings' do
- let(:path) { 'test/files/html_strings_formatting.xlsx' }
+ describe "HTML Parsing Enabling" do
+ let(:path) { 'test/files/html_strings_formatting.xlsx' }
- it 'returns the expected result' do
- expect(subject.excelx_value(1, 1, "Sheet1")).to eq "This has no formatting."
- expect(subject.excelx_value(2, 1, "Sheet1")).to eq "<html>This has<b> bold </b>formatting.</html>"
- expect(subject.excelx_value(2, 2, "Sheet1")).to eq "<html>This has <i>italics</i> formatting.</html>"
- expect(subject.excelx_value(2, 3, "Sheet1")).to eq "<html>This has <u>underline</u> format.</html>"
- expect(subject.excelx_value(2, 4, "Sheet1")).to eq "<html>Superscript. x<sup>123</sup></html>"
- expect(subject.excelx_value(2, 5, "Sheet1")).to eq "<html>SubScript. T<sub>j</sub></html>"
-
- expect(subject.excelx_value(3, 1, "Sheet1")).to eq "<html>Bold, italics <b><i>together</i></b>.</html>"
- expect(subject.excelx_value(3, 2, "Sheet1")).to eq "<html>Bold, Underline <b><u>together</u></b>.</html>"
- expect(subject.excelx_value(3, 3, "Sheet1")).to eq "<html>Bold, Superscript. <b>x</b><sup><b>N</b></sup></html>"
- expect(subject.excelx_value(3, 4, "Sheet1")).to eq "<html>Bold, Subscript. <b>T</b><sub><b>abc</b></sub></html>"
- expect(subject.excelx_value(3, 5, "Sheet1")).to eq "<html>Italics, Underline <i><u>together</u></i>.</html>"
- expect(subject.excelx_value(3, 6, "Sheet1")).to eq "<html>Italics, Superscript. <i>X</i><sup><i>abc</i></sup></html>"
- expect(subject.excelx_value(3, 7, "Sheet1")).to eq "<html>Italics, Subscript. <i>B</i><sub><i>efg</i></sub></html>"
- expect(subject.excelx_value(4, 1, "Sheet1")).to eq "<html>Bold, italics underline,<b><i><u> together</u></i></b>.</html>"
- expect(subject.excelx_value(4, 2, "Sheet1")).to eq "<html>Bold, italics, superscript. <b>X</b><sup><b><i>abc</i></b></sup><b><i>123</i></b></html>"
- expect(subject.excelx_value(4, 3, "Sheet1")).to eq "<html>Bold, Italics, subscript. <b><i>Mg</i></b><sub><b><i>ha</i></b></sub><b><i>2</i></b></html>"
- expect(subject.excelx_value(4, 4, "Sheet1")).to eq "<html>Bold, Underline, superscript. <b><u>AB</u></b><sup><b><u>C12</u></b></sup><b><u>3</u></b></html>"
- expect(subject.excelx_value(4, 5, "Sheet1")).to eq "<html>Bold, Underline, subscript. <b><u>Good</u></b><sub><b><u>XYZ</u></b></sub></html>"
- expect(subject.excelx_value(4, 6, "Sheet1")).to eq "<html>Italics, Underline, superscript. <i><u>Up</u></i><sup><i><u>swing</u></i></sup></html>"
- expect(subject.excelx_value(4, 7, "Sheet1")).to eq "<html>Italics, Underline, subscript. <i><u>T</u></i><sub><i><u>swing</u></i></sub></html>"
- expect(subject.excelx_value(5, 1, "Sheet1")).to eq "<html>Bold, italics, underline, superscript. <b><i><u>GHJK</u></i></b><sup><b><i><u>190</u></i></b></sup><b><i><u>4</u></i></b></html>"
- expect(subject.excelx_value(5, 2, "Sheet1")).to eq "<html>Bold, italics, underline, subscript. <b><i><u>Mike</u></i></b><sub><b><i><u>drop</u></i></b></sub></html>"
- expect(subject.excelx_value(6, 1, "Sheet1")).to eq "See that regular html tags do not create html tags.\n<ol>\n <li> Denver Broncos </li>\n <li> Carolina Panthers </li>\n <li> New England Patriots</li>\n <li>Arizona Panthers</li>\n</ol>"
- expect(subject.excelx_value(7, 1, "Sheet1")).to eq "<html>Does create html tags when formatting is used..\n<ol>\n <li> <b>Denver Broncos</b> </li>\n <li> <i>Carolina Panthers </i></li>\n <li> <u>New England Patriots</u></li>\n <li>Arizona Panthers</li>\n</ol></html>"
+ it 'returns the expected result' do
+ expect(subject.excelx_value(1, 1, "Sheet1")).to eq("This has no formatting.")
+ expect(subject.excelx_value(2, 1, "Sheet1")).to eq("<html>This has<b> bold </b>formatting.</html>")
+ expect(subject.excelx_value(2, 2, "Sheet1")).to eq("<html>This has <i>italics</i> formatting.</html>")
+ expect(subject.excelx_value(2, 3, "Sheet1")).to eq("<html>This has <u>underline</u> format.</html>")
+ expect(subject.excelx_value(2, 4, "Sheet1")).to eq("<html>Superscript. x<sup>123</sup></html>")
+ expect(subject.excelx_value(2, 5, "Sheet1")).to eq("<html>SubScript. T<sub>j</sub></html>")
+
+ expect(subject.excelx_value(3, 1, "Sheet1")).to eq("<html>Bold, italics <b><i>together</i></b>.</html>")
+ expect(subject.excelx_value(3, 2, "Sheet1")).to eq("<html>Bold, Underline <b><u>together</u></b>.</html>")
+ expect(subject.excelx_value(3, 3, "Sheet1")).to eq("<html>Bold, Superscript. <b>x</b><sup><b>N</b></sup></html>")
+ expect(subject.excelx_value(3, 4, "Sheet1")).to eq("<html>Bold, Subscript. <b>T</b><sub><b>abc</b></sub></html>")
+ expect(subject.excelx_value(3, 5, "Sheet1")).to eq("<html>Italics, Underline <i><u>together</u></i>.</html>")
+ expect(subject.excelx_value(3, 6, "Sheet1")).to eq("<html>Italics, Superscript. <i>X</i><sup><i>abc</i></sup></html>")
+ expect(subject.excelx_value(3, 7, "Sheet1")).to eq("<html>Italics, Subscript. <i>B</i><sub><i>efg</i></sub></html>")
+ expect(subject.excelx_value(4, 1, "Sheet1")).to eq("<html>Bold, italics underline,<b><i><u> together</u></i></b>.</html>")
+ expect(subject.excelx_value(4, 2, "Sheet1")).to eq("<html>Bold, italics, superscript. <b>X</b><sup><b><i>abc</i></b></sup><b><i>123</i></b></html>")
+ expect(subject.excelx_value(4, 3, "Sheet1")).to eq("<html>Bold, Italics, subscript. <b><i>Mg</i></b><sub><b><i>ha</i></b></sub><b><i>2</i></b></html>")
+ expect(subject.excelx_value(4, 4, "Sheet1")).to eq("<html>Bold, Underline, superscript. <b><u>AB</u></b><sup><b><u>C12</u></b></sup><b><u>3</u></b></html>")
+ expect(subject.excelx_value(4, 5, "Sheet1")).to eq("<html>Bold, Underline, subscript. <b><u>Good</u></b><sub><b><u>XYZ</u></b></sub></html>")
+ expect(subject.excelx_value(4, 6, "Sheet1")).to eq("<html>Italics, Underline, superscript. <i><u>Up</u></i><sup><i><u>swing</u></i></sup></html>")
+ expect(subject.excelx_value(4, 7, "Sheet1")).to eq("<html>Italics, Underline, subscript. <i><u>T</u></i><sub><i><u>swing</u></i></sub></html>")
+ expect(subject.excelx_value(5, 1, "Sheet1")).to eq("<html>Bold, italics, underline, superscript. <b><i><u>GHJK</u></i></b><sup><b><i><u>190</u></i></b></sup><b><i><u>4</u></i></b></html>")
+ expect(subject.excelx_value(5, 2, "Sheet1")).to eq("<html>Bold, italics, underline, subscript. <b><i><u>Mike</u></i></b><sub><b><i><u>drop</u></i></b></sub></html>")
+ expect(subject.excelx_value(6, 1, "Sheet1")).to eq("See that regular html tags do not create html tags.\n<ol>\n <li> Denver Broncos </li>\n <li> Carolina Panthers </li>\n <li> New England Patriots</li>\n <li>Arizona Panthers</li>\n</ol>")
+ expect(subject.excelx_value(7, 1, "Sheet1")).to eq("<html>Does create html tags when formatting is used..\n<ol>\n <li> <b>Denver Broncos</b> </li>\n <li> <i>Carolina Panthers </i></li>\n <li> <u>New England Patriots</u></li>\n <li>Arizona Panthers</li>\n</ol></html>")
+ end
end
end
@@ -534,4 +575,57 @@ describe Roo::Excelx do
expect(subject.sheet(0).excelx_format(2,1)).to eq 'm/d/yyyy" "h:mm:ss" "AM/PM'
end
end
+
+ describe 'images' do
+ let(:path) { 'test/files/images.xlsx' }
+
+ it 'returns array of images from default sheet' do
+ expect(subject.images).to be_kind_of(Array)
+ expect(subject.images.size).to eql(19)
+ end
+
+ it 'returns empty array if there is no images on the sheet' do
+ expect(subject.images("Sheet2")).to eql([])
+ end
+ end
end
+
+describe 'Roo::Excelx with options set' do
+ subject(:xlsx) do
+ Roo::Excelx.new(path, disable_html_wrapper: true)
+ end
+
+ describe '#html_strings' do
+ describe "HTML Parsing Disabled" do
+ let(:path) { 'test/files/html_strings_formatting.xlsx' }
+
+ it 'returns the expected result' do
+ expect(subject.excelx_value(1, 1, "Sheet1")).to eq("This has no formatting.")
+ expect(subject.excelx_value(2, 1, "Sheet1")).to eq("This has bold formatting.")
+ expect(subject.excelx_value(2, 2, "Sheet1")).to eq("This has italics formatting.")
+ expect(subject.excelx_value(2, 3, "Sheet1")).to eq("This has underline format.")
+ expect(subject.excelx_value(2, 4, "Sheet1")).to eq("Superscript. x123")
+ expect(subject.excelx_value(2, 5, "Sheet1")).to eq("SubScript. Tj")
+
+ expect(subject.excelx_value(3, 1, "Sheet1")).to eq("Bold, italics together.")
+ expect(subject.excelx_value(3, 2, "Sheet1")).to eq("Bold, Underline together.")
+ expect(subject.excelx_value(3, 3, "Sheet1")).to eq("Bold, Superscript. xN")
+ expect(subject.excelx_value(3, 4, "Sheet1")).to eq("Bold, Subscript. Tabc")
+ expect(subject.excelx_value(3, 5, "Sheet1")).to eq("Italics, Underline together.")
+ expect(subject.excelx_value(3, 6, "Sheet1")).to eq("Italics, Superscript. Xabc")
+ expect(subject.excelx_value(3, 7, "Sheet1")).to eq("Italics, Subscript. Befg")
+ expect(subject.excelx_value(4, 1, "Sheet1")).to eq("Bold, italics underline, together.")
+ expect(subject.excelx_value(4, 2, "Sheet1")).to eq("Bold, italics, superscript. Xabc123")
+ expect(subject.excelx_value(4, 3, "Sheet1")).to eq("Bold, Italics, subscript. Mgha2")
+ expect(subject.excelx_value(4, 4, "Sheet1")).to eq("Bold, Underline, superscript. ABC123")
+ expect(subject.excelx_value(4, 5, "Sheet1")).to eq("Bold, Underline, subscript. GoodXYZ")
+ expect(subject.excelx_value(4, 6, "Sheet1")).to eq("Italics, Underline, superscript. Upswing")
+ expect(subject.excelx_value(4, 7, "Sheet1")).to eq("Italics, Underline, subscript. Tswing")
+ expect(subject.excelx_value(5, 1, "Sheet1")).to eq("Bold, italics, underline, superscript. GHJK1904")
+ expect(subject.excelx_value(5, 2, "Sheet1")).to eq("Bold, italics, underline, subscript. Mikedrop")
+ expect(subject.excelx_value(6, 1, "Sheet1")).to eq("See that regular html tags do not create html tags.\n<ol>\n <li> Denver Broncos </li>\n <li> Carolina Panthers </li>\n <li> New England Patriots</li>\n <li>Arizona Panthers</li>\n</ol>")
+ expect(subject.excelx_value(7, 1, "Sheet1")).to eq("Does create html tags when formatting is used..\n<ol>\n <li> Denver Broncos </li>\n <li> Carolina Panthers </li>\n <li> New England Patriots</li>\n <li>Arizona Panthers</li>\n</ol>")
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/lib/roo/strict_spec.rb b/spec/lib/roo/strict_spec.rb
new file mode 100644
index 0000000..811ee51
--- /dev/null
+++ b/spec/lib/roo/strict_spec.rb
@@ -0,0 +1,43 @@
+require 'spec_helper'
+
+describe Roo::Excelx do
+ subject { Roo::Excelx.new('test/files/strict.xlsx') }
+
+ example '#sheets' do
+ expect(subject.sheets).to eq %w(Sheet1 Sheet2)
+ end
+
+ example '#sheet' do
+ expect(subject.sheet('Sheet1')).to be_a(Roo::Excelx)
+ end
+
+ example '#cell' do
+ expect(subject.cell(1, 1)).to eq 'Sheet 1'
+ expect(subject.cell(1, 1, 'Sheet2')).to eq 'Sheet 2'
+ end
+
+ example '#row' do
+ expect(subject.row(1)).to eq ['Sheet 1']
+ expect(subject.row(1, 'Sheet2')).to eq ['Sheet 2']
+ end
+
+ example '#first_row' do
+ expect(subject.first_row).to eq 1
+ expect(subject.first_row('Sheet2')).to eq 1
+ end
+
+ example '#last_row' do
+ expect(subject.last_row).to eq 1
+ expect(subject.last_row('Sheet2')).to eq 1
+ end
+
+ example '#first_column' do
+ expect(subject.first_column).to eq 1
+ expect(subject.first_column('Sheet2')).to eq 1
+ end
+
+ example '#last_column' do
+ expect(subject.last_column).to eq 1
+ expect(subject.last_column('Sheet2')).to eq 1
+ end
+end
diff --git a/spec/lib/roo/utils_spec.rb b/spec/lib/roo/utils_spec.rb
index ffe93d4..8f322d4 100644
--- a/spec/lib/roo/utils_spec.rb
+++ b/spec/lib/roo/utils_spec.rb
@@ -52,6 +52,15 @@ RSpec.describe ::Roo::Utils do
end
end
+ context '.extract_coordinate' do
+ it "returns the expected result" do
+ expect(described_class.extract_coordinate('A1')).to eq [1, 1]
+ expect(described_class.extract_coordinate('B2')).to eq [2, 2]
+ expect(described_class.extract_coordinate('R2')).to eq [2, 18]
+ expect(described_class.extract_coordinate('AR31')).to eq [31, 18 + 26]
+ end
+ end
+
context '.split_coord' do
it "returns the expected result" do
expect(described_class.split_coord('A1')).to eq ["A", 1]
@@ -86,21 +95,21 @@ RSpec.describe ::Roo::Utils do
expect(described_class.load_xml('test/files/sheet1.xml')).to be_a(Nokogiri::XML::Document)
expect(described_class.load_xml('test/files/sheet1.xml').
remove_namespaces!.xpath("/worksheet/dimension").map do |dim|
- dim.attributes["ref"].value end.first).to eq "A1:B11"
+ dim["ref"] end.first).to eq "A1:B11"
end
end
context '.each_element' do
it 'returns the expected result' do
described_class.each_element('test/files/sheet1.xml', 'dimension') do |dim|
- expect(dim.attributes["ref"].value).to eq "A1:B11"
+ expect(dim["ref"]).to eq "A1:B11"
end
rows = []
described_class.each_element('test/files/sheet1.xml', 'row') do |row|
rows << row
end
expect(rows.size).to eq 11
- expect(rows[2].attributes["r"].value).to eq "3"
+ expect(rows[2]["r"]).to eq "3"
end
end
end
diff --git a/spec/lib/roo/weak_instance_cache_spec.rb b/spec/lib/roo/weak_instance_cache_spec.rb
new file mode 100644
index 0000000..c2ad9b4
--- /dev/null
+++ b/spec/lib/roo/weak_instance_cache_spec.rb
@@ -0,0 +1,92 @@
+require 'spec_helper'
+
+if RUBY_PLATFORM == "java"
+ require 'java'
+ java_import 'java.lang.System'
+end
+
+describe Roo::Helpers::WeakInstanceCache do
+ let(:klass) do
+ Class.new do
+ include Roo::Helpers::WeakInstanceCache
+
+ def memoized_data
+ instance_cache(:@memoized_data) do
+ "Some Costly Operation #{rand(1000)}" * 1_000
+ end
+ end
+ end
+ end
+
+ subject do
+ klass.new
+ end
+
+ it 'should be lazy' do
+ expect(subject.instance_variables).to_not include(:@memoized_data)
+ data = subject.memoized_data
+ expect(subject.instance_variables).to include(:@memoized_data)
+ end
+
+
+ it 'should be memoized' do
+ data = subject.memoized_data
+ expect(subject.memoized_data).to equal(data)
+ end
+
+ it 'should recalculate after GC' do
+ expect(subject.instance_variables).to_not include(:@memoized_data)
+ GC.disable
+ subject.memoized_data && nil
+ expect(subject.instance_variables).to include(:@memoized_data)
+
+ force_gc
+ expect(subject.instance_variables).to_not include(:@memoized_data)
+ GC.disable
+ subject.memoized_data && nil
+ expect(subject.instance_variables).to include(:@memoized_data)
+ end
+
+ it 'must remove instance variable' do
+ expect(subject.instance_variables).to_not include(:@memoized_data)
+ GC.disable
+ subject.memoized_data && nil
+ expect(subject.instance_variables).to include(:@memoized_data)
+
+ force_gc
+ expect(subject.instance_variables).to_not include(:@memoized_data)
+ end
+
+ context '#inspect must not raise' do
+ it 'before calculation' do
+ expect{subject.inspect}.to_not raise_error
+ end
+ it 'after calculation' do
+ GC.disable
+ subject.memoized_data && nil
+ expect{subject.inspect}.to_not raise_error
+ expect(subject.inspect).to include("Some Costly Operation")
+ force_gc
+ end
+ it 'after GC' do
+ subject.memoized_data && nil
+ force_gc
+ expect(subject.instance_variables).to_not include(:@memoized_data)
+ expect{subject.inspect}.to_not raise_error
+ expect(subject.inspect).to_not include("Some Costly Operation")
+ end
+ end
+
+ if RUBY_PLATFORM == "java"
+ def force_gc
+ System.gc
+ sleep(0.1)
+ end
+ else
+ def force_gc
+ GC.start(full_mark: true, immediate_sweep: true)
+ sleep(0.1)
+ GC.start(full_mark: true, immediate_sweep: true)
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/lib/roo_spec.rb b/spec/lib/roo_spec.rb
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/spec/lib/roo_spec.rb
diff --git a/test/excelx/cell/test_attr_reader_default.rb b/test/excelx/cell/test_attr_reader_default.rb
new file mode 100644
index 0000000..c1ae277
--- /dev/null
+++ b/test/excelx/cell/test_attr_reader_default.rb
@@ -0,0 +1,72 @@
+require "test_helper"
+
+class TestAttrReaderDefault < Minitest::Test
+ def base
+ Roo::Excelx::Cell::Base
+ end
+
+ def boolean
+ Roo::Excelx::Cell::Boolean
+ end
+
+ def class_date
+ Roo::Excelx::Cell::Date
+ end
+
+ def datetime
+ Roo::Excelx::Cell::DateTime
+ end
+
+ def empty
+ Roo::Excelx::Cell::Empty
+ end
+
+ def number
+ Roo::Excelx::Cell::Number
+ end
+
+ def string
+ Roo::Excelx::Cell::String
+ end
+
+ def base_date
+ ::Date.new(1899, 12, 30)
+ end
+
+ def base_timestamp
+ ::Date.new(1899, 12, 30).to_datetime.to_time.to_i
+ end
+
+ def class_time
+ Roo::Excelx::Cell::Time
+ end
+
+ def test_cell_default_values
+ assert_values base.new(nil, nil, [], 1, nil, nil), default_type: :base, :@default_type => nil, style: 1, :@style => nil
+ assert_values boolean.new("1", nil, nil, nil, nil), default_type: :boolean, :@default_type => nil, cell_type: :boolean, :@cell_type => nil
+ assert_values class_date.new("41791", nil, [:numeric_or_formula, "mm-dd-yy"], 6, nil, base_date, nil), default_type: :date, :@default_type => nil
+ assert_values class_time.new("0.521", nil, [:numeric_or_formula, "hh:mm"], 6, nil, base_timestamp, nil), default_type: :time, :@default_type => nil
+ assert_values datetime.new("41791.521", nil, [:numeric_or_formula, "mm-dd-yy hh:mm"], 6, nil, base_timestamp, nil), default_type: :datetime, :@default_type => nil
+ assert_values empty.new(nil), default_type: nil, :@default_type => nil, style: nil, :@style => nil
+ assert_values number.new("42", nil, ["0"], nil, nil, nil), default_type: :float, :@default_type => nil
+ assert_values string.new("1", nil, nil, nil, nil), default_type: :string, :@default_type => nil, cell_type: :string, :@cell_type => nil
+
+ assert_values base.new(nil, nil, [], 2, nil, nil), style: 2, :@style => 2
+ end
+
+ def assert_values(object, value_hash)
+ value_hash.each do |attr_name, expected_value|
+ value = if attr_name.to_s.include?("@")
+ object.instance_variable_defined?(attr_name) ? object.instance_variable_get(attr_name) : nil
+ else
+ object.public_send(attr_name)
+ end
+
+ if expected_value
+ assert_equal expected_value, value
+ else
+ assert_nil value
+ end
+ end
+ end
+end
diff --git a/test/excelx/cell/test_base.rb b/test/excelx/cell/test_base.rb
index 17c83be..e3d0c7c 100644
--- a/test/excelx/cell/test_base.rb
+++ b/test/excelx/cell/test_base.rb
@@ -25,6 +25,11 @@ class TestRooExcelxCellBase < Minitest::Test
refute cell.empty?
end
+ def test_presence
+ cell = base.new(value, nil, [], nil, nil, nil)
+ assert_equal cell, cell.presence
+ end
+
def test_cell_type_is_formula
formula = true
cell = base.new(value, formula, [], nil, nil, nil)
diff --git a/test/excelx/cell/test_datetime.rb b/test/excelx/cell/test_datetime.rb
index 425830b..4ab1e18 100644
--- a/test/excelx/cell/test_datetime.rb
+++ b/test/excelx/cell/test_datetime.rb
@@ -2,12 +2,12 @@ require 'test_helper'
class TestRooExcelxCellDateTime < Minitest::Test
def test_cell_value_is_datetime
- cell = datetime.new('30000.323212', nil, ['mm-dd-yy'], nil, nil, base_date, nil)
+ cell = datetime.new('30000.323212', nil, ['mm-dd-yy'], nil, nil, base_timestamp, nil)
assert_kind_of ::DateTime, cell.value
end
def test_cell_type_is_datetime
- cell = datetime.new('30000.323212', nil, [], nil, nil, base_date, nil)
+ cell = datetime.new('30000.323212', nil, [], nil, nil, base_timestamp, nil)
assert_equal :datetime, cell.type
end
@@ -19,7 +19,7 @@ class TestRooExcelxCellDateTime < Minitest::Test
['mmm-yy', 'JAN-15'],
['m/d/yy h:mm', '1/25/15 8:15']
].each do |format, formatted_value|
- cell = datetime.new '42029.34375', nil, [format], nil, nil, base_date, nil
+ cell = datetime.new '42029.34375', nil, [format], nil, nil, base_timestamp, nil
assert_equal formatted_value, cell.formatted_value
end
end
@@ -30,7 +30,7 @@ class TestRooExcelxCellDateTime < Minitest::Test
['h:mm:ss000 mm/yy', '8:15:00000 01/15'],
['mmm yyy', '2015-01-25 08:15:00']
].each do |format, formatted_value|
- cell = datetime.new '42029.34375', nil, [format], nil, nil, base_date, nil
+ cell = datetime.new '42029.34375', nil, [format], nil, nil, base_timestamp, nil
assert_equal formatted_value, cell.formatted_value
end
end
@@ -39,7 +39,7 @@ class TestRooExcelxCellDateTime < Minitest::Test
Roo::Excelx::Cell::DateTime
end
- def base_date
- Date.new(1899, 12, 30)
+ def base_timestamp
+ DateTime.new(1899, 12, 30).to_time.to_i
end
end
diff --git a/test/excelx/cell/test_empty.rb b/test/excelx/cell/test_empty.rb
index 8263714..e502a1d 100644
--- a/test/excelx/cell/test_empty.rb
+++ b/test/excelx/cell/test_empty.rb
@@ -4,4 +4,15 @@ class TestRooExcelxCellEmpty < Minitest::Test
def empty
Roo::Excelx::Cell::Empty
end
+
+ def test_empty?
+ cell = empty.new(nil)
+ assert_same true, cell.empty?
+ end
+
+ def test_nil_presence
+ cell = empty.new(nil)
+ assert_nil cell.presence
+ end
+
end
diff --git a/test/excelx/cell/test_number.rb b/test/excelx/cell/test_number.rb
index 45db819..5c8d726 100644
--- a/test/excelx/cell/test_number.rb
+++ b/test/excelx/cell/test_number.rb
@@ -25,6 +25,11 @@ class TestRooExcelxCellNumber < Minitest::Test
assert_kind_of(Float, cell.value)
end
+ def test_very_simple_scientific_notation
+ cell = Roo::Excelx::Cell::Number.new '1e6', nil, ['0'], nil, nil, nil
+ assert_kind_of(Float, cell.value)
+ end
+
def test_percent
cell = Roo::Excelx::Cell::Number.new '42.1', nil, ['0.00%'], nil, nil, nil
assert_kind_of(Float, cell.value)
@@ -53,8 +58,12 @@ class TestRooExcelxCellNumber < Minitest::Test
def test_formats
[
['General', '1042'],
+ ['GENERAL', '1042'],
['0', '1042'],
+ ['000000', '001042'],
['0.00', '1042.00'],
+ ['0.0000', '1042.0000'],
+ ['0.000000000', '1042.000000000'],
['#,##0', '1,042'],
['#,##0.00', '1,042.00'],
['0%', '104200%'],
diff --git a/test/excelx/cell/test_string.rb b/test/excelx/cell/test_string.rb
index f1c848f..b7ecaa7 100644
--- a/test/excelx/cell/test_string.rb
+++ b/test/excelx/cell/test_string.rb
@@ -25,4 +25,24 @@ class TestRooExcelxCellString < Minitest::Test
cell = string.new '0', nil, nil, nil, nil
assert_equal '0', cell.value
end
+
+ def test_not_empty?
+ cell = string.new '1', nil, nil, nil, nil
+ assert_equal false, cell.empty?
+ end
+
+ def test_empty?
+ cell = string.new '', nil, nil, nil, nil
+ assert_equal true, cell.empty?
+ end
+
+ def test_presence
+ cell = string.new '1', nil, nil, nil, nil
+ assert_equal cell, cell.presence
+ end
+
+ def test_nil_presence
+ cell = string.new '', nil, nil, nil, nil
+ assert_nil cell.presence
+ end
end
diff --git a/test/excelx/cell/test_time.rb b/test/excelx/cell/test_time.rb
index 7619b3a..25d15f9 100644
--- a/test/excelx/cell/test_time.rb
+++ b/test/excelx/cell/test_time.rb
@@ -5,8 +5,8 @@ class TestRooExcelxCellTime < Minitest::Test
Roo::Excelx::Cell::Time
end
- def base_date
- Date.new(1899, 12, 30)
+ def base_timestamp
+ DateTime.new(1899, 12, 30).to_time.to_i
end
def test_formatted_value
@@ -18,13 +18,13 @@ class TestRooExcelxCellTime < Minitest::Test
['[h]:mm:ss', '[1]:48:09'],
['mmss.0', '4809.0'] # Cell::Time always get rounded to the nearest second.
].each do |style_format, result|
- cell = roo_time.new(value, nil, [:numeric_or_formula, style_format], 6, nil, base_date, nil)
+ cell = roo_time.new(value, nil, [:numeric_or_formula, style_format], 6, nil, base_timestamp, nil)
assert_equal result, cell.formatted_value, "Style=#{style_format} is not properly formatted"
end
end
def test_value
- cell = roo_time.new('0.0751', nil, [:numeric_or_formula, 'h:mm'], 6, nil, base_date, nil)
+ cell = roo_time.new('0.0751', nil, [:numeric_or_formula, 'h:mm'], 6, nil, base_timestamp, nil)
assert_kind_of Integer, cell.value
end
end
diff --git a/test/excelx/test_coordinate.rb b/test/excelx/test_coordinate.rb
new file mode 100644
index 0000000..5cddcc4
--- /dev/null
+++ b/test/excelx/test_coordinate.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require "test_helper"
+
+class TestRooExcelxCoordinate < Minitest::Test
+ def row
+ 10
+ end
+
+ def column
+ 20
+ end
+
+ def coordinate
+ Roo::Excelx::Coordinate.new(row, column)
+ end
+
+ def array
+ [row, column]
+ end
+
+ def test_row
+ assert_same row, coordinate.row
+ end
+
+ def test_column
+ assert_same column, coordinate.column
+ end
+
+ def test_frozen?
+ assert coordinate.frozen?
+ end
+
+ def test_equality
+ hash = {}
+ hash[coordinate] = true
+ assert hash.key?(coordinate)
+ assert hash.key?(array)
+ end
+
+ def test_expand
+ r, c = coordinate
+ assert_same row, r
+ assert_same column, c
+ end
+
+ def test_aref
+ assert_same row, coordinate[0]
+ assert_same column, coordinate[1]
+ end
+end
diff --git a/test/files/datetime_timezone_ist_offset_change.ods b/test/files/datetime_timezone_ist_offset_change.ods
new file mode 100644
index 0000000..ebe469b
--- /dev/null
+++ b/test/files/datetime_timezone_ist_offset_change.ods
Binary files differ
diff --git a/test/files/datetime_timezone_ist_offset_change.xlsx b/test/files/datetime_timezone_ist_offset_change.xlsx
new file mode 100644
index 0000000..62240e9
--- /dev/null
+++ b/test/files/datetime_timezone_ist_offset_change.xlsx
Binary files differ
diff --git a/test/files/images.xlsx b/test/files/images.xlsx
new file mode 100644
index 0000000..669f371
--- /dev/null
+++ b/test/files/images.xlsx
Binary files differ
diff --git a/test/files/link_with_location.xlsx b/test/files/link_with_location.xlsx
new file mode 100644
index 0000000..393f5ac
--- /dev/null
+++ b/test/files/link_with_location.xlsx
Binary files differ
diff --git a/test/files/number_with_zero_prefix.xlsx b/test/files/number_with_zero_prefix.xlsx
new file mode 100644
index 0000000..104e07f
--- /dev/null
+++ b/test/files/number_with_zero_prefix.xlsx
Binary files differ
diff --git a/test/files/simple_spreadsheet.csv b/test/files/simple_spreadsheet.csv
new file mode 100644
index 0000000..fc4ab6b
--- /dev/null
+++ b/test/files/simple_spreadsheet.csv
@@ -0,0 +1,13 @@
+,,,,,
+,,,,,
+Date,Start time,End time,Pause,Sum,Comment
+2007-05-07,9.25,10.25,0,1,Task 1
+2007-05-07,10.75,12.50,0,1.75,Task 1
+2007-05-07,18.00,19.00,0,1,Task 2
+2007-05-08,9.25,10.25,0,1,Task 2
+2007-05-08,14.50,15.50,0,1,Task 3
+2007-05-08,8.75,9.25,0,0.5,Task 3
+2007-05-14,21.75,22.25,0,0.5,Task 3
+2007-05-14,22.50,23.00,0,0.5,Task 3
+2007-05-15,11.75,12.75,0,1,Task 3
+2007-05-07,10.75,10.75,0,0,Task 1
diff --git a/test/files/so_datetime_timezone_ist_offset_change.csv b/test/files/so_datetime_timezone_ist_offset_change.csv
new file mode 100644
index 0000000..6f602aa
--- /dev/null
+++ b/test/files/so_datetime_timezone_ist_offset_change.csv
@@ -0,0 +1,864 @@
+1941-09-30,1942-08-31,1905-12-31
+1941-09-30T00:05:00+00:00,1942-08-31T00:05:00+00:00,1905-12-31T00:05:00+00:00
+1941-09-30T00:10:00+00:00,1942-08-31T00:10:00+00:00,1905-12-31T00:10:00+00:00
+1941-09-30T00:15:00+00:00,1942-08-31T00:15:00+00:00,1905-12-31T00:15:00+00:00
+1941-09-30T00:20:00+00:00,1942-08-31T00:20:00+00:00,1905-12-31T00:20:00+00:00
+1941-09-30T00:25:00+00:00,1942-08-31T00:25:00+00:00,1905-12-31T00:25:00+00:00
+1941-09-30T00:30:00+00:00,1942-08-31T00:30:00+00:00,1905-12-31T00:30:00+00:00
+1941-09-30T00:35:00+00:00,1942-08-31T00:35:00+00:00,1905-12-31T00:35:00+00:00
+1941-09-30T00:40:00+00:00,1942-08-31T00:40:00+00:00,1905-12-31T00:40:00+00:00
+1941-09-30T00:45:00+00:00,1942-08-31T00:45:00+00:00,1905-12-31T00:45:00+00:00
+1941-09-30T00:50:00+00:00,1942-08-31T00:50:00+00:00,1905-12-31T00:50:00+00:00
+1941-09-30T00:55:00+00:00,1942-08-31T00:55:00+00:00,1905-12-31T00:55:00+00:00
+1941-09-30T01:00:00+00:00,1942-08-31T01:00:00+00:00,1905-12-31T01:00:00+00:00
+1941-09-30T01:05:00+00:00,1942-08-31T01:05:00+00:00,1905-12-31T01:05:00+00:00
+1941-09-30T01:10:00+00:00,1942-08-31T01:10:00+00:00,1905-12-31T01:10:00+00:00
+1941-09-30T01:15:00+00:00,1942-08-31T01:15:00+00:00,1905-12-31T01:15:00+00:00
+1941-09-30T01:20:00+00:00,1942-08-31T01:20:00+00:00,1905-12-31T01:20:00+00:00
+1941-09-30T01:25:00+00:00,1942-08-31T01:25:00+00:00,1905-12-31T01:25:00+00:00
+1941-09-30T01:30:00+00:00,1942-08-31T01:30:00+00:00,1905-12-31T01:30:00+00:00
+1941-09-30T01:35:00+00:00,1942-08-31T01:35:00+00:00,1905-12-31T01:35:00+00:00
+1941-09-30T01:40:00+00:00,1942-08-31T01:40:00+00:00,1905-12-31T01:40:00+00:00
+1941-09-30T01:45:00+00:00,1942-08-31T01:45:00+00:00,1905-12-31T01:45:00+00:00
+1941-09-30T01:50:00+00:00,1942-08-31T01:50:00+00:00,1905-12-31T01:50:00+00:00
+1941-09-30T01:55:00+00:00,1942-08-31T01:55:00+00:00,1905-12-31T01:55:00+00:00
+1941-09-30T02:00:00+00:00,1942-08-31T02:00:00+00:00,1905-12-31T02:00:00+00:00
+1941-09-30T02:05:00+00:00,1942-08-31T02:05:00+00:00,1905-12-31T02:05:00+00:00
+1941-09-30T02:10:00+00:00,1942-08-31T02:10:00+00:00,1905-12-31T02:10:00+00:00
+1941-09-30T02:15:00+00:00,1942-08-31T02:15:00+00:00,1905-12-31T02:15:00+00:00
+1941-09-30T02:20:00+00:00,1942-08-31T02:20:00+00:00,1905-12-31T02:20:00+00:00
+1941-09-30T02:25:00+00:00,1942-08-31T02:25:00+00:00,1905-12-31T02:25:00+00:00
+1941-09-30T02:30:00+00:00,1942-08-31T02:30:00+00:00,1905-12-31T02:30:00+00:00
+1941-09-30T02:35:00+00:00,1942-08-31T02:35:00+00:00,1905-12-31T02:35:00+00:00
+1941-09-30T02:40:00+00:00,1942-08-31T02:40:00+00:00,1905-12-31T02:40:00+00:00
+1941-09-30T02:45:00+00:00,1942-08-31T02:45:00+00:00,1905-12-31T02:45:00+00:00
+1941-09-30T02:50:00+00:00,1942-08-31T02:50:00+00:00,1905-12-31T02:50:00+00:00
+1941-09-30T02:55:00+00:00,1942-08-31T02:55:00+00:00,1905-12-31T02:55:00+00:00
+1941-09-30T03:00:00+00:00,1942-08-31T03:00:00+00:00,1905-12-31T03:00:00+00:00
+1941-09-30T03:05:00+00:00,1942-08-31T03:05:00+00:00,1905-12-31T03:05:00+00:00
+1941-09-30T03:10:00+00:00,1942-08-31T03:10:00+00:00,1905-12-31T03:10:00+00:00
+1941-09-30T03:15:00+00:00,1942-08-31T03:15:00+00:00,1905-12-31T03:15:00+00:00
+1941-09-30T03:20:00+00:00,1942-08-31T03:20:00+00:00,1905-12-31T03:20:00+00:00
+1941-09-30T03:25:00+00:00,1942-08-31T03:25:00+00:00,1905-12-31T03:25:00+00:00
+1941-09-30T03:30:00+00:00,1942-08-31T03:30:00+00:00,1905-12-31T03:30:00+00:00
+1941-09-30T03:35:00+00:00,1942-08-31T03:35:00+00:00,1905-12-31T03:35:00+00:00
+1941-09-30T03:40:00+00:00,1942-08-31T03:40:00+00:00,1905-12-31T03:40:00+00:00
+1941-09-30T03:45:00+00:00,1942-08-31T03:45:00+00:00,1905-12-31T03:45:00+00:00
+1941-09-30T03:50:00+00:00,1942-08-31T03:50:00+00:00,1905-12-31T03:50:00+00:00
+1941-09-30T03:55:00+00:00,1942-08-31T03:55:00+00:00,1905-12-31T03:55:00+00:00
+1941-09-30T04:00:00+00:00,1942-08-31T04:00:00+00:00,1905-12-31T04:00:00+00:00
+1941-09-30T04:05:00+00:00,1942-08-31T04:05:00+00:00,1905-12-31T04:05:00+00:00
+1941-09-30T04:10:00+00:00,1942-08-31T04:10:00+00:00,1905-12-31T04:10:00+00:00
+1941-09-30T04:15:00+00:00,1942-08-31T04:15:00+00:00,1905-12-31T04:15:00+00:00
+1941-09-30T04:20:00+00:00,1942-08-31T04:20:00+00:00,1905-12-31T04:20:00+00:00
+1941-09-30T04:25:00+00:00,1942-08-31T04:25:00+00:00,1905-12-31T04:25:00+00:00
+1941-09-30T04:30:00+00:00,1942-08-31T04:30:00+00:00,1905-12-31T04:30:00+00:00
+1941-09-30T04:35:00+00:00,1942-08-31T04:35:00+00:00,1905-12-31T04:35:00+00:00
+1941-09-30T04:40:00+00:00,1942-08-31T04:40:00+00:00,1905-12-31T04:40:00+00:00
+1941-09-30T04:45:00+00:00,1942-08-31T04:45:00+00:00,1905-12-31T04:45:00+00:00
+1941-09-30T04:50:00+00:00,1942-08-31T04:50:00+00:00,1905-12-31T04:50:00+00:00
+1941-09-30T04:55:00+00:00,1942-08-31T04:55:00+00:00,1905-12-31T04:55:00+00:00
+1941-09-30T05:00:00+00:00,1942-08-31T05:00:00+00:00,1905-12-31T05:00:00+00:00
+1941-09-30T05:05:00+00:00,1942-08-31T05:05:00+00:00,1905-12-31T05:05:00+00:00
+1941-09-30T05:10:00+00:00,1942-08-31T05:10:00+00:00,1905-12-31T05:10:00+00:00
+1941-09-30T05:15:00+00:00,1942-08-31T05:15:00+00:00,1905-12-31T05:15:00+00:00
+1941-09-30T05:20:00+00:00,1942-08-31T05:20:00+00:00,1905-12-31T05:20:00+00:00
+1941-09-30T05:25:00+00:00,1942-08-31T05:25:00+00:00,1905-12-31T05:25:00+00:00
+1941-09-30T05:30:00+00:00,1942-08-31T05:30:00+00:00,1905-12-31T05:30:00+00:00
+1941-09-30T05:35:00+00:00,1942-08-31T05:35:00+00:00,1905-12-31T05:35:00+00:00
+1941-09-30T05:40:00+00:00,1942-08-31T05:40:00+00:00,1905-12-31T05:40:00+00:00
+1941-09-30T05:45:00+00:00,1942-08-31T05:45:00+00:00,1905-12-31T05:45:00+00:00
+1941-09-30T05:50:00+00:00,1942-08-31T05:50:00+00:00,1905-12-31T05:50:00+00:00
+1941-09-30T05:55:00+00:00,1942-08-31T05:55:00+00:00,1905-12-31T05:55:00+00:00
+1941-09-30T06:00:00+00:00,1942-08-31T06:00:00+00:00,1905-12-31T06:00:00+00:00
+1941-09-30T06:05:00+00:00,1942-08-31T06:05:00+00:00,1905-12-31T06:05:00+00:00
+1941-09-30T06:10:00+00:00,1942-08-31T06:10:00+00:00,1905-12-31T06:10:00+00:00
+1941-09-30T06:15:00+00:00,1942-08-31T06:15:00+00:00,1905-12-31T06:15:00+00:00
+1941-09-30T06:20:00+00:00,1942-08-31T06:20:00+00:00,1905-12-31T06:20:00+00:00
+1941-09-30T06:25:00+00:00,1942-08-31T06:25:00+00:00,1905-12-31T06:25:00+00:00
+1941-09-30T06:30:00+00:00,1942-08-31T06:30:00+00:00,1905-12-31T06:30:00+00:00
+1941-09-30T06:35:00+00:00,1942-08-31T06:35:00+00:00,1905-12-31T06:35:00+00:00
+1941-09-30T06:40:00+00:00,1942-08-31T06:40:00+00:00,1905-12-31T06:40:00+00:00
+1941-09-30T06:45:00+00:00,1942-08-31T06:45:00+00:00,1905-12-31T06:45:00+00:00
+1941-09-30T06:50:00+00:00,1942-08-31T06:50:00+00:00,1905-12-31T06:50:00+00:00
+1941-09-30T06:55:00+00:00,1942-08-31T06:55:00+00:00,1905-12-31T06:55:00+00:00
+1941-09-30T07:00:00+00:00,1942-08-31T07:00:00+00:00,1905-12-31T07:00:00+00:00
+1941-09-30T07:05:00+00:00,1942-08-31T07:05:00+00:00,1905-12-31T07:05:00+00:00
+1941-09-30T07:10:00+00:00,1942-08-31T07:10:00+00:00,1905-12-31T07:10:00+00:00
+1941-09-30T07:15:00+00:00,1942-08-31T07:15:00+00:00,1905-12-31T07:15:00+00:00
+1941-09-30T07:20:00+00:00,1942-08-31T07:20:00+00:00,1905-12-31T07:20:00+00:00
+1941-09-30T07:25:00+00:00,1942-08-31T07:25:00+00:00,1905-12-31T07:25:00+00:00
+1941-09-30T07:30:00+00:00,1942-08-31T07:30:00+00:00,1905-12-31T07:30:00+00:00
+1941-09-30T07:35:00+00:00,1942-08-31T07:35:00+00:00,1905-12-31T07:35:00+00:00
+1941-09-30T07:40:00+00:00,1942-08-31T07:40:00+00:00,1905-12-31T07:40:00+00:00
+1941-09-30T07:45:00+00:00,1942-08-31T07:45:00+00:00,1905-12-31T07:45:00+00:00
+1941-09-30T07:50:00+00:00,1942-08-31T07:50:00+00:00,1905-12-31T07:50:00+00:00
+1941-09-30T07:55:00+00:00,1942-08-31T07:55:00+00:00,1905-12-31T07:55:00+00:00
+1941-09-30T08:00:00+00:00,1942-08-31T08:00:00+00:00,1905-12-31T08:00:00+00:00
+1941-09-30T08:05:00+00:00,1942-08-31T08:05:00+00:00,1905-12-31T08:05:00+00:00
+1941-09-30T08:10:00+00:00,1942-08-31T08:10:00+00:00,1905-12-31T08:10:00+00:00
+1941-09-30T08:15:00+00:00,1942-08-31T08:15:00+00:00,1905-12-31T08:15:00+00:00
+1941-09-30T08:20:00+00:00,1942-08-31T08:20:00+00:00,1905-12-31T08:20:00+00:00
+1941-09-30T08:25:00+00:00,1942-08-31T08:25:00+00:00,1905-12-31T08:25:00+00:00
+1941-09-30T08:30:00+00:00,1942-08-31T08:30:00+00:00,1905-12-31T08:30:00+00:00
+1941-09-30T08:35:00+00:00,1942-08-31T08:35:00+00:00,1905-12-31T08:35:00+00:00
+1941-09-30T08:40:00+00:00,1942-08-31T08:40:00+00:00,1905-12-31T08:40:00+00:00
+1941-09-30T08:45:00+00:00,1942-08-31T08:45:00+00:00,1905-12-31T08:45:00+00:00
+1941-09-30T08:50:00+00:00,1942-08-31T08:50:00+00:00,1905-12-31T08:50:00+00:00
+1941-09-30T08:55:00+00:00,1942-08-31T08:55:00+00:00,1905-12-31T08:55:00+00:00
+1941-09-30T09:00:00+00:00,1942-08-31T09:00:00+00:00,1905-12-31T09:00:00+00:00
+1941-09-30T09:05:00+00:00,1942-08-31T09:05:00+00:00,1905-12-31T09:05:00+00:00
+1941-09-30T09:10:00+00:00,1942-08-31T09:10:00+00:00,1905-12-31T09:10:00+00:00
+1941-09-30T09:15:00+00:00,1942-08-31T09:15:00+00:00,1905-12-31T09:15:00+00:00
+1941-09-30T09:20:00+00:00,1942-08-31T09:20:00+00:00,1905-12-31T09:20:00+00:00
+1941-09-30T09:25:00+00:00,1942-08-31T09:25:00+00:00,1905-12-31T09:25:00+00:00
+1941-09-30T09:30:00+00:00,1942-08-31T09:30:00+00:00,1905-12-31T09:30:00+00:00
+1941-09-30T09:35:00+00:00,1942-08-31T09:35:00+00:00,1905-12-31T09:35:00+00:00
+1941-09-30T09:40:00+00:00,1942-08-31T09:40:00+00:00,1905-12-31T09:40:00+00:00
+1941-09-30T09:45:00+00:00,1942-08-31T09:45:00+00:00,1905-12-31T09:45:00+00:00
+1941-09-30T09:50:00+00:00,1942-08-31T09:50:00+00:00,1905-12-31T09:50:00+00:00
+1941-09-30T09:55:00+00:00,1942-08-31T09:55:00+00:00,1905-12-31T09:55:00+00:00
+1941-09-30T10:00:00+00:00,1942-08-31T10:00:00+00:00,1905-12-31T10:00:00+00:00
+1941-09-30T10:05:00+00:00,1942-08-31T10:05:00+00:00,1905-12-31T10:05:00+00:00
+1941-09-30T10:10:00+00:00,1942-08-31T10:10:00+00:00,1905-12-31T10:10:00+00:00
+1941-09-30T10:15:00+00:00,1942-08-31T10:15:00+00:00,1905-12-31T10:15:00+00:00
+1941-09-30T10:20:00+00:00,1942-08-31T10:20:00+00:00,1905-12-31T10:20:00+00:00
+1941-09-30T10:25:00+00:00,1942-08-31T10:25:00+00:00,1905-12-31T10:25:00+00:00
+1941-09-30T10:30:00+00:00,1942-08-31T10:30:00+00:00,1905-12-31T10:30:00+00:00
+1941-09-30T10:35:00+00:00,1942-08-31T10:35:00+00:00,1905-12-31T10:35:00+00:00
+1941-09-30T10:40:00+00:00,1942-08-31T10:40:00+00:00,1905-12-31T10:40:00+00:00
+1941-09-30T10:45:00+00:00,1942-08-31T10:45:00+00:00,1905-12-31T10:45:00+00:00
+1941-09-30T10:50:00+00:00,1942-08-31T10:50:00+00:00,1905-12-31T10:50:00+00:00
+1941-09-30T10:55:00+00:00,1942-08-31T10:55:00+00:00,1905-12-31T10:55:00+00:00
+1941-09-30T11:00:00+00:00,1942-08-31T11:00:00+00:00,1905-12-31T11:00:00+00:00
+1941-09-30T11:05:00+00:00,1942-08-31T11:05:00+00:00,1905-12-31T11:05:00+00:00
+1941-09-30T11:10:00+00:00,1942-08-31T11:10:00+00:00,1905-12-31T11:10:00+00:00
+1941-09-30T11:15:00+00:00,1942-08-31T11:15:00+00:00,1905-12-31T11:15:00+00:00
+1941-09-30T11:20:00+00:00,1942-08-31T11:20:00+00:00,1905-12-31T11:20:00+00:00
+1941-09-30T11:25:00+00:00,1942-08-31T11:25:00+00:00,1905-12-31T11:25:00+00:00
+1941-09-30T11:30:00+00:00,1942-08-31T11:30:00+00:00,1905-12-31T11:30:00+00:00
+1941-09-30T11:35:00+00:00,1942-08-31T11:35:00+00:00,1905-12-31T11:35:00+00:00
+1941-09-30T11:40:00+00:00,1942-08-31T11:40:00+00:00,1905-12-31T11:40:00+00:00
+1941-09-30T11:45:00+00:00,1942-08-31T11:45:00+00:00,1905-12-31T11:45:00+00:00
+1941-09-30T11:50:00+00:00,1942-08-31T11:50:00+00:00,1905-12-31T11:50:00+00:00
+1941-09-30T11:55:00+00:00,1942-08-31T11:55:00+00:00,1905-12-31T11:55:00+00:00
+1941-09-30T12:00:00+00:00,1942-08-31T12:00:00+00:00,1905-12-31T12:00:00+00:00
+1941-09-30T12:05:00+00:00,1942-08-31T12:05:00+00:00,1905-12-31T12:05:00+00:00
+1941-09-30T12:10:00+00:00,1942-08-31T12:10:00+00:00,1905-12-31T12:10:00+00:00
+1941-09-30T12:15:00+00:00,1942-08-31T12:15:00+00:00,1905-12-31T12:15:00+00:00
+1941-09-30T12:20:00+00:00,1942-08-31T12:20:00+00:00,1905-12-31T12:20:00+00:00
+1941-09-30T12:25:00+00:00,1942-08-31T12:25:00+00:00,1905-12-31T12:25:00+00:00
+1941-09-30T12:30:00+00:00,1942-08-31T12:30:00+00:00,1905-12-31T12:30:00+00:00
+1941-09-30T12:35:00+00:00,1942-08-31T12:35:00+00:00,1905-12-31T12:35:00+00:00
+1941-09-30T12:40:00+00:00,1942-08-31T12:40:00+00:00,1905-12-31T12:40:00+00:00
+1941-09-30T12:45:00+00:00,1942-08-31T12:45:00+00:00,1905-12-31T12:45:00+00:00
+1941-09-30T12:50:00+00:00,1942-08-31T12:50:00+00:00,1905-12-31T12:50:00+00:00
+1941-09-30T12:55:00+00:00,1942-08-31T12:55:00+00:00,1905-12-31T12:55:00+00:00
+1941-09-30T13:00:00+00:00,1942-08-31T13:00:00+00:00,1905-12-31T13:00:00+00:00
+1941-09-30T13:05:00+00:00,1942-08-31T13:05:00+00:00,1905-12-31T13:05:00+00:00
+1941-09-30T13:10:00+00:00,1942-08-31T13:10:00+00:00,1905-12-31T13:10:00+00:00
+1941-09-30T13:15:00+00:00,1942-08-31T13:15:00+00:00,1905-12-31T13:15:00+00:00
+1941-09-30T13:20:00+00:00,1942-08-31T13:20:00+00:00,1905-12-31T13:20:00+00:00
+1941-09-30T13:25:00+00:00,1942-08-31T13:25:00+00:00,1905-12-31T13:25:00+00:00
+1941-09-30T13:30:00+00:00,1942-08-31T13:30:00+00:00,1905-12-31T13:30:00+00:00
+1941-09-30T13:35:00+00:00,1942-08-31T13:35:00+00:00,1905-12-31T13:35:00+00:00
+1941-09-30T13:40:00+00:00,1942-08-31T13:40:00+00:00,1905-12-31T13:40:00+00:00
+1941-09-30T13:45:00+00:00,1942-08-31T13:45:00+00:00,1905-12-31T13:45:00+00:00
+1941-09-30T13:50:00+00:00,1942-08-31T13:50:00+00:00,1905-12-31T13:50:00+00:00
+1941-09-30T13:55:00+00:00,1942-08-31T13:55:00+00:00,1905-12-31T13:55:00+00:00
+1941-09-30T14:00:00+00:00,1942-08-31T14:00:00+00:00,1905-12-31T14:00:00+00:00
+1941-09-30T14:05:00+00:00,1942-08-31T14:05:00+00:00,1905-12-31T14:05:00+00:00
+1941-09-30T14:10:00+00:00,1942-08-31T14:10:00+00:00,1905-12-31T14:10:00+00:00
+1941-09-30T14:15:00+00:00,1942-08-31T14:15:00+00:00,1905-12-31T14:15:00+00:00
+1941-09-30T14:20:00+00:00,1942-08-31T14:20:00+00:00,1905-12-31T14:20:00+00:00
+1941-09-30T14:25:00+00:00,1942-08-31T14:25:00+00:00,1905-12-31T14:25:00+00:00
+1941-09-30T14:30:00+00:00,1942-08-31T14:30:00+00:00,1905-12-31T14:30:00+00:00
+1941-09-30T14:35:00+00:00,1942-08-31T14:35:00+00:00,1905-12-31T14:35:00+00:00
+1941-09-30T14:40:00+00:00,1942-08-31T14:40:00+00:00,1905-12-31T14:40:00+00:00
+1941-09-30T14:45:00+00:00,1942-08-31T14:45:00+00:00,1905-12-31T14:45:00+00:00
+1941-09-30T14:50:00+00:00,1942-08-31T14:50:00+00:00,1905-12-31T14:50:00+00:00
+1941-09-30T14:55:00+00:00,1942-08-31T14:55:00+00:00,1905-12-31T14:55:00+00:00
+1941-09-30T15:00:00+00:00,1942-08-31T15:00:00+00:00,1905-12-31T15:00:00+00:00
+1941-09-30T15:05:00+00:00,1942-08-31T15:05:00+00:00,1905-12-31T15:05:00+00:00
+1941-09-30T15:10:00+00:00,1942-08-31T15:10:00+00:00,1905-12-31T15:10:00+00:00
+1941-09-30T15:15:00+00:00,1942-08-31T15:15:00+00:00,1905-12-31T15:15:00+00:00
+1941-09-30T15:20:00+00:00,1942-08-31T15:20:00+00:00,1905-12-31T15:20:00+00:00
+1941-09-30T15:25:00+00:00,1942-08-31T15:25:00+00:00,1905-12-31T15:25:00+00:00
+1941-09-30T15:30:00+00:00,1942-08-31T15:30:00+00:00,1905-12-31T15:30:00+00:00
+1941-09-30T15:35:00+00:00,1942-08-31T15:35:00+00:00,1905-12-31T15:35:00+00:00
+1941-09-30T15:40:00+00:00,1942-08-31T15:40:00+00:00,1905-12-31T15:40:00+00:00
+1941-09-30T15:45:00+00:00,1942-08-31T15:45:00+00:00,1905-12-31T15:45:00+00:00
+1941-09-30T15:50:00+00:00,1942-08-31T15:50:00+00:00,1905-12-31T15:50:00+00:00
+1941-09-30T15:55:00+00:00,1942-08-31T15:55:00+00:00,1905-12-31T15:55:00+00:00
+1941-09-30T16:00:00+00:00,1942-08-31T16:00:00+00:00,1905-12-31T16:00:00+00:00
+1941-09-30T16:05:00+00:00,1942-08-31T16:05:00+00:00,1905-12-31T16:05:00+00:00
+1941-09-30T16:10:00+00:00,1942-08-31T16:10:00+00:00,1905-12-31T16:10:00+00:00
+1941-09-30T16:15:00+00:00,1942-08-31T16:15:00+00:00,1905-12-31T16:15:00+00:00
+1941-09-30T16:20:00+00:00,1942-08-31T16:20:00+00:00,1905-12-31T16:20:00+00:00
+1941-09-30T16:25:00+00:00,1942-08-31T16:25:00+00:00,1905-12-31T16:25:00+00:00
+1941-09-30T16:30:00+00:00,1942-08-31T16:30:00+00:00,1905-12-31T16:30:00+00:00
+1941-09-30T16:35:00+00:00,1942-08-31T16:35:00+00:00,1905-12-31T16:35:00+00:00
+1941-09-30T16:40:00+00:00,1942-08-31T16:40:00+00:00,1905-12-31T16:40:00+00:00
+1941-09-30T16:45:00+00:00,1942-08-31T16:45:00+00:00,1905-12-31T16:45:00+00:00
+1941-09-30T16:50:00+00:00,1942-08-31T16:50:00+00:00,1905-12-31T16:50:00+00:00
+1941-09-30T16:55:00+00:00,1942-08-31T16:55:00+00:00,1905-12-31T16:55:00+00:00
+1941-09-30T17:00:00+00:00,1942-08-31T17:00:00+00:00,1905-12-31T17:00:00+00:00
+1941-09-30T17:05:00+00:00,1942-08-31T17:05:00+00:00,1905-12-31T17:05:00+00:00
+1941-09-30T17:10:00+00:00,1942-08-31T17:10:00+00:00,1905-12-31T17:10:00+00:00
+1941-09-30T17:15:00+00:00,1942-08-31T17:15:00+00:00,1905-12-31T17:15:00+00:00
+1941-09-30T17:20:00+00:00,1942-08-31T17:20:00+00:00,1905-12-31T17:20:00+00:00
+1941-09-30T17:25:00+00:00,1942-08-31T17:25:00+00:00,1905-12-31T17:25:00+00:00
+1941-09-30T17:30:00+00:00,1942-08-31T17:30:00+00:00,1905-12-31T17:30:00+00:00
+1941-09-30T17:35:00+00:00,1942-08-31T17:35:00+00:00,1905-12-31T17:35:00+00:00
+1941-09-30T17:40:00+00:00,1942-08-31T17:40:00+00:00,1905-12-31T17:40:00+00:00
+1941-09-30T17:45:00+00:00,1942-08-31T17:45:00+00:00,1905-12-31T17:45:00+00:00
+1941-09-30T17:50:00+00:00,1942-08-31T17:50:00+00:00,1905-12-31T17:50:00+00:00
+1941-09-30T17:55:00+00:00,1942-08-31T17:55:00+00:00,1905-12-31T17:55:00+00:00
+1941-09-30T18:00:00+00:00,1942-08-31T18:00:00+00:00,1905-12-31T18:00:00+00:00
+1941-09-30T18:05:00+00:00,1942-08-31T18:05:00+00:00,1905-12-31T18:05:00+00:00
+1941-09-30T18:10:00+00:00,1942-08-31T18:10:00+00:00,1905-12-31T18:10:00+00:00
+1941-09-30T18:15:00+00:00,1942-08-31T18:15:00+00:00,1905-12-31T18:15:00+00:00
+1941-09-30T18:20:00+00:00,1942-08-31T18:20:00+00:00,1905-12-31T18:20:00+00:00
+1941-09-30T18:25:00+00:00,1942-08-31T18:25:00+00:00,1905-12-31T18:25:00+00:00
+1941-09-30T18:30:00+00:00,1942-08-31T18:30:00+00:00,1905-12-31T18:30:00+00:00
+1941-09-30T18:35:00+00:00,1942-08-31T18:35:00+00:00,1905-12-31T18:35:00+00:00
+1941-09-30T18:40:00+00:00,1942-08-31T18:40:00+00:00,1905-12-31T18:40:00+00:00
+1941-09-30T18:45:00+00:00,1942-08-31T18:45:00+00:00,1905-12-31T18:45:00+00:00
+1941-09-30T18:50:00+00:00,1942-08-31T18:50:00+00:00,1905-12-31T18:50:00+00:00
+1941-09-30T18:55:00+00:00,1942-08-31T18:55:00+00:00,1905-12-31T18:55:00+00:00
+1941-09-30T19:00:00+00:00,1942-08-31T19:00:00+00:00,1905-12-31T19:00:00+00:00
+1941-09-30T19:05:00+00:00,1942-08-31T19:05:00+00:00,1905-12-31T19:05:00+00:00
+1941-09-30T19:10:00+00:00,1942-08-31T19:10:00+00:00,1905-12-31T19:10:00+00:00
+1941-09-30T19:15:00+00:00,1942-08-31T19:15:00+00:00,1905-12-31T19:15:00+00:00
+1941-09-30T19:20:00+00:00,1942-08-31T19:20:00+00:00,1905-12-31T19:20:00+00:00
+1941-09-30T19:25:00+00:00,1942-08-31T19:25:00+00:00,1905-12-31T19:25:00+00:00
+1941-09-30T19:30:00+00:00,1942-08-31T19:30:00+00:00,1905-12-31T19:30:00+00:00
+1941-09-30T19:35:00+00:00,1942-08-31T19:35:00+00:00,1905-12-31T19:35:00+00:00
+1941-09-30T19:40:00+00:00,1942-08-31T19:40:00+00:00,1905-12-31T19:40:00+00:00
+1941-09-30T19:45:00+00:00,1942-08-31T19:45:00+00:00,1905-12-31T19:45:00+00:00
+1941-09-30T19:50:00+00:00,1942-08-31T19:50:00+00:00,1905-12-31T19:50:00+00:00
+1941-09-30T19:55:00+00:00,1942-08-31T19:55:00+00:00,1905-12-31T19:55:00+00:00
+1941-09-30T20:00:00+00:00,1942-08-31T20:00:00+00:00,1905-12-31T20:00:00+00:00
+1941-09-30T20:05:00+00:00,1942-08-31T20:05:00+00:00,1905-12-31T20:05:00+00:00
+1941-09-30T20:10:00+00:00,1942-08-31T20:10:00+00:00,1905-12-31T20:10:00+00:00
+1941-09-30T20:15:00+00:00,1942-08-31T20:15:00+00:00,1905-12-31T20:15:00+00:00
+1941-09-30T20:20:00+00:00,1942-08-31T20:20:00+00:00,1905-12-31T20:20:00+00:00
+1941-09-30T20:25:00+00:00,1942-08-31T20:25:00+00:00,1905-12-31T20:25:00+00:00
+1941-09-30T20:30:00+00:00,1942-08-31T20:30:00+00:00,1905-12-31T20:30:00+00:00
+1941-09-30T20:35:00+00:00,1942-08-31T20:35:00+00:00,1905-12-31T20:35:00+00:00
+1941-09-30T20:40:00+00:00,1942-08-31T20:40:00+00:00,1905-12-31T20:40:00+00:00
+1941-09-30T20:45:00+00:00,1942-08-31T20:45:00+00:00,1905-12-31T20:45:00+00:00
+1941-09-30T20:50:00+00:00,1942-08-31T20:50:00+00:00,1905-12-31T20:50:00+00:00
+1941-09-30T20:55:00+00:00,1942-08-31T20:55:00+00:00,1905-12-31T20:55:00+00:00
+1941-09-30T21:00:00+00:00,1942-08-31T21:00:00+00:00,1905-12-31T21:00:00+00:00
+1941-09-30T21:05:00+00:00,1942-08-31T21:05:00+00:00,1905-12-31T21:05:00+00:00
+1941-09-30T21:10:00+00:00,1942-08-31T21:10:00+00:00,1905-12-31T21:10:00+00:00
+1941-09-30T21:15:00+00:00,1942-08-31T21:15:00+00:00,1905-12-31T21:15:00+00:00
+1941-09-30T21:20:00+00:00,1942-08-31T21:20:00+00:00,1905-12-31T21:20:00+00:00
+1941-09-30T21:25:00+00:00,1942-08-31T21:25:00+00:00,1905-12-31T21:25:00+00:00
+1941-09-30T21:30:00+00:00,1942-08-31T21:30:00+00:00,1905-12-31T21:30:00+00:00
+1941-09-30T21:35:00+00:00,1942-08-31T21:35:00+00:00,1905-12-31T21:35:00+00:00
+1941-09-30T21:40:00+00:00,1942-08-31T21:40:00+00:00,1905-12-31T21:40:00+00:00
+1941-09-30T21:45:00+00:00,1942-08-31T21:45:00+00:00,1905-12-31T21:45:00+00:00
+1941-09-30T21:50:00+00:00,1942-08-31T21:50:00+00:00,1905-12-31T21:50:00+00:00
+1941-09-30T21:55:00+00:00,1942-08-31T21:55:00+00:00,1905-12-31T21:55:00+00:00
+1941-09-30T22:00:00+00:00,1942-08-31T22:00:00+00:00,1905-12-31T22:00:00+00:00
+1941-09-30T22:05:00+00:00,1942-08-31T22:05:00+00:00,1905-12-31T22:05:00+00:00
+1941-09-30T22:10:00+00:00,1942-08-31T22:10:00+00:00,1905-12-31T22:10:00+00:00
+1941-09-30T22:15:00+00:00,1942-08-31T22:15:00+00:00,1905-12-31T22:15:00+00:00
+1941-09-30T22:20:00+00:00,1942-08-31T22:20:00+00:00,1905-12-31T22:20:00+00:00
+1941-09-30T22:25:00+00:00,1942-08-31T22:25:00+00:00,1905-12-31T22:25:00+00:00
+1941-09-30T22:30:00+00:00,1942-08-31T22:30:00+00:00,1905-12-31T22:30:00+00:00
+1941-09-30T22:35:00+00:00,1942-08-31T22:35:00+00:00,1905-12-31T22:35:00+00:00
+1941-09-30T22:40:00+00:00,1942-08-31T22:40:00+00:00,1905-12-31T22:40:00+00:00
+1941-09-30T22:45:00+00:00,1942-08-31T22:45:00+00:00,1905-12-31T22:45:00+00:00
+1941-09-30T22:50:00+00:00,1942-08-31T22:50:00+00:00,1905-12-31T22:50:00+00:00
+1941-09-30T22:55:00+00:00,1942-08-31T22:55:00+00:00,1905-12-31T22:55:00+00:00
+1941-09-30T23:00:00+00:00,1942-08-31T23:00:00+00:00,1905-12-31T23:00:00+00:00
+1941-09-30T23:05:00+00:00,1942-08-31T23:05:00+00:00,1905-12-31T23:05:00+00:00
+1941-09-30T23:10:00+00:00,1942-08-31T23:10:00+00:00,1905-12-31T23:10:00+00:00
+1941-09-30T23:15:00+00:00,1942-08-31T23:15:00+00:00,1905-12-31T23:15:00+00:00
+1941-09-30T23:20:00+00:00,1942-08-31T23:20:00+00:00,1905-12-31T23:20:00+00:00
+1941-09-30T23:25:00+00:00,1942-08-31T23:25:00+00:00,1905-12-31T23:25:00+00:00
+1941-09-30T23:30:00+00:00,1942-08-31T23:30:00+00:00,1905-12-31T23:30:00+00:00
+1941-09-30T23:35:00+00:00,1942-08-31T23:35:00+00:00,1905-12-31T23:35:00+00:00
+1941-09-30T23:40:00+00:00,1942-08-31T23:40:00+00:00,1905-12-31T23:40:00+00:00
+1941-09-30T23:45:00+00:00,1942-08-31T23:45:00+00:00,1905-12-31T23:45:00+00:00
+1941-09-30T23:50:00+00:00,1942-08-31T23:50:00+00:00,1905-12-31T23:50:00+00:00
+1941-09-30T23:55:00+00:00,1942-08-31T23:55:00+00:00,1905-12-31T23:55:00+00:00
+1941-10-01,1942-09-01,1906-01-01
+1941-10-01T00:05:00+00:00,1942-09-01T00:05:00+00:00,1906-01-01T00:05:00+00:00
+1941-10-01T00:10:00+00:00,1942-09-01T00:10:00+00:00,1906-01-01T00:10:00+00:00
+1941-10-01T00:15:00+00:00,1942-09-01T00:15:00+00:00,1906-01-01T00:15:00+00:00
+1941-10-01T00:20:00+00:00,1942-09-01T00:20:00+00:00,1906-01-01T00:20:00+00:00
+1941-10-01T00:25:00+00:00,1942-09-01T00:25:00+00:00,1906-01-01T00:25:00+00:00
+1941-10-01T00:30:00+00:00,1942-09-01T00:30:00+00:00,1906-01-01T00:30:00+00:00
+1941-10-01T00:35:00+00:00,1942-09-01T00:35:00+00:00,1906-01-01T00:35:00+00:00
+1941-10-01T00:40:00+00:00,1942-09-01T00:40:00+00:00,1906-01-01T00:40:00+00:00
+1941-10-01T00:45:00+00:00,1942-09-01T00:45:00+00:00,1906-01-01T00:45:00+00:00
+1941-10-01T00:50:00+00:00,1942-09-01T00:50:00+00:00,1906-01-01T00:50:00+00:00
+1941-10-01T00:55:00+00:00,1942-09-01T00:55:00+00:00,1906-01-01T00:55:00+00:00
+1941-10-01T01:00:00+00:00,1942-09-01T01:00:00+00:00,1906-01-01T01:00:00+00:00
+1941-10-01T01:05:00+00:00,1942-09-01T01:05:00+00:00,1906-01-01T01:05:00+00:00
+1941-10-01T01:10:00+00:00,1942-09-01T01:10:00+00:00,1906-01-01T01:10:00+00:00
+1941-10-01T01:15:00+00:00,1942-09-01T01:15:00+00:00,1906-01-01T01:15:00+00:00
+1941-10-01T01:20:00+00:00,1942-09-01T01:20:00+00:00,1906-01-01T01:20:00+00:00
+1941-10-01T01:25:00+00:00,1942-09-01T01:25:00+00:00,1906-01-01T01:25:00+00:00
+1941-10-01T01:30:00+00:00,1942-09-01T01:30:00+00:00,1906-01-01T01:30:00+00:00
+1941-10-01T01:35:00+00:00,1942-09-01T01:35:00+00:00,1906-01-01T01:35:00+00:00
+1941-10-01T01:40:00+00:00,1942-09-01T01:40:00+00:00,1906-01-01T01:40:00+00:00
+1941-10-01T01:45:00+00:00,1942-09-01T01:45:00+00:00,1906-01-01T01:45:00+00:00
+1941-10-01T01:50:00+00:00,1942-09-01T01:50:00+00:00,1906-01-01T01:50:00+00:00
+1941-10-01T01:55:00+00:00,1942-09-01T01:55:00+00:00,1906-01-01T01:55:00+00:00
+1941-10-01T02:00:00+00:00,1942-09-01T02:00:00+00:00,1906-01-01T02:00:00+00:00
+1941-10-01T02:05:00+00:00,1942-09-01T02:05:00+00:00,1906-01-01T02:05:00+00:00
+1941-10-01T02:10:00+00:00,1942-09-01T02:10:00+00:00,1906-01-01T02:10:00+00:00
+1941-10-01T02:15:00+00:00,1942-09-01T02:15:00+00:00,1906-01-01T02:15:00+00:00
+1941-10-01T02:20:00+00:00,1942-09-01T02:20:00+00:00,1906-01-01T02:20:00+00:00
+1941-10-01T02:25:00+00:00,1942-09-01T02:25:00+00:00,1906-01-01T02:25:00+00:00
+1941-10-01T02:30:00+00:00,1942-09-01T02:30:00+00:00,1906-01-01T02:30:00+00:00
+1941-10-01T02:35:00+00:00,1942-09-01T02:35:00+00:00,1906-01-01T02:35:00+00:00
+1941-10-01T02:40:00+00:00,1942-09-01T02:40:00+00:00,1906-01-01T02:40:00+00:00
+1941-10-01T02:45:00+00:00,1942-09-01T02:45:00+00:00,1906-01-01T02:45:00+00:00
+1941-10-01T02:50:00+00:00,1942-09-01T02:50:00+00:00,1906-01-01T02:50:00+00:00
+1941-10-01T02:55:00+00:00,1942-09-01T02:55:00+00:00,1906-01-01T02:55:00+00:00
+1941-10-01T03:00:00+00:00,1942-09-01T03:00:00+00:00,1906-01-01T03:00:00+00:00
+1941-10-01T03:05:00+00:00,1942-09-01T03:05:00+00:00,1906-01-01T03:05:00+00:00
+1941-10-01T03:10:00+00:00,1942-09-01T03:10:00+00:00,1906-01-01T03:10:00+00:00
+1941-10-01T03:15:00+00:00,1942-09-01T03:15:00+00:00,1906-01-01T03:15:00+00:00
+1941-10-01T03:20:00+00:00,1942-09-01T03:20:00+00:00,1906-01-01T03:20:00+00:00
+1941-10-01T03:25:00+00:00,1942-09-01T03:25:00+00:00,1906-01-01T03:25:00+00:00
+1941-10-01T03:30:00+00:00,1942-09-01T03:30:00+00:00,1906-01-01T03:30:00+00:00
+1941-10-01T03:35:00+00:00,1942-09-01T03:35:00+00:00,1906-01-01T03:35:00+00:00
+1941-10-01T03:40:00+00:00,1942-09-01T03:40:00+00:00,1906-01-01T03:40:00+00:00
+1941-10-01T03:45:00+00:00,1942-09-01T03:45:00+00:00,1906-01-01T03:45:00+00:00
+1941-10-01T03:50:00+00:00,1942-09-01T03:50:00+00:00,1906-01-01T03:50:00+00:00
+1941-10-01T03:55:00+00:00,1942-09-01T03:55:00+00:00,1906-01-01T03:55:00+00:00
+1941-10-01T04:00:00+00:00,1942-09-01T04:00:00+00:00,1906-01-01T04:00:00+00:00
+1941-10-01T04:05:00+00:00,1942-09-01T04:05:00+00:00,1906-01-01T04:05:00+00:00
+1941-10-01T04:10:00+00:00,1942-09-01T04:10:00+00:00,1906-01-01T04:10:00+00:00
+1941-10-01T04:15:00+00:00,1942-09-01T04:15:00+00:00,1906-01-01T04:15:00+00:00
+1941-10-01T04:20:00+00:00,1942-09-01T04:20:00+00:00,1906-01-01T04:20:00+00:00
+1941-10-01T04:25:00+00:00,1942-09-01T04:25:00+00:00,1906-01-01T04:25:00+00:00
+1941-10-01T04:30:00+00:00,1942-09-01T04:30:00+00:00,1906-01-01T04:30:00+00:00
+1941-10-01T04:35:00+00:00,1942-09-01T04:35:00+00:00,1906-01-01T04:35:00+00:00
+1941-10-01T04:40:00+00:00,1942-09-01T04:40:00+00:00,1906-01-01T04:40:00+00:00
+1941-10-01T04:45:00+00:00,1942-09-01T04:45:00+00:00,1906-01-01T04:45:00+00:00
+1941-10-01T04:50:00+00:00,1942-09-01T04:50:00+00:00,1906-01-01T04:50:00+00:00
+1941-10-01T04:55:00+00:00,1942-09-01T04:55:00+00:00,1906-01-01T04:55:00+00:00
+1941-10-01T05:00:00+00:00,1942-09-01T05:00:00+00:00,1906-01-01T05:00:00+00:00
+1941-10-01T05:05:00+00:00,1942-09-01T05:05:00+00:00,1906-01-01T05:05:00+00:00
+1941-10-01T05:10:00+00:00,1942-09-01T05:10:00+00:00,1906-01-01T05:10:00+00:00
+1941-10-01T05:15:00+00:00,1942-09-01T05:15:00+00:00,1906-01-01T05:15:00+00:00
+1941-10-01T05:20:00+00:00,1942-09-01T05:20:00+00:00,1906-01-01T05:20:00+00:00
+1941-10-01T05:25:00+00:00,1942-09-01T05:25:00+00:00,1906-01-01T05:25:00+00:00
+1941-10-01T05:30:00+00:00,1942-09-01T05:30:00+00:00,1906-01-01T05:30:00+00:00
+1941-10-01T05:35:00+00:00,1942-09-01T05:35:00+00:00,1906-01-01T05:35:00+00:00
+1941-10-01T05:40:00+00:00,1942-09-01T05:40:00+00:00,1906-01-01T05:40:00+00:00
+1941-10-01T05:45:00+00:00,1942-09-01T05:45:00+00:00,1906-01-01T05:45:00+00:00
+1941-10-01T05:50:00+00:00,1942-09-01T05:50:00+00:00,1906-01-01T05:50:00+00:00
+1941-10-01T05:55:00+00:00,1942-09-01T05:55:00+00:00,1906-01-01T05:55:00+00:00
+1941-10-01T06:00:00+00:00,1942-09-01T06:00:00+00:00,1906-01-01T06:00:00+00:00
+1941-10-01T06:05:00+00:00,1942-09-01T06:05:00+00:00,1906-01-01T06:05:00+00:00
+1941-10-01T06:10:00+00:00,1942-09-01T06:10:00+00:00,1906-01-01T06:10:00+00:00
+1941-10-01T06:15:00+00:00,1942-09-01T06:15:00+00:00,1906-01-01T06:15:00+00:00
+1941-10-01T06:20:00+00:00,1942-09-01T06:20:00+00:00,1906-01-01T06:20:00+00:00
+1941-10-01T06:25:00+00:00,1942-09-01T06:25:00+00:00,1906-01-01T06:25:00+00:00
+1941-10-01T06:30:00+00:00,1942-09-01T06:30:00+00:00,1906-01-01T06:30:00+00:00
+1941-10-01T06:35:00+00:00,1942-09-01T06:35:00+00:00,1906-01-01T06:35:00+00:00
+1941-10-01T06:40:00+00:00,1942-09-01T06:40:00+00:00,1906-01-01T06:40:00+00:00
+1941-10-01T06:45:00+00:00,1942-09-01T06:45:00+00:00,1906-01-01T06:45:00+00:00
+1941-10-01T06:50:00+00:00,1942-09-01T06:50:00+00:00,1906-01-01T06:50:00+00:00
+1941-10-01T06:55:00+00:00,1942-09-01T06:55:00+00:00,1906-01-01T06:55:00+00:00
+1941-10-01T07:00:00+00:00,1942-09-01T07:00:00+00:00,1906-01-01T07:00:00+00:00
+1941-10-01T07:05:00+00:00,1942-09-01T07:05:00+00:00,1906-01-01T07:05:00+00:00
+1941-10-01T07:10:00+00:00,1942-09-01T07:10:00+00:00,1906-01-01T07:10:00+00:00
+1941-10-01T07:15:00+00:00,1942-09-01T07:15:00+00:00,1906-01-01T07:15:00+00:00
+1941-10-01T07:20:00+00:00,1942-09-01T07:20:00+00:00,1906-01-01T07:20:00+00:00
+1941-10-01T07:25:00+00:00,1942-09-01T07:25:00+00:00,1906-01-01T07:25:00+00:00
+1941-10-01T07:30:00+00:00,1942-09-01T07:30:00+00:00,1906-01-01T07:30:00+00:00
+1941-10-01T07:35:00+00:00,1942-09-01T07:35:00+00:00,1906-01-01T07:35:00+00:00
+1941-10-01T07:40:00+00:00,1942-09-01T07:40:00+00:00,1906-01-01T07:40:00+00:00
+1941-10-01T07:45:00+00:00,1942-09-01T07:45:00+00:00,1906-01-01T07:45:00+00:00
+1941-10-01T07:50:00+00:00,1942-09-01T07:50:00+00:00,1906-01-01T07:50:00+00:00
+1941-10-01T07:55:00+00:00,1942-09-01T07:55:00+00:00,1906-01-01T07:55:00+00:00
+1941-10-01T08:00:00+00:00,1942-09-01T08:00:00+00:00,1906-01-01T08:00:00+00:00
+1941-10-01T08:05:00+00:00,1942-09-01T08:05:00+00:00,1906-01-01T08:05:00+00:00
+1941-10-01T08:10:00+00:00,1942-09-01T08:10:00+00:00,1906-01-01T08:10:00+00:00
+1941-10-01T08:15:00+00:00,1942-09-01T08:15:00+00:00,1906-01-01T08:15:00+00:00
+1941-10-01T08:20:00+00:00,1942-09-01T08:20:00+00:00,1906-01-01T08:20:00+00:00
+1941-10-01T08:25:00+00:00,1942-09-01T08:25:00+00:00,1906-01-01T08:25:00+00:00
+1941-10-01T08:30:00+00:00,1942-09-01T08:30:00+00:00,1906-01-01T08:30:00+00:00
+1941-10-01T08:35:00+00:00,1942-09-01T08:35:00+00:00,1906-01-01T08:35:00+00:00
+1941-10-01T08:40:00+00:00,1942-09-01T08:40:00+00:00,1906-01-01T08:40:00+00:00
+1941-10-01T08:45:00+00:00,1942-09-01T08:45:00+00:00,1906-01-01T08:45:00+00:00
+1941-10-01T08:50:00+00:00,1942-09-01T08:50:00+00:00,1906-01-01T08:50:00+00:00
+1941-10-01T08:55:00+00:00,1942-09-01T08:55:00+00:00,1906-01-01T08:55:00+00:00
+1941-10-01T09:00:00+00:00,1942-09-01T09:00:00+00:00,1906-01-01T09:00:00+00:00
+1941-10-01T09:05:00+00:00,1942-09-01T09:05:00+00:00,1906-01-01T09:05:00+00:00
+1941-10-01T09:10:00+00:00,1942-09-01T09:10:00+00:00,1906-01-01T09:10:00+00:00
+1941-10-01T09:15:00+00:00,1942-09-01T09:15:00+00:00,1906-01-01T09:15:00+00:00
+1941-10-01T09:20:00+00:00,1942-09-01T09:20:00+00:00,1906-01-01T09:20:00+00:00
+1941-10-01T09:25:00+00:00,1942-09-01T09:25:00+00:00,1906-01-01T09:25:00+00:00
+1941-10-01T09:30:00+00:00,1942-09-01T09:30:00+00:00,1906-01-01T09:30:00+00:00
+1941-10-01T09:35:00+00:00,1942-09-01T09:35:00+00:00,1906-01-01T09:35:00+00:00
+1941-10-01T09:40:00+00:00,1942-09-01T09:40:00+00:00,1906-01-01T09:40:00+00:00
+1941-10-01T09:45:00+00:00,1942-09-01T09:45:00+00:00,1906-01-01T09:45:00+00:00
+1941-10-01T09:50:00+00:00,1942-09-01T09:50:00+00:00,1906-01-01T09:50:00+00:00
+1941-10-01T09:55:00+00:00,1942-09-01T09:55:00+00:00,1906-01-01T09:55:00+00:00
+1941-10-01T10:00:00+00:00,1942-09-01T10:00:00+00:00,1906-01-01T10:00:00+00:00
+1941-10-01T10:05:00+00:00,1942-09-01T10:05:00+00:00,1906-01-01T10:05:00+00:00
+1941-10-01T10:10:00+00:00,1942-09-01T10:10:00+00:00,1906-01-01T10:10:00+00:00
+1941-10-01T10:15:00+00:00,1942-09-01T10:15:00+00:00,1906-01-01T10:15:00+00:00
+1941-10-01T10:20:00+00:00,1942-09-01T10:20:00+00:00,1906-01-01T10:20:00+00:00
+1941-10-01T10:25:00+00:00,1942-09-01T10:25:00+00:00,1906-01-01T10:25:00+00:00
+1941-10-01T10:30:00+00:00,1942-09-01T10:30:00+00:00,1906-01-01T10:30:00+00:00
+1941-10-01T10:35:00+00:00,1942-09-01T10:35:00+00:00,1906-01-01T10:35:00+00:00
+1941-10-01T10:40:00+00:00,1942-09-01T10:40:00+00:00,1906-01-01T10:40:00+00:00
+1941-10-01T10:45:00+00:00,1942-09-01T10:45:00+00:00,1906-01-01T10:45:00+00:00
+1941-10-01T10:50:00+00:00,1942-09-01T10:50:00+00:00,1906-01-01T10:50:00+00:00
+1941-10-01T10:55:00+00:00,1942-09-01T10:55:00+00:00,1906-01-01T10:55:00+00:00
+1941-10-01T11:00:00+00:00,1942-09-01T11:00:00+00:00,1906-01-01T11:00:00+00:00
+1941-10-01T11:05:00+00:00,1942-09-01T11:05:00+00:00,1906-01-01T11:05:00+00:00
+1941-10-01T11:10:00+00:00,1942-09-01T11:10:00+00:00,1906-01-01T11:10:00+00:00
+1941-10-01T11:15:00+00:00,1942-09-01T11:15:00+00:00,1906-01-01T11:15:00+00:00
+1941-10-01T11:20:00+00:00,1942-09-01T11:20:00+00:00,1906-01-01T11:20:00+00:00
+1941-10-01T11:25:00+00:00,1942-09-01T11:25:00+00:00,1906-01-01T11:25:00+00:00
+1941-10-01T11:30:00+00:00,1942-09-01T11:30:00+00:00,1906-01-01T11:30:00+00:00
+1941-10-01T11:35:00+00:00,1942-09-01T11:35:00+00:00,1906-01-01T11:35:00+00:00
+1941-10-01T11:40:00+00:00,1942-09-01T11:40:00+00:00,1906-01-01T11:40:00+00:00
+1941-10-01T11:45:00+00:00,1942-09-01T11:45:00+00:00,1906-01-01T11:45:00+00:00
+1941-10-01T11:50:00+00:00,1942-09-01T11:50:00+00:00,1906-01-01T11:50:00+00:00
+1941-10-01T11:55:00+00:00,1942-09-01T11:55:00+00:00,1906-01-01T11:55:00+00:00
+1941-10-01T12:00:00+00:00,1942-09-01T12:00:00+00:00,1906-01-01T12:00:00+00:00
+1941-10-01T12:05:00+00:00,1942-09-01T12:05:00+00:00,1906-01-01T12:05:00+00:00
+1941-10-01T12:10:00+00:00,1942-09-01T12:10:00+00:00,1906-01-01T12:10:00+00:00
+1941-10-01T12:15:00+00:00,1942-09-01T12:15:00+00:00,1906-01-01T12:15:00+00:00
+1941-10-01T12:20:00+00:00,1942-09-01T12:20:00+00:00,1906-01-01T12:20:00+00:00
+1941-10-01T12:25:00+00:00,1942-09-01T12:25:00+00:00,1906-01-01T12:25:00+00:00
+1941-10-01T12:30:00+00:00,1942-09-01T12:30:00+00:00,1906-01-01T12:30:00+00:00
+1941-10-01T12:35:00+00:00,1942-09-01T12:35:00+00:00,1906-01-01T12:35:00+00:00
+1941-10-01T12:40:00+00:00,1942-09-01T12:40:00+00:00,1906-01-01T12:40:00+00:00
+1941-10-01T12:45:00+00:00,1942-09-01T12:45:00+00:00,1906-01-01T12:45:00+00:00
+1941-10-01T12:50:00+00:00,1942-09-01T12:50:00+00:00,1906-01-01T12:50:00+00:00
+1941-10-01T12:55:00+00:00,1942-09-01T12:55:00+00:00,1906-01-01T12:55:00+00:00
+1941-10-01T13:00:00+00:00,1942-09-01T13:00:00+00:00,1906-01-01T13:00:00+00:00
+1941-10-01T13:05:00+00:00,1942-09-01T13:05:00+00:00,1906-01-01T13:05:00+00:00
+1941-10-01T13:10:00+00:00,1942-09-01T13:10:00+00:00,1906-01-01T13:10:00+00:00
+1941-10-01T13:15:00+00:00,1942-09-01T13:15:00+00:00,1906-01-01T13:15:00+00:00
+1941-10-01T13:20:00+00:00,1942-09-01T13:20:00+00:00,1906-01-01T13:20:00+00:00
+1941-10-01T13:25:00+00:00,1942-09-01T13:25:00+00:00,1906-01-01T13:25:00+00:00
+1941-10-01T13:30:00+00:00,1942-09-01T13:30:00+00:00,1906-01-01T13:30:00+00:00
+1941-10-01T13:35:00+00:00,1942-09-01T13:35:00+00:00,1906-01-01T13:35:00+00:00
+1941-10-01T13:40:00+00:00,1942-09-01T13:40:00+00:00,1906-01-01T13:40:00+00:00
+1941-10-01T13:45:00+00:00,1942-09-01T13:45:00+00:00,1906-01-01T13:45:00+00:00
+1941-10-01T13:50:00+00:00,1942-09-01T13:50:00+00:00,1906-01-01T13:50:00+00:00
+1941-10-01T13:55:00+00:00,1942-09-01T13:55:00+00:00,1906-01-01T13:55:00+00:00
+1941-10-01T14:00:00+00:00,1942-09-01T14:00:00+00:00,1906-01-01T14:00:00+00:00
+1941-10-01T14:05:00+00:00,1942-09-01T14:05:00+00:00,1906-01-01T14:05:00+00:00
+1941-10-01T14:10:00+00:00,1942-09-01T14:10:00+00:00,1906-01-01T14:10:00+00:00
+1941-10-01T14:15:00+00:00,1942-09-01T14:15:00+00:00,1906-01-01T14:15:00+00:00
+1941-10-01T14:20:00+00:00,1942-09-01T14:20:00+00:00,1906-01-01T14:20:00+00:00
+1941-10-01T14:25:00+00:00,1942-09-01T14:25:00+00:00,1906-01-01T14:25:00+00:00
+1941-10-01T14:30:00+00:00,1942-09-01T14:30:00+00:00,1906-01-01T14:30:00+00:00
+1941-10-01T14:35:00+00:00,1942-09-01T14:35:00+00:00,1906-01-01T14:35:00+00:00
+1941-10-01T14:40:00+00:00,1942-09-01T14:40:00+00:00,1906-01-01T14:40:00+00:00
+1941-10-01T14:45:00+00:00,1942-09-01T14:45:00+00:00,1906-01-01T14:45:00+00:00
+1941-10-01T14:50:00+00:00,1942-09-01T14:50:00+00:00,1906-01-01T14:50:00+00:00
+1941-10-01T14:55:00+00:00,1942-09-01T14:55:00+00:00,1906-01-01T14:55:00+00:00
+1941-10-01T15:00:00+00:00,1942-09-01T15:00:00+00:00,1906-01-01T15:00:00+00:00
+1941-10-01T15:05:00+00:00,1942-09-01T15:05:00+00:00,1906-01-01T15:05:00+00:00
+1941-10-01T15:10:00+00:00,1942-09-01T15:10:00+00:00,1906-01-01T15:10:00+00:00
+1941-10-01T15:15:00+00:00,1942-09-01T15:15:00+00:00,1906-01-01T15:15:00+00:00
+1941-10-01T15:20:00+00:00,1942-09-01T15:20:00+00:00,1906-01-01T15:20:00+00:00
+1941-10-01T15:25:00+00:00,1942-09-01T15:25:00+00:00,1906-01-01T15:25:00+00:00
+1941-10-01T15:30:00+00:00,1942-09-01T15:30:00+00:00,1906-01-01T15:30:00+00:00
+1941-10-01T15:35:00+00:00,1942-09-01T15:35:00+00:00,1906-01-01T15:35:00+00:00
+1941-10-01T15:40:00+00:00,1942-09-01T15:40:00+00:00,1906-01-01T15:40:00+00:00
+1941-10-01T15:45:00+00:00,1942-09-01T15:45:00+00:00,1906-01-01T15:45:00+00:00
+1941-10-01T15:50:00+00:00,1942-09-01T15:50:00+00:00,1906-01-01T15:50:00+00:00
+1941-10-01T15:55:00+00:00,1942-09-01T15:55:00+00:00,1906-01-01T15:55:00+00:00
+1941-10-01T16:00:00+00:00,1942-09-01T16:00:00+00:00,1906-01-01T16:00:00+00:00
+1941-10-01T16:05:00+00:00,1942-09-01T16:05:00+00:00,1906-01-01T16:05:00+00:00
+1941-10-01T16:10:00+00:00,1942-09-01T16:10:00+00:00,1906-01-01T16:10:00+00:00
+1941-10-01T16:15:00+00:00,1942-09-01T16:15:00+00:00,1906-01-01T16:15:00+00:00
+1941-10-01T16:20:00+00:00,1942-09-01T16:20:00+00:00,1906-01-01T16:20:00+00:00
+1941-10-01T16:25:00+00:00,1942-09-01T16:25:00+00:00,1906-01-01T16:25:00+00:00
+1941-10-01T16:30:00+00:00,1942-09-01T16:30:00+00:00,1906-01-01T16:30:00+00:00
+1941-10-01T16:35:00+00:00,1942-09-01T16:35:00+00:00,1906-01-01T16:35:00+00:00
+1941-10-01T16:40:00+00:00,1942-09-01T16:40:00+00:00,1906-01-01T16:40:00+00:00
+1941-10-01T16:45:00+00:00,1942-09-01T16:45:00+00:00,1906-01-01T16:45:00+00:00
+1941-10-01T16:50:00+00:00,1942-09-01T16:50:00+00:00,1906-01-01T16:50:00+00:00
+1941-10-01T16:55:00+00:00,1942-09-01T16:55:00+00:00,1906-01-01T16:55:00+00:00
+1941-10-01T17:00:00+00:00,1942-09-01T17:00:00+00:00,1906-01-01T17:00:00+00:00
+1941-10-01T17:05:00+00:00,1942-09-01T17:05:00+00:00,1906-01-01T17:05:00+00:00
+1941-10-01T17:10:00+00:00,1942-09-01T17:10:00+00:00,1906-01-01T17:10:00+00:00
+1941-10-01T17:15:00+00:00,1942-09-01T17:15:00+00:00,1906-01-01T17:15:00+00:00
+1941-10-01T17:20:00+00:00,1942-09-01T17:20:00+00:00,1906-01-01T17:20:00+00:00
+1941-10-01T17:25:00+00:00,1942-09-01T17:25:00+00:00,1906-01-01T17:25:00+00:00
+1941-10-01T17:30:00+00:00,1942-09-01T17:30:00+00:00,1906-01-01T17:30:00+00:00
+1941-10-01T17:35:00+00:00,1942-09-01T17:35:00+00:00,1906-01-01T17:35:00+00:00
+1941-10-01T17:40:00+00:00,1942-09-01T17:40:00+00:00,1906-01-01T17:40:00+00:00
+1941-10-01T17:45:00+00:00,1942-09-01T17:45:00+00:00,1906-01-01T17:45:00+00:00
+1941-10-01T17:50:00+00:00,1942-09-01T17:50:00+00:00,1906-01-01T17:50:00+00:00
+1941-10-01T17:55:00+00:00,1942-09-01T17:55:00+00:00,1906-01-01T17:55:00+00:00
+1941-10-01T18:00:00+00:00,1942-09-01T18:00:00+00:00,1906-01-01T18:00:00+00:00
+1941-10-01T18:05:00+00:00,1942-09-01T18:05:00+00:00,1906-01-01T18:05:00+00:00
+1941-10-01T18:10:00+00:00,1942-09-01T18:10:00+00:00,1906-01-01T18:10:00+00:00
+1941-10-01T18:15:00+00:00,1942-09-01T18:15:00+00:00,1906-01-01T18:15:00+00:00
+1941-10-01T18:20:00+00:00,1942-09-01T18:20:00+00:00,1906-01-01T18:20:00+00:00
+1941-10-01T18:25:00+00:00,1942-09-01T18:25:00+00:00,1906-01-01T18:25:00+00:00
+1941-10-01T18:30:00+00:00,1942-09-01T18:30:00+00:00,1906-01-01T18:30:00+00:00
+1941-10-01T18:35:00+00:00,1942-09-01T18:35:00+00:00,1906-01-01T18:35:00+00:00
+1941-10-01T18:40:00+00:00,1942-09-01T18:40:00+00:00,1906-01-01T18:40:00+00:00
+1941-10-01T18:45:00+00:00,1942-09-01T18:45:00+00:00,1906-01-01T18:45:00+00:00
+1941-10-01T18:50:00+00:00,1942-09-01T18:50:00+00:00,1906-01-01T18:50:00+00:00
+1941-10-01T18:55:00+00:00,1942-09-01T18:55:00+00:00,1906-01-01T18:55:00+00:00
+1941-10-01T19:00:00+00:00,1942-09-01T19:00:00+00:00,1906-01-01T19:00:00+00:00
+1941-10-01T19:05:00+00:00,1942-09-01T19:05:00+00:00,1906-01-01T19:05:00+00:00
+1941-10-01T19:10:00+00:00,1942-09-01T19:10:00+00:00,1906-01-01T19:10:00+00:00
+1941-10-01T19:15:00+00:00,1942-09-01T19:15:00+00:00,1906-01-01T19:15:00+00:00
+1941-10-01T19:20:00+00:00,1942-09-01T19:20:00+00:00,1906-01-01T19:20:00+00:00
+1941-10-01T19:25:00+00:00,1942-09-01T19:25:00+00:00,1906-01-01T19:25:00+00:00
+1941-10-01T19:30:00+00:00,1942-09-01T19:30:00+00:00,1906-01-01T19:30:00+00:00
+1941-10-01T19:35:00+00:00,1942-09-01T19:35:00+00:00,1906-01-01T19:35:00+00:00
+1941-10-01T19:40:00+00:00,1942-09-01T19:40:00+00:00,1906-01-01T19:40:00+00:00
+1941-10-01T19:45:00+00:00,1942-09-01T19:45:00+00:00,1906-01-01T19:45:00+00:00
+1941-10-01T19:50:00+00:00,1942-09-01T19:50:00+00:00,1906-01-01T19:50:00+00:00
+1941-10-01T19:55:00+00:00,1942-09-01T19:55:00+00:00,1906-01-01T19:55:00+00:00
+1941-10-01T20:00:00+00:00,1942-09-01T20:00:00+00:00,1906-01-01T20:00:00+00:00
+1941-10-01T20:05:00+00:00,1942-09-01T20:05:00+00:00,1906-01-01T20:05:00+00:00
+1941-10-01T20:10:00+00:00,1942-09-01T20:10:00+00:00,1906-01-01T20:10:00+00:00
+1941-10-01T20:15:00+00:00,1942-09-01T20:15:00+00:00,1906-01-01T20:15:00+00:00
+1941-10-01T20:20:00+00:00,1942-09-01T20:20:00+00:00,1906-01-01T20:20:00+00:00
+1941-10-01T20:25:00+00:00,1942-09-01T20:25:00+00:00,1906-01-01T20:25:00+00:00
+1941-10-01T20:30:00+00:00,1942-09-01T20:30:00+00:00,1906-01-01T20:30:00+00:00
+1941-10-01T20:35:00+00:00,1942-09-01T20:35:00+00:00,1906-01-01T20:35:00+00:00
+1941-10-01T20:40:00+00:00,1942-09-01T20:40:00+00:00,1906-01-01T20:40:00+00:00
+1941-10-01T20:45:00+00:00,1942-09-01T20:45:00+00:00,1906-01-01T20:45:00+00:00
+1941-10-01T20:50:00+00:00,1942-09-01T20:50:00+00:00,1906-01-01T20:50:00+00:00
+1941-10-01T20:55:00+00:00,1942-09-01T20:55:00+00:00,1906-01-01T20:55:00+00:00
+1941-10-01T21:00:00+00:00,1942-09-01T21:00:00+00:00,1906-01-01T21:00:00+00:00
+1941-10-01T21:05:00+00:00,1942-09-01T21:05:00+00:00,1906-01-01T21:05:00+00:00
+1941-10-01T21:10:00+00:00,1942-09-01T21:10:00+00:00,1906-01-01T21:10:00+00:00
+1941-10-01T21:15:00+00:00,1942-09-01T21:15:00+00:00,1906-01-01T21:15:00+00:00
+1941-10-01T21:20:00+00:00,1942-09-01T21:20:00+00:00,1906-01-01T21:20:00+00:00
+1941-10-01T21:25:00+00:00,1942-09-01T21:25:00+00:00,1906-01-01T21:25:00+00:00
+1941-10-01T21:30:00+00:00,1942-09-01T21:30:00+00:00,1906-01-01T21:30:00+00:00
+1941-10-01T21:35:00+00:00,1942-09-01T21:35:00+00:00,1906-01-01T21:35:00+00:00
+1941-10-01T21:40:00+00:00,1942-09-01T21:40:00+00:00,1906-01-01T21:40:00+00:00
+1941-10-01T21:45:00+00:00,1942-09-01T21:45:00+00:00,1906-01-01T21:45:00+00:00
+1941-10-01T21:50:00+00:00,1942-09-01T21:50:00+00:00,1906-01-01T21:50:00+00:00
+1941-10-01T21:55:00+00:00,1942-09-01T21:55:00+00:00,1906-01-01T21:55:00+00:00
+1941-10-01T22:00:00+00:00,1942-09-01T22:00:00+00:00,1906-01-01T22:00:00+00:00
+1941-10-01T22:05:00+00:00,1942-09-01T22:05:00+00:00,1906-01-01T22:05:00+00:00
+1941-10-01T22:10:00+00:00,1942-09-01T22:10:00+00:00,1906-01-01T22:10:00+00:00
+1941-10-01T22:15:00+00:00,1942-09-01T22:15:00+00:00,1906-01-01T22:15:00+00:00
+1941-10-01T22:20:00+00:00,1942-09-01T22:20:00+00:00,1906-01-01T22:20:00+00:00
+1941-10-01T22:25:00+00:00,1942-09-01T22:25:00+00:00,1906-01-01T22:25:00+00:00
+1941-10-01T22:30:00+00:00,1942-09-01T22:30:00+00:00,1906-01-01T22:30:00+00:00
+1941-10-01T22:35:00+00:00,1942-09-01T22:35:00+00:00,1906-01-01T22:35:00+00:00
+1941-10-01T22:40:00+00:00,1942-09-01T22:40:00+00:00,1906-01-01T22:40:00+00:00
+1941-10-01T22:45:00+00:00,1942-09-01T22:45:00+00:00,1906-01-01T22:45:00+00:00
+1941-10-01T22:50:00+00:00,1942-09-01T22:50:00+00:00,1906-01-01T22:50:00+00:00
+1941-10-01T22:55:00+00:00,1942-09-01T22:55:00+00:00,1906-01-01T22:55:00+00:00
+1941-10-01T23:00:00+00:00,1942-09-01T23:00:00+00:00,1906-01-01T23:00:00+00:00
+1941-10-01T23:05:00+00:00,1942-09-01T23:05:00+00:00,1906-01-01T23:05:00+00:00
+1941-10-01T23:10:00+00:00,1942-09-01T23:10:00+00:00,1906-01-01T23:10:00+00:00
+1941-10-01T23:15:00+00:00,1942-09-01T23:15:00+00:00,1906-01-01T23:15:00+00:00
+1941-10-01T23:20:00+00:00,1942-09-01T23:20:00+00:00,1906-01-01T23:20:00+00:00
+1941-10-01T23:25:00+00:00,1942-09-01T23:25:00+00:00,1906-01-01T23:25:00+00:00
+1941-10-01T23:30:00+00:00,1942-09-01T23:30:00+00:00,1906-01-01T23:30:00+00:00
+1941-10-01T23:35:00+00:00,1942-09-01T23:35:00+00:00,1906-01-01T23:35:00+00:00
+1941-10-01T23:40:00+00:00,1942-09-01T23:40:00+00:00,1906-01-01T23:40:00+00:00
+1941-10-01T23:45:00+00:00,1942-09-01T23:45:00+00:00,1906-01-01T23:45:00+00:00
+1941-10-01T23:50:00+00:00,1942-09-01T23:50:00+00:00,1906-01-01T23:50:00+00:00
+1941-10-01T23:55:00+00:00,1942-09-01T23:55:00+00:00,1906-01-01T23:55:00+00:00
+1941-10-02,1942-09-02,1906-01-02
+1941-10-02T00:05:00+00:00,1942-09-02T00:05:00+00:00,1906-01-02T00:05:00+00:00
+1941-10-02T00:10:00+00:00,1942-09-02T00:10:00+00:00,1906-01-02T00:10:00+00:00
+1941-10-02T00:15:00+00:00,1942-09-02T00:15:00+00:00,1906-01-02T00:15:00+00:00
+1941-10-02T00:20:00+00:00,1942-09-02T00:20:00+00:00,1906-01-02T00:20:00+00:00
+1941-10-02T00:25:00+00:00,1942-09-02T00:25:00+00:00,1906-01-02T00:25:00+00:00
+1941-10-02T00:30:00+00:00,1942-09-02T00:30:00+00:00,1906-01-02T00:30:00+00:00
+1941-10-02T00:35:00+00:00,1942-09-02T00:35:00+00:00,1906-01-02T00:35:00+00:00
+1941-10-02T00:40:00+00:00,1942-09-02T00:40:00+00:00,1906-01-02T00:40:00+00:00
+1941-10-02T00:45:00+00:00,1942-09-02T00:45:00+00:00,1906-01-02T00:45:00+00:00
+1941-10-02T00:50:00+00:00,1942-09-02T00:50:00+00:00,1906-01-02T00:50:00+00:00
+1941-10-02T00:55:00+00:00,1942-09-02T00:55:00+00:00,1906-01-02T00:55:00+00:00
+1941-10-02T01:00:00+00:00,1942-09-02T01:00:00+00:00,1906-01-02T01:00:00+00:00
+1941-10-02T01:05:00+00:00,1942-09-02T01:05:00+00:00,1906-01-02T01:05:00+00:00
+1941-10-02T01:10:00+00:00,1942-09-02T01:10:00+00:00,1906-01-02T01:10:00+00:00
+1941-10-02T01:15:00+00:00,1942-09-02T01:15:00+00:00,1906-01-02T01:15:00+00:00
+1941-10-02T01:20:00+00:00,1942-09-02T01:20:00+00:00,1906-01-02T01:20:00+00:00
+1941-10-02T01:25:00+00:00,1942-09-02T01:25:00+00:00,1906-01-02T01:25:00+00:00
+1941-10-02T01:30:00+00:00,1942-09-02T01:30:00+00:00,1906-01-02T01:30:00+00:00
+1941-10-02T01:35:00+00:00,1942-09-02T01:35:00+00:00,1906-01-02T01:35:00+00:00
+1941-10-02T01:40:00+00:00,1942-09-02T01:40:00+00:00,1906-01-02T01:40:00+00:00
+1941-10-02T01:45:00+00:00,1942-09-02T01:45:00+00:00,1906-01-02T01:45:00+00:00
+1941-10-02T01:50:00+00:00,1942-09-02T01:50:00+00:00,1906-01-02T01:50:00+00:00
+1941-10-02T01:55:00+00:00,1942-09-02T01:55:00+00:00,1906-01-02T01:55:00+00:00
+1941-10-02T02:00:00+00:00,1942-09-02T02:00:00+00:00,1906-01-02T02:00:00+00:00
+1941-10-02T02:05:00+00:00,1942-09-02T02:05:00+00:00,1906-01-02T02:05:00+00:00
+1941-10-02T02:10:00+00:00,1942-09-02T02:10:00+00:00,1906-01-02T02:10:00+00:00
+1941-10-02T02:15:00+00:00,1942-09-02T02:15:00+00:00,1906-01-02T02:15:00+00:00
+1941-10-02T02:20:00+00:00,1942-09-02T02:20:00+00:00,1906-01-02T02:20:00+00:00
+1941-10-02T02:25:00+00:00,1942-09-02T02:25:00+00:00,1906-01-02T02:25:00+00:00
+1941-10-02T02:30:00+00:00,1942-09-02T02:30:00+00:00,1906-01-02T02:30:00+00:00
+1941-10-02T02:35:00+00:00,1942-09-02T02:35:00+00:00,1906-01-02T02:35:00+00:00
+1941-10-02T02:40:00+00:00,1942-09-02T02:40:00+00:00,1906-01-02T02:40:00+00:00
+1941-10-02T02:45:00+00:00,1942-09-02T02:45:00+00:00,1906-01-02T02:45:00+00:00
+1941-10-02T02:50:00+00:00,1942-09-02T02:50:00+00:00,1906-01-02T02:50:00+00:00
+1941-10-02T02:55:00+00:00,1942-09-02T02:55:00+00:00,1906-01-02T02:55:00+00:00
+1941-10-02T03:00:00+00:00,1942-09-02T03:00:00+00:00,1906-01-02T03:00:00+00:00
+1941-10-02T03:05:00+00:00,1942-09-02T03:05:00+00:00,1906-01-02T03:05:00+00:00
+1941-10-02T03:10:00+00:00,1942-09-02T03:10:00+00:00,1906-01-02T03:10:00+00:00
+1941-10-02T03:15:00+00:00,1942-09-02T03:15:00+00:00,1906-01-02T03:15:00+00:00
+1941-10-02T03:20:00+00:00,1942-09-02T03:20:00+00:00,1906-01-02T03:20:00+00:00
+1941-10-02T03:25:00+00:00,1942-09-02T03:25:00+00:00,1906-01-02T03:25:00+00:00
+1941-10-02T03:30:00+00:00,1942-09-02T03:30:00+00:00,1906-01-02T03:30:00+00:00
+1941-10-02T03:35:00+00:00,1942-09-02T03:35:00+00:00,1906-01-02T03:35:00+00:00
+1941-10-02T03:40:00+00:00,1942-09-02T03:40:00+00:00,1906-01-02T03:40:00+00:00
+1941-10-02T03:45:00+00:00,1942-09-02T03:45:00+00:00,1906-01-02T03:45:00+00:00
+1941-10-02T03:50:00+00:00,1942-09-02T03:50:00+00:00,1906-01-02T03:50:00+00:00
+1941-10-02T03:55:00+00:00,1942-09-02T03:55:00+00:00,1906-01-02T03:55:00+00:00
+1941-10-02T04:00:00+00:00,1942-09-02T04:00:00+00:00,1906-01-02T04:00:00+00:00
+1941-10-02T04:05:00+00:00,1942-09-02T04:05:00+00:00,1906-01-02T04:05:00+00:00
+1941-10-02T04:10:00+00:00,1942-09-02T04:10:00+00:00,1906-01-02T04:10:00+00:00
+1941-10-02T04:15:00+00:00,1942-09-02T04:15:00+00:00,1906-01-02T04:15:00+00:00
+1941-10-02T04:20:00+00:00,1942-09-02T04:20:00+00:00,1906-01-02T04:20:00+00:00
+1941-10-02T04:25:00+00:00,1942-09-02T04:25:00+00:00,1906-01-02T04:25:00+00:00
+1941-10-02T04:30:00+00:00,1942-09-02T04:30:00+00:00,1906-01-02T04:30:00+00:00
+1941-10-02T04:35:00+00:00,1942-09-02T04:35:00+00:00,1906-01-02T04:35:00+00:00
+1941-10-02T04:40:00+00:00,1942-09-02T04:40:00+00:00,1906-01-02T04:40:00+00:00
+1941-10-02T04:45:00+00:00,1942-09-02T04:45:00+00:00,1906-01-02T04:45:00+00:00
+1941-10-02T04:50:00+00:00,1942-09-02T04:50:00+00:00,1906-01-02T04:50:00+00:00
+1941-10-02T04:55:00+00:00,1942-09-02T04:55:00+00:00,1906-01-02T04:55:00+00:00
+1941-10-02T05:00:00+00:00,1942-09-02T05:00:00+00:00,1906-01-02T05:00:00+00:00
+1941-10-02T05:05:00+00:00,1942-09-02T05:05:00+00:00,1906-01-02T05:05:00+00:00
+1941-10-02T05:10:00+00:00,1942-09-02T05:10:00+00:00,1906-01-02T05:10:00+00:00
+1941-10-02T05:15:00+00:00,1942-09-02T05:15:00+00:00,1906-01-02T05:15:00+00:00
+1941-10-02T05:20:00+00:00,1942-09-02T05:20:00+00:00,1906-01-02T05:20:00+00:00
+1941-10-02T05:25:00+00:00,1942-09-02T05:25:00+00:00,1906-01-02T05:25:00+00:00
+1941-10-02T05:30:00+00:00,1942-09-02T05:30:00+00:00,1906-01-02T05:30:00+00:00
+1941-10-02T05:35:00+00:00,1942-09-02T05:35:00+00:00,1906-01-02T05:35:00+00:00
+1941-10-02T05:40:00+00:00,1942-09-02T05:40:00+00:00,1906-01-02T05:40:00+00:00
+1941-10-02T05:45:00+00:00,1942-09-02T05:45:00+00:00,1906-01-02T05:45:00+00:00
+1941-10-02T05:50:00+00:00,1942-09-02T05:50:00+00:00,1906-01-02T05:50:00+00:00
+1941-10-02T05:55:00+00:00,1942-09-02T05:55:00+00:00,1906-01-02T05:55:00+00:00
+1941-10-02T06:00:00+00:00,1942-09-02T06:00:00+00:00,1906-01-02T06:00:00+00:00
+1941-10-02T06:05:00+00:00,1942-09-02T06:05:00+00:00,1906-01-02T06:05:00+00:00
+1941-10-02T06:10:00+00:00,1942-09-02T06:10:00+00:00,1906-01-02T06:10:00+00:00
+1941-10-02T06:15:00+00:00,1942-09-02T06:15:00+00:00,1906-01-02T06:15:00+00:00
+1941-10-02T06:20:00+00:00,1942-09-02T06:20:00+00:00,1906-01-02T06:20:00+00:00
+1941-10-02T06:25:00+00:00,1942-09-02T06:25:00+00:00,1906-01-02T06:25:00+00:00
+1941-10-02T06:30:00+00:00,1942-09-02T06:30:00+00:00,1906-01-02T06:30:00+00:00
+1941-10-02T06:35:00+00:00,1942-09-02T06:35:00+00:00,1906-01-02T06:35:00+00:00
+1941-10-02T06:40:00+00:00,1942-09-02T06:40:00+00:00,1906-01-02T06:40:00+00:00
+1941-10-02T06:45:00+00:00,1942-09-02T06:45:00+00:00,1906-01-02T06:45:00+00:00
+1941-10-02T06:50:00+00:00,1942-09-02T06:50:00+00:00,1906-01-02T06:50:00+00:00
+1941-10-02T06:55:00+00:00,1942-09-02T06:55:00+00:00,1906-01-02T06:55:00+00:00
+1941-10-02T07:00:00+00:00,1942-09-02T07:00:00+00:00,1906-01-02T07:00:00+00:00
+1941-10-02T07:05:00+00:00,1942-09-02T07:05:00+00:00,1906-01-02T07:05:00+00:00
+1941-10-02T07:10:00+00:00,1942-09-02T07:10:00+00:00,1906-01-02T07:10:00+00:00
+1941-10-02T07:15:00+00:00,1942-09-02T07:15:00+00:00,1906-01-02T07:15:00+00:00
+1941-10-02T07:20:00+00:00,1942-09-02T07:20:00+00:00,1906-01-02T07:20:00+00:00
+1941-10-02T07:25:00+00:00,1942-09-02T07:25:00+00:00,1906-01-02T07:25:00+00:00
+1941-10-02T07:30:00+00:00,1942-09-02T07:30:00+00:00,1906-01-02T07:30:00+00:00
+1941-10-02T07:35:00+00:00,1942-09-02T07:35:00+00:00,1906-01-02T07:35:00+00:00
+1941-10-02T07:40:00+00:00,1942-09-02T07:40:00+00:00,1906-01-02T07:40:00+00:00
+1941-10-02T07:45:00+00:00,1942-09-02T07:45:00+00:00,1906-01-02T07:45:00+00:00
+1941-10-02T07:50:00+00:00,1942-09-02T07:50:00+00:00,1906-01-02T07:50:00+00:00
+1941-10-02T07:55:00+00:00,1942-09-02T07:55:00+00:00,1906-01-02T07:55:00+00:00
+1941-10-02T08:00:00+00:00,1942-09-02T08:00:00+00:00,1906-01-02T08:00:00+00:00
+1941-10-02T08:05:00+00:00,1942-09-02T08:05:00+00:00,1906-01-02T08:05:00+00:00
+1941-10-02T08:10:00+00:00,1942-09-02T08:10:00+00:00,1906-01-02T08:10:00+00:00
+1941-10-02T08:15:00+00:00,1942-09-02T08:15:00+00:00,1906-01-02T08:15:00+00:00
+1941-10-02T08:20:00+00:00,1942-09-02T08:20:00+00:00,1906-01-02T08:20:00+00:00
+1941-10-02T08:25:00+00:00,1942-09-02T08:25:00+00:00,1906-01-02T08:25:00+00:00
+1941-10-02T08:30:00+00:00,1942-09-02T08:30:00+00:00,1906-01-02T08:30:00+00:00
+1941-10-02T08:35:00+00:00,1942-09-02T08:35:00+00:00,1906-01-02T08:35:00+00:00
+1941-10-02T08:40:00+00:00,1942-09-02T08:40:00+00:00,1906-01-02T08:40:00+00:00
+1941-10-02T08:45:00+00:00,1942-09-02T08:45:00+00:00,1906-01-02T08:45:00+00:00
+1941-10-02T08:50:00+00:00,1942-09-02T08:50:00+00:00,1906-01-02T08:50:00+00:00
+1941-10-02T08:55:00+00:00,1942-09-02T08:55:00+00:00,1906-01-02T08:55:00+00:00
+1941-10-02T09:00:00+00:00,1942-09-02T09:00:00+00:00,1906-01-02T09:00:00+00:00
+1941-10-02T09:05:00+00:00,1942-09-02T09:05:00+00:00,1906-01-02T09:05:00+00:00
+1941-10-02T09:10:00+00:00,1942-09-02T09:10:00+00:00,1906-01-02T09:10:00+00:00
+1941-10-02T09:15:00+00:00,1942-09-02T09:15:00+00:00,1906-01-02T09:15:00+00:00
+1941-10-02T09:20:00+00:00,1942-09-02T09:20:00+00:00,1906-01-02T09:20:00+00:00
+1941-10-02T09:25:00+00:00,1942-09-02T09:25:00+00:00,1906-01-02T09:25:00+00:00
+1941-10-02T09:30:00+00:00,1942-09-02T09:30:00+00:00,1906-01-02T09:30:00+00:00
+1941-10-02T09:35:00+00:00,1942-09-02T09:35:00+00:00,1906-01-02T09:35:00+00:00
+1941-10-02T09:40:00+00:00,1942-09-02T09:40:00+00:00,1906-01-02T09:40:00+00:00
+1941-10-02T09:45:00+00:00,1942-09-02T09:45:00+00:00,1906-01-02T09:45:00+00:00
+1941-10-02T09:50:00+00:00,1942-09-02T09:50:00+00:00,1906-01-02T09:50:00+00:00
+1941-10-02T09:55:00+00:00,1942-09-02T09:55:00+00:00,1906-01-02T09:55:00+00:00
+1941-10-02T10:00:00+00:00,1942-09-02T10:00:00+00:00,1906-01-02T10:00:00+00:00
+1941-10-02T10:05:00+00:00,1942-09-02T10:05:00+00:00,1906-01-02T10:05:00+00:00
+1941-10-02T10:10:00+00:00,1942-09-02T10:10:00+00:00,1906-01-02T10:10:00+00:00
+1941-10-02T10:15:00+00:00,1942-09-02T10:15:00+00:00,1906-01-02T10:15:00+00:00
+1941-10-02T10:20:00+00:00,1942-09-02T10:20:00+00:00,1906-01-02T10:20:00+00:00
+1941-10-02T10:25:00+00:00,1942-09-02T10:25:00+00:00,1906-01-02T10:25:00+00:00
+1941-10-02T10:30:00+00:00,1942-09-02T10:30:00+00:00,1906-01-02T10:30:00+00:00
+1941-10-02T10:35:00+00:00,1942-09-02T10:35:00+00:00,1906-01-02T10:35:00+00:00
+1941-10-02T10:40:00+00:00,1942-09-02T10:40:00+00:00,1906-01-02T10:40:00+00:00
+1941-10-02T10:45:00+00:00,1942-09-02T10:45:00+00:00,1906-01-02T10:45:00+00:00
+1941-10-02T10:50:00+00:00,1942-09-02T10:50:00+00:00,1906-01-02T10:50:00+00:00
+1941-10-02T10:55:00+00:00,1942-09-02T10:55:00+00:00,1906-01-02T10:55:00+00:00
+1941-10-02T11:00:00+00:00,1942-09-02T11:00:00+00:00,1906-01-02T11:00:00+00:00
+1941-10-02T11:05:00+00:00,1942-09-02T11:05:00+00:00,1906-01-02T11:05:00+00:00
+1941-10-02T11:10:00+00:00,1942-09-02T11:10:00+00:00,1906-01-02T11:10:00+00:00
+1941-10-02T11:15:00+00:00,1942-09-02T11:15:00+00:00,1906-01-02T11:15:00+00:00
+1941-10-02T11:20:00+00:00,1942-09-02T11:20:00+00:00,1906-01-02T11:20:00+00:00
+1941-10-02T11:25:00+00:00,1942-09-02T11:25:00+00:00,1906-01-02T11:25:00+00:00
+1941-10-02T11:30:00+00:00,1942-09-02T11:30:00+00:00,1906-01-02T11:30:00+00:00
+1941-10-02T11:35:00+00:00,1942-09-02T11:35:00+00:00,1906-01-02T11:35:00+00:00
+1941-10-02T11:40:00+00:00,1942-09-02T11:40:00+00:00,1906-01-02T11:40:00+00:00
+1941-10-02T11:45:00+00:00,1942-09-02T11:45:00+00:00,1906-01-02T11:45:00+00:00
+1941-10-02T11:50:00+00:00,1942-09-02T11:50:00+00:00,1906-01-02T11:50:00+00:00
+1941-10-02T11:55:00+00:00,1942-09-02T11:55:00+00:00,1906-01-02T11:55:00+00:00
+1941-10-02T12:00:00+00:00,1942-09-02T12:00:00+00:00,1906-01-02T12:00:00+00:00
+1941-10-02T12:05:00+00:00,1942-09-02T12:05:00+00:00,1906-01-02T12:05:00+00:00
+1941-10-02T12:10:00+00:00,1942-09-02T12:10:00+00:00,1906-01-02T12:10:00+00:00
+1941-10-02T12:15:00+00:00,1942-09-02T12:15:00+00:00,1906-01-02T12:15:00+00:00
+1941-10-02T12:20:00+00:00,1942-09-02T12:20:00+00:00,1906-01-02T12:20:00+00:00
+1941-10-02T12:25:00+00:00,1942-09-02T12:25:00+00:00,1906-01-02T12:25:00+00:00
+1941-10-02T12:30:00+00:00,1942-09-02T12:30:00+00:00,1906-01-02T12:30:00+00:00
+1941-10-02T12:35:00+00:00,1942-09-02T12:35:00+00:00,1906-01-02T12:35:00+00:00
+1941-10-02T12:40:00+00:00,1942-09-02T12:40:00+00:00,1906-01-02T12:40:00+00:00
+1941-10-02T12:45:00+00:00,1942-09-02T12:45:00+00:00,1906-01-02T12:45:00+00:00
+1941-10-02T12:50:00+00:00,1942-09-02T12:50:00+00:00,1906-01-02T12:50:00+00:00
+1941-10-02T12:55:00+00:00,1942-09-02T12:55:00+00:00,1906-01-02T12:55:00+00:00
+1941-10-02T13:00:00+00:00,1942-09-02T13:00:00+00:00,1906-01-02T13:00:00+00:00
+1941-10-02T13:05:00+00:00,1942-09-02T13:05:00+00:00,1906-01-02T13:05:00+00:00
+1941-10-02T13:10:00+00:00,1942-09-02T13:10:00+00:00,1906-01-02T13:10:00+00:00
+1941-10-02T13:15:00+00:00,1942-09-02T13:15:00+00:00,1906-01-02T13:15:00+00:00
+1941-10-02T13:20:00+00:00,1942-09-02T13:20:00+00:00,1906-01-02T13:20:00+00:00
+1941-10-02T13:25:00+00:00,1942-09-02T13:25:00+00:00,1906-01-02T13:25:00+00:00
+1941-10-02T13:30:00+00:00,1942-09-02T13:30:00+00:00,1906-01-02T13:30:00+00:00
+1941-10-02T13:35:00+00:00,1942-09-02T13:35:00+00:00,1906-01-02T13:35:00+00:00
+1941-10-02T13:40:00+00:00,1942-09-02T13:40:00+00:00,1906-01-02T13:40:00+00:00
+1941-10-02T13:45:00+00:00,1942-09-02T13:45:00+00:00,1906-01-02T13:45:00+00:00
+1941-10-02T13:50:00+00:00,1942-09-02T13:50:00+00:00,1906-01-02T13:50:00+00:00
+1941-10-02T13:55:00+00:00,1942-09-02T13:55:00+00:00,1906-01-02T13:55:00+00:00
+1941-10-02T14:00:00+00:00,1942-09-02T14:00:00+00:00,1906-01-02T14:00:00+00:00
+1941-10-02T14:05:00+00:00,1942-09-02T14:05:00+00:00,1906-01-02T14:05:00+00:00
+1941-10-02T14:10:00+00:00,1942-09-02T14:10:00+00:00,1906-01-02T14:10:00+00:00
+1941-10-02T14:15:00+00:00,1942-09-02T14:15:00+00:00,1906-01-02T14:15:00+00:00
+1941-10-02T14:20:00+00:00,1942-09-02T14:20:00+00:00,1906-01-02T14:20:00+00:00
+1941-10-02T14:25:00+00:00,1942-09-02T14:25:00+00:00,1906-01-02T14:25:00+00:00
+1941-10-02T14:30:00+00:00,1942-09-02T14:30:00+00:00,1906-01-02T14:30:00+00:00
+1941-10-02T14:35:00+00:00,1942-09-02T14:35:00+00:00,1906-01-02T14:35:00+00:00
+1941-10-02T14:40:00+00:00,1942-09-02T14:40:00+00:00,1906-01-02T14:40:00+00:00
+1941-10-02T14:45:00+00:00,1942-09-02T14:45:00+00:00,1906-01-02T14:45:00+00:00
+1941-10-02T14:50:00+00:00,1942-09-02T14:50:00+00:00,1906-01-02T14:50:00+00:00
+1941-10-02T14:55:00+00:00,1942-09-02T14:55:00+00:00,1906-01-02T14:55:00+00:00
+1941-10-02T15:00:00+00:00,1942-09-02T15:00:00+00:00,1906-01-02T15:00:00+00:00
+1941-10-02T15:05:00+00:00,1942-09-02T15:05:00+00:00,1906-01-02T15:05:00+00:00
+1941-10-02T15:10:00+00:00,1942-09-02T15:10:00+00:00,1906-01-02T15:10:00+00:00
+1941-10-02T15:15:00+00:00,1942-09-02T15:15:00+00:00,1906-01-02T15:15:00+00:00
+1941-10-02T15:20:00+00:00,1942-09-02T15:20:00+00:00,1906-01-02T15:20:00+00:00
+1941-10-02T15:25:00+00:00,1942-09-02T15:25:00+00:00,1906-01-02T15:25:00+00:00
+1941-10-02T15:30:00+00:00,1942-09-02T15:30:00+00:00,1906-01-02T15:30:00+00:00
+1941-10-02T15:35:00+00:00,1942-09-02T15:35:00+00:00,1906-01-02T15:35:00+00:00
+1941-10-02T15:40:00+00:00,1942-09-02T15:40:00+00:00,1906-01-02T15:40:00+00:00
+1941-10-02T15:45:00+00:00,1942-09-02T15:45:00+00:00,1906-01-02T15:45:00+00:00
+1941-10-02T15:50:00+00:00,1942-09-02T15:50:00+00:00,1906-01-02T15:50:00+00:00
+1941-10-02T15:55:00+00:00,1942-09-02T15:55:00+00:00,1906-01-02T15:55:00+00:00
+1941-10-02T16:00:00+00:00,1942-09-02T16:00:00+00:00,1906-01-02T16:00:00+00:00
+1941-10-02T16:05:00+00:00,1942-09-02T16:05:00+00:00,1906-01-02T16:05:00+00:00
+1941-10-02T16:10:00+00:00,1942-09-02T16:10:00+00:00,1906-01-02T16:10:00+00:00
+1941-10-02T16:15:00+00:00,1942-09-02T16:15:00+00:00,1906-01-02T16:15:00+00:00
+1941-10-02T16:20:00+00:00,1942-09-02T16:20:00+00:00,1906-01-02T16:20:00+00:00
+1941-10-02T16:25:00+00:00,1942-09-02T16:25:00+00:00,1906-01-02T16:25:00+00:00
+1941-10-02T16:30:00+00:00,1942-09-02T16:30:00+00:00,1906-01-02T16:30:00+00:00
+1941-10-02T16:35:00+00:00,1942-09-02T16:35:00+00:00,1906-01-02T16:35:00+00:00
+1941-10-02T16:40:00+00:00,1942-09-02T16:40:00+00:00,1906-01-02T16:40:00+00:00
+1941-10-02T16:45:00+00:00,1942-09-02T16:45:00+00:00,1906-01-02T16:45:00+00:00
+1941-10-02T16:50:00+00:00,1942-09-02T16:50:00+00:00,1906-01-02T16:50:00+00:00
+1941-10-02T16:55:00+00:00,1942-09-02T16:55:00+00:00,1906-01-02T16:55:00+00:00
+1941-10-02T17:00:00+00:00,1942-09-02T17:00:00+00:00,1906-01-02T17:00:00+00:00
+1941-10-02T17:05:00+00:00,1942-09-02T17:05:00+00:00,1906-01-02T17:05:00+00:00
+1941-10-02T17:10:00+00:00,1942-09-02T17:10:00+00:00,1906-01-02T17:10:00+00:00
+1941-10-02T17:15:00+00:00,1942-09-02T17:15:00+00:00,1906-01-02T17:15:00+00:00
+1941-10-02T17:20:00+00:00,1942-09-02T17:20:00+00:00,1906-01-02T17:20:00+00:00
+1941-10-02T17:25:00+00:00,1942-09-02T17:25:00+00:00,1906-01-02T17:25:00+00:00
+1941-10-02T17:30:00+00:00,1942-09-02T17:30:00+00:00,1906-01-02T17:30:00+00:00
+1941-10-02T17:35:00+00:00,1942-09-02T17:35:00+00:00,1906-01-02T17:35:00+00:00
+1941-10-02T17:40:00+00:00,1942-09-02T17:40:00+00:00,1906-01-02T17:40:00+00:00
+1941-10-02T17:45:00+00:00,1942-09-02T17:45:00+00:00,1906-01-02T17:45:00+00:00
+1941-10-02T17:50:00+00:00,1942-09-02T17:50:00+00:00,1906-01-02T17:50:00+00:00
+1941-10-02T17:55:00+00:00,1942-09-02T17:55:00+00:00,1906-01-02T17:55:00+00:00
+1941-10-02T18:00:00+00:00,1942-09-02T18:00:00+00:00,1906-01-02T18:00:00+00:00
+1941-10-02T18:05:00+00:00,1942-09-02T18:05:00+00:00,1906-01-02T18:05:00+00:00
+1941-10-02T18:10:00+00:00,1942-09-02T18:10:00+00:00,1906-01-02T18:10:00+00:00
+1941-10-02T18:15:00+00:00,1942-09-02T18:15:00+00:00,1906-01-02T18:15:00+00:00
+1941-10-02T18:20:00+00:00,1942-09-02T18:20:00+00:00,1906-01-02T18:20:00+00:00
+1941-10-02T18:25:00+00:00,1942-09-02T18:25:00+00:00,1906-01-02T18:25:00+00:00
+1941-10-02T18:30:00+00:00,1942-09-02T18:30:00+00:00,1906-01-02T18:30:00+00:00
+1941-10-02T18:35:00+00:00,1942-09-02T18:35:00+00:00,1906-01-02T18:35:00+00:00
+1941-10-02T18:40:00+00:00,1942-09-02T18:40:00+00:00,1906-01-02T18:40:00+00:00
+1941-10-02T18:45:00+00:00,1942-09-02T18:45:00+00:00,1906-01-02T18:45:00+00:00
+1941-10-02T18:50:00+00:00,1942-09-02T18:50:00+00:00,1906-01-02T18:50:00+00:00
+1941-10-02T18:55:00+00:00,1942-09-02T18:55:00+00:00,1906-01-02T18:55:00+00:00
+1941-10-02T19:00:00+00:00,1942-09-02T19:00:00+00:00,1906-01-02T19:00:00+00:00
+1941-10-02T19:05:00+00:00,1942-09-02T19:05:00+00:00,1906-01-02T19:05:00+00:00
+1941-10-02T19:10:00+00:00,1942-09-02T19:10:00+00:00,1906-01-02T19:10:00+00:00
+1941-10-02T19:15:00+00:00,1942-09-02T19:15:00+00:00,1906-01-02T19:15:00+00:00
+1941-10-02T19:20:00+00:00,1942-09-02T19:20:00+00:00,1906-01-02T19:20:00+00:00
+1941-10-02T19:25:00+00:00,1942-09-02T19:25:00+00:00,1906-01-02T19:25:00+00:00
+1941-10-02T19:30:00+00:00,1942-09-02T19:30:00+00:00,1906-01-02T19:30:00+00:00
+1941-10-02T19:35:00+00:00,1942-09-02T19:35:00+00:00,1906-01-02T19:35:00+00:00
+1941-10-02T19:40:00+00:00,1942-09-02T19:40:00+00:00,1906-01-02T19:40:00+00:00
+1941-10-02T19:45:00+00:00,1942-09-02T19:45:00+00:00,1906-01-02T19:45:00+00:00
+1941-10-02T19:50:00+00:00,1942-09-02T19:50:00+00:00,1906-01-02T19:50:00+00:00
+1941-10-02T19:55:00+00:00,1942-09-02T19:55:00+00:00,1906-01-02T19:55:00+00:00
+1941-10-02T20:00:00+00:00,1942-09-02T20:00:00+00:00,1906-01-02T20:00:00+00:00
+1941-10-02T20:05:00+00:00,1942-09-02T20:05:00+00:00,1906-01-02T20:05:00+00:00
+1941-10-02T20:10:00+00:00,1942-09-02T20:10:00+00:00,1906-01-02T20:10:00+00:00
+1941-10-02T20:15:00+00:00,1942-09-02T20:15:00+00:00,1906-01-02T20:15:00+00:00
+1941-10-02T20:20:00+00:00,1942-09-02T20:20:00+00:00,1906-01-02T20:20:00+00:00
+1941-10-02T20:25:00+00:00,1942-09-02T20:25:00+00:00,1906-01-02T20:25:00+00:00
+1941-10-02T20:30:00+00:00,1942-09-02T20:30:00+00:00,1906-01-02T20:30:00+00:00
+1941-10-02T20:35:00+00:00,1942-09-02T20:35:00+00:00,1906-01-02T20:35:00+00:00
+1941-10-02T20:40:00+00:00,1942-09-02T20:40:00+00:00,1906-01-02T20:40:00+00:00
+1941-10-02T20:45:00+00:00,1942-09-02T20:45:00+00:00,1906-01-02T20:45:00+00:00
+1941-10-02T20:50:00+00:00,1942-09-02T20:50:00+00:00,1906-01-02T20:50:00+00:00
+1941-10-02T20:55:00+00:00,1942-09-02T20:55:00+00:00,1906-01-02T20:55:00+00:00
+1941-10-02T21:00:00+00:00,1942-09-02T21:00:00+00:00,1906-01-02T21:00:00+00:00
+1941-10-02T21:05:00+00:00,1942-09-02T21:05:00+00:00,1906-01-02T21:05:00+00:00
+1941-10-02T21:10:00+00:00,1942-09-02T21:10:00+00:00,1906-01-02T21:10:00+00:00
+1941-10-02T21:15:00+00:00,1942-09-02T21:15:00+00:00,1906-01-02T21:15:00+00:00
+1941-10-02T21:20:00+00:00,1942-09-02T21:20:00+00:00,1906-01-02T21:20:00+00:00
+1941-10-02T21:25:00+00:00,1942-09-02T21:25:00+00:00,1906-01-02T21:25:00+00:00
+1941-10-02T21:30:00+00:00,1942-09-02T21:30:00+00:00,1906-01-02T21:30:00+00:00
+1941-10-02T21:35:00+00:00,1942-09-02T21:35:00+00:00,1906-01-02T21:35:00+00:00
+1941-10-02T21:40:00+00:00,1942-09-02T21:40:00+00:00,1906-01-02T21:40:00+00:00
+1941-10-02T21:45:00+00:00,1942-09-02T21:45:00+00:00,1906-01-02T21:45:00+00:00
+1941-10-02T21:50:00+00:00,1942-09-02T21:50:00+00:00,1906-01-02T21:50:00+00:00
+1941-10-02T21:55:00+00:00,1942-09-02T21:55:00+00:00,1906-01-02T21:55:00+00:00
+1941-10-02T22:00:00+00:00,1942-09-02T22:00:00+00:00,1906-01-02T22:00:00+00:00
+1941-10-02T22:05:00+00:00,1942-09-02T22:05:00+00:00,1906-01-02T22:05:00+00:00
+1941-10-02T22:10:00+00:00,1942-09-02T22:10:00+00:00,1906-01-02T22:10:00+00:00
+1941-10-02T22:15:00+00:00,1942-09-02T22:15:00+00:00,1906-01-02T22:15:00+00:00
+1941-10-02T22:20:00+00:00,1942-09-02T22:20:00+00:00,1906-01-02T22:20:00+00:00
+1941-10-02T22:25:00+00:00,1942-09-02T22:25:00+00:00,1906-01-02T22:25:00+00:00
+1941-10-02T22:30:00+00:00,1942-09-02T22:30:00+00:00,1906-01-02T22:30:00+00:00
+1941-10-02T22:35:00+00:00,1942-09-02T22:35:00+00:00,1906-01-02T22:35:00+00:00
+1941-10-02T22:40:00+00:00,1942-09-02T22:40:00+00:00,1906-01-02T22:40:00+00:00
+1941-10-02T22:45:00+00:00,1942-09-02T22:45:00+00:00,1906-01-02T22:45:00+00:00
+1941-10-02T22:50:00+00:00,1942-09-02T22:50:00+00:00,1906-01-02T22:50:00+00:00
+1941-10-02T22:55:00+00:00,1942-09-02T22:55:00+00:00,1906-01-02T22:55:00+00:00
+1941-10-02T23:00:00+00:00,1942-09-02T23:00:00+00:00,1906-01-02T23:00:00+00:00
+1941-10-02T23:05:00+00:00,1942-09-02T23:05:00+00:00,1906-01-02T23:05:00+00:00
+1941-10-02T23:10:00+00:00,1942-09-02T23:10:00+00:00,1906-01-02T23:10:00+00:00
+1941-10-02T23:15:00+00:00,1942-09-02T23:15:00+00:00,1906-01-02T23:15:00+00:00
+1941-10-02T23:20:00+00:00,1942-09-02T23:20:00+00:00,1906-01-02T23:20:00+00:00
+1941-10-02T23:25:00+00:00,1942-09-02T23:25:00+00:00,1906-01-02T23:25:00+00:00
+1941-10-02T23:30:00+00:00,1942-09-02T23:30:00+00:00,1906-01-02T23:30:00+00:00
+1941-10-02T23:35:00+00:00,1942-09-02T23:35:00+00:00,1906-01-02T23:35:00+00:00
+1941-10-02T23:40:00+00:00,1942-09-02T23:40:00+00:00,1906-01-02T23:40:00+00:00
+1941-10-02T23:45:00+00:00,1942-09-02T23:45:00+00:00,1906-01-02T23:45:00+00:00
+1941-10-02T23:50:00+00:00,1942-09-02T23:50:00+00:00,1906-01-02T23:50:00+00:00
+1941-10-02T23:55:00+00:00,1942-09-02T23:55:00+00:00,1906-01-02T23:55:00+00:00 \ No newline at end of file
diff --git a/test/files/strict.xlsx b/test/files/strict.xlsx
new file mode 100644
index 0000000..16ae030
--- /dev/null
+++ b/test/files/strict.xlsx
Binary files differ
diff --git a/test/formatters/test_csv.rb b/test/formatters/test_csv.rb
index a4443f4..d47d93d 100644
--- a/test/formatters/test_csv.rb
+++ b/test/formatters/test_csv.rb
@@ -100,6 +100,23 @@ class TestRooFormatterCSV < Minitest::Test
end
end
+ def test_bug_datetime_offset_change
+ # DO NOT REMOVE Asia/Calcutta
+ [nil, "US/Eastern", "US/Pacific", "Asia/Calcutta"].each do |zone|
+ with_timezone(zone) do
+ with_each_spreadsheet(name: "datetime_timezone_ist_offset_change", format: %i[excelx openoffice libreoffice]) do |workbook|
+ Dir.mktmpdir do |tempdir|
+ datetime_csv_file = File.join(tempdir, "datetime_timezone_ist_offset_change.csv")
+
+ assert workbook.to_csv(datetime_csv_file)
+ assert File.exist?(datetime_csv_file)
+ assert_equal "", file_diff("#{TESTDIR}/so_datetime_timezone_ist_offset_change.csv", datetime_csv_file)
+ end
+ end
+ end
+ end
+ end
+
def test_true_class
assert_equal "true", cell_to_csv(1, 1)
end
diff --git a/test/formatters/test_xml.rb b/test/formatters/test_xml.rb
index c8390b6..ef904ec 100644
--- a/test/formatters/test_xml.rb
+++ b/test/formatters/test_xml.rb
@@ -16,7 +16,7 @@ class TestRooFormatterXML < Minitest::Test
all_cells = init_all_cells(workbook, sheetname)
cells = xml_sheet.children.reject(&:text?)
- assert_equal sheetname, xml_sheet.attribute("name").value
+ assert_equal sheetname, xml_sheet["name"]
assert_equal all_cells.size, cells.size
cells.each_with_index do |cell, i|
@@ -27,10 +27,10 @@ class TestRooFormatterXML < Minitest::Test
all_cells[i][:type],
]
result = [
- cell.attribute("row").value,
- cell.attribute("column").value,
+ cell["row"],
+ cell["column"],
cell.text,
- cell.attribute("type").value,
+ cell["type"],
]
assert_equal expected, result
diff --git a/test/roo/test_base.rb b/test/roo/test_base.rb
index 31ddb09..a9a4dd6 100644
--- a/test/roo/test_base.rb
+++ b/test/roo/test_base.rb
@@ -63,11 +63,11 @@ class TestRooBase < Minitest::Test
workbook.default_sheet = workbook.sheets.first
result = workbook.find 20
assert result
- assert_equal "Brief aus dem Sekretariat", result[0]["TITEL"]
+ assert_equal "Brief aus dem Sekretariat", result[0]
result = workbook.find 22
assert result
- assert_equal "Brief aus dem Skretariat. Tagung in Amberg/Opf.", result[0]["TITEL"]
+ assert_equal "Brief aus dem Skretariat. Tagung in Amberg/Opf.", result[0]
end
end
diff --git a/test/roo/test_csv.rb b/test/roo/test_csv.rb
index c5e251d..336191b 100644
--- a/test/roo/test_csv.rb
+++ b/test/roo/test_csv.rb
@@ -13,6 +13,34 @@ class TestRooCSV < Minitest::Test
end
end
+ def test_download_uri_with_query_string
+ file = filename("simple_spreadsheet")
+ port = 12_347
+ url = "#{local_server(port)}/#{file}?query-param=value"
+
+ start_local_server(file, port) do
+ csv = roo_class.new(url)
+ assert_equal "Task 1", csv.cell("f", 4)
+ assert_equal 1, csv.first_row
+ assert_equal 13, csv.last_row
+ assert_equal 1, csv.first_column
+ assert_equal 6, csv.last_column
+ end
+ end
+
+ def test_open_stream
+ file = filename("Bibelbund")
+ file_contents = File.read File.join(TESTDIR, file)
+ stream = StringIO.new(file_contents)
+ csv = roo_class.new(stream)
+
+ assert_equal "Aktuelle Seite", csv.cell("h", 12)
+ assert_equal 1, csv.first_row
+ assert_equal 3735, csv.last_row
+ assert_equal 1, csv.first_column
+ assert_equal 8, csv.last_column
+ end
+
def test_nil_rows_and_lines_csv
# x_123
oo = Roo::CSV.new(File.join(TESTDIR,'Bibelbund.csv'))
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 96af546..9b761af 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -154,3 +154,16 @@ def skip_jruby_incompatible_test
msg = "This test uses a feature incompatible with JRuby"
skip(msg) if defined?(JRUBY_VERSION)
end
+
+def with_timezone(new_tz)
+ if new_tz
+ begin
+ prev_tz, ENV['TZ'] = ENV['TZ'], new_tz
+ yield
+ ensure
+ ENV['TZ'] = prev_tz
+ end
+ else
+ yield
+ end
+end
diff --git a/test/test_roo.rb b/test/test_roo.rb
index 9b732e9..dae4a41 100644
--- a/test/test_roo.rb
+++ b/test/test_roo.rb
@@ -339,21 +339,21 @@ class TestRoo < Minitest::Test
# compare large spreadsheets
def test_compare_large_spreadsheets
- # problematisch, weil Formeln in Excel nicht unterstützt werden
skip_long_test
- qq = Roo::OpenOffice.new(File.join('test',"Bibelbund.ods"))
- with_each_spreadsheet(:name=>'Bibelbund') do |oo|
- # p "comparing Bibelbund.ods with #{oo.class}"
+ qq = Roo::OpenOffice.new(File.join('test', 'files', "Bibelbund.ods"))
+ with_each_spreadsheet(name: 'Bibelbund') do |oo|
oo.sheets.each do |sh|
oo.first_row.upto(oo.last_row) do |row|
oo.first_column.upto(oo.last_column) do |col|
- c1 = qq.cell(row,col,sh)
+ c1 = qq.cell(row, col, sh)
c1.force_encoding("UTF-8") if c1.class == String
c2 = oo.cell(row,col,sh)
c2.force_encoding("UTF-8") if c2.class == String
+ next if c1.nil? && c2.nil?
+
assert_equal c1, c2, "diff in #{sh}/#{row}/#{col}}"
- assert_equal qq.celltype(row,col,sh), oo.celltype(row,col,sh)
- assert_equal qq.formula?(row,col,sh), oo.formula?(row,col,sh) if oo.class != Roo::Excel
+ assert_equal qq.celltype(row, col, sh), oo.celltype(row, col, sh)
+ assert_equal qq.formula?(row, col, sh), oo.formula?(row, col, sh)
end
end
end