diff --git a/.github/workflows/check-links.yml b/.github/workflows/check-links.yml
index 348d6009..8627b211 100644
--- a/.github/workflows/check-links.yml
+++ b/.github/workflows/check-links.yml
@@ -34,7 +34,7 @@ jobs:
- name: Check links
id: lychee
- uses: lycheeverse/lychee-action@v1.9.3
+ uses: lycheeverse/lychee-action@v1.10.0
with:
fail: true
args: --max-concurrency 1 --cache --no-progress --exclude-all-private './**/*.md'
diff --git a/.github/workflows/java-ea-maven.yml b/.github/workflows/java-ea-maven.yml
index 53906f4d..a690e85f 100644
--- a/.github/workflows/java-ea-maven.yml
+++ b/.github/workflows/java-ea-maven.yml
@@ -12,7 +12,7 @@ jobs:
fail-fast: false
matrix:
java: [ 21 ]
- os: [ ubuntu-latest ]
+ os: [ ubuntu-latest, macos-latest ]
name: JDK${{ matrix.java }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
@@ -34,4 +34,4 @@ jobs:
- name: Build and (headless) test with Maven
uses: smithki/xvfb-action@v1.1.2
with:
- run: mvn -U -B -ntp package
+ run: mvn -U -B -ntp verify
diff --git a/.github/workflows/java8-maven.yml b/.github/workflows/java8-maven.yml
index 822d1e01..d0683de0 100644
--- a/.github/workflows/java8-maven.yml
+++ b/.github/workflows/java8-maven.yml
@@ -9,7 +9,7 @@ jobs:
fail-fast: false
matrix:
java: [ 8, 21 ]
- os: [ ubuntu-latest, macOS-latest, windows-latest ]
+ os: [ ubuntu-latest, macos-13, windows-latest ]
name: JDK${{ matrix.java }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
@@ -34,7 +34,7 @@ jobs:
- name: Build and (headless) test with Maven
uses: smithki/xvfb-action@v1.1.2
with:
- run: mvn -U -B -ntp package
+ run: mvn -U -B -ntp verify
auto-merge-job:
needs: build-and-test-job
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 94f831eb..44fdf3af 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,17 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
+## [2.5.9] - 2024-05-28
+
+### Fixed
+
+- Fix date parsing in SODS [#470](https://github.com/nbbrd/spreadsheet4j/issues/470)
+
+### Changed
+
+- Bump java-io-util from 0.0.27 to [0.0.28](https://github.com/nbbrd/spreadsheet4j/blob/develop/CHANGELOG.md)
+- Bump fastexcel from 0.16.6 to [0.18.0](https://github.com/dhatim/fastexcel/compare/0.15.7...0.16.6)
+
## [2.5.8] - 2024-02-26
### Changed
@@ -52,7 +63,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- Bump SODS from [1.5.1 to 1.6.2](https://github.com/miachm/SODS/releases)
- Bump fastexcel from [0.14.0 to 0.15.7](https://github.com/dhatim/fastexcel/releases)
-- Bump jsoup from [1.15.3 to 1.16.1](https://github.com/jhy/jsoup/blob/master/CHANGES)
+- Bump jsoup from [1.15.3 to 1.16.1](https://github.com/jhy/jsoup/blob/master/CHANGES.md)
- Remove `spreadsheet-xl` dependency from `spreadsheet-poi`
## [2.5.2] - 2022-10-28
@@ -172,7 +183,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- JDK11 cleanup
-[Unreleased]: https://github.com/nbbrd/spreadsheet4j/compare/v2.5.8...HEAD
+[Unreleased]: https://github.com/nbbrd/spreadsheet4j/compare/v2.5.9...HEAD
+[2.5.9]: https://github.com/nbbrd/spreadsheet4j/compare/v2.5.8...v2.5.9
[2.5.8]: https://github.com/nbbrd/spreadsheet4j/compare/v2.5.7...v2.5.8
[2.5.7]: https://github.com/nbbrd/spreadsheet4j/compare/v2.5.6...v2.5.7
[2.5.6]: https://github.com/nbbrd/spreadsheet4j/compare/v2.5.5...v2.5.6
diff --git a/pom.xml b/pom.xml
index 6894d0d4..087b006e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
com.github.nbbrd.spreadsheet4j
spreadsheet-parent
- 2.5.8
+ 2.5.9
pom
spreadsheet4j
@@ -38,7 +38,7 @@
UTF-8
- 2024-02-26T12:39:59Z
+ 2024-05-28T08:50:45Z
1.8
1.8
@@ -65,7 +65,7 @@
org.checkerframework
checker-qual
- 3.42.0
+ 3.43.0
@@ -86,7 +86,7 @@
com.github.nbbrd.java-io-util
java-io-bom
- 0.0.27
+ 0.0.28
pom
import
@@ -105,22 +105,22 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.12.1
+ 3.13.0
org.apache.maven.plugins
maven-deploy-plugin
- 3.1.1
+ 3.1.2
org.apache.maven.plugins
maven-install-plugin
- 3.1.1
+ 3.1.2
org.apache.maven.plugins
maven-jar-plugin
- 3.3.0
+ 3.4.1
org.apache.maven.plugins
@@ -148,7 +148,7 @@
org.apache.maven.plugins
maven-shade-plugin
- 3.5.2
+ 3.5.3
org.apache.maven.plugins
@@ -163,17 +163,17 @@
org.gaul
modernizer-maven-plugin
- 2.7.0
+ 2.9.0
de.thetaphi
forbiddenapis
- 3.6
+ 3.7
com.github.nbbrd.heylogs
heylogs-maven-plugin
- 0.7.2
+ 0.8.1
com.amashchenko.maven.plugin
@@ -183,7 +183,7 @@
org.apache.maven.plugins
maven-source-plugin
- 3.3.0
+ 3.3.1
org.apache.maven.plugins
@@ -203,12 +203,12 @@
org.jacoco
jacoco-maven-plugin
- 0.8.11
+ 0.8.12
org.jreleaser
jreleaser-maven-plugin
- 1.10.0
+ 1.12.0
@@ -301,9 +301,9 @@
- 1.18.30
+ 1.18.32
1.9.0
- 1.5.0
+ 1.5.1
1.37
@@ -466,12 +466,12 @@
org.kordamp.maven
pomchecker-enforcer-rules
- 1.10.0
+ 1.11.0
org.codehaus.mojo
extra-enforcer-rules
- 1.7.0
+ 1.8.0
diff --git a/spreadsheet-api/pom.xml b/spreadsheet-api/pom.xml
index 4e13d2a4..64b3b396 100644
--- a/spreadsheet-api/pom.xml
+++ b/spreadsheet-api/pom.xml
@@ -5,7 +5,7 @@
com.github.nbbrd.spreadsheet4j
spreadsheet-parent
- 2.5.8
+ 2.5.9
spreadsheet-api
diff --git a/spreadsheet-bom/pom.xml b/spreadsheet-bom/pom.xml
index ea9fd60e..b6ee754a 100644
--- a/spreadsheet-bom/pom.xml
+++ b/spreadsheet-bom/pom.xml
@@ -6,7 +6,7 @@
com.github.nbbrd.spreadsheet4j
spreadsheet-parent
- 2.5.8
+ 2.5.9
spreadsheet-bom
diff --git a/spreadsheet-fastexcel/pom.xml b/spreadsheet-fastexcel/pom.xml
index 582b6cdc..5e98e979 100644
--- a/spreadsheet-fastexcel/pom.xml
+++ b/spreadsheet-fastexcel/pom.xml
@@ -6,7 +6,7 @@
spreadsheet-parent
com.github.nbbrd.spreadsheet4j
- 2.5.8
+ 2.5.9
spreadsheet-fastexcel
@@ -47,7 +47,7 @@
org.dhatim
fastexcel
- 0.16.6
+ 0.18.0
diff --git a/spreadsheet-html/pom.xml b/spreadsheet-html/pom.xml
index dbaaeb77..a3915e6a 100644
--- a/spreadsheet-html/pom.xml
+++ b/spreadsheet-html/pom.xml
@@ -5,7 +5,7 @@
com.github.nbbrd.spreadsheet4j
spreadsheet-parent
- 2.5.8
+ 2.5.9
spreadsheet-html
diff --git a/spreadsheet-od/pom.xml b/spreadsheet-od/pom.xml
index 0f7d8955..61218ff3 100644
--- a/spreadsheet-od/pom.xml
+++ b/spreadsheet-od/pom.xml
@@ -5,7 +5,7 @@
com.github.nbbrd.spreadsheet4j
spreadsheet-parent
- 2.5.8
+ 2.5.9
spreadsheet-od
diff --git a/spreadsheet-od/src/main/java/ec/util/spreadsheet/od/OdBook.java b/spreadsheet-od/src/main/java/ec/util/spreadsheet/od/OdBook.java
index f93007eb..3b2d1bf2 100644
--- a/spreadsheet-od/src/main/java/ec/util/spreadsheet/od/OdBook.java
+++ b/spreadsheet-od/src/main/java/ec/util/spreadsheet/od/OdBook.java
@@ -1,17 +1,17 @@
/*
* Copyright 2013 National Bank of Belgium
*
- * Licensed under the EUPL, Version 1.1 or – as soon they will be approved
+ * Licensed under the EUPL, Version 1.1 or – as soon they will be approved
* by the European Commission - subsequent versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
- * Unless required by applicable law or agreed to in writing, software
+ * Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
+ * See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
package ec.util.spreadsheet.od;
@@ -22,16 +22,12 @@
import org.checkerframework.checker.nullness.qual.NonNull;
/**
- *
* @author Philippe Charles
*/
+@lombok.AllArgsConstructor
final class OdBook extends Book {
- private final SpreadSheet book;
-
- public OdBook(SpreadSheet book) {
- this.book = book;
- }
+ private final @lombok.NonNull SpreadSheet book;
@Override
public int getSheetCount() {
diff --git a/spreadsheet-od/src/main/java/ec/util/spreadsheet/od/OdCell.java b/spreadsheet-od/src/main/java/ec/util/spreadsheet/od/OdCell.java
index d2238b34..64d7796a 100644
--- a/spreadsheet-od/src/main/java/ec/util/spreadsheet/od/OdCell.java
+++ b/spreadsheet-od/src/main/java/ec/util/spreadsheet/od/OdCell.java
@@ -1,53 +1,56 @@
/*
* Copyright 2013 National Bank of Belgium
*
- * Licensed under the EUPL, Version 1.1 or – as soon they will be approved
+ * Licensed under the EUPL, Version 1.1 or – as soon they will be approved
* by the European Commission - subsequent versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
- * Unless required by applicable law or agreed to in writing, software
+ * Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
+ * See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
package ec.util.spreadsheet.od;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
-import org.checkerframework.checker.nullness.qual.NonNull;
-import org.checkerframework.checker.nullness.qual.Nullable;
/**
- *
* @author Philippe Charles
*/
//@FlyweightPattern
@Deprecated
+@lombok.RequiredArgsConstructor
final class OdCell extends ec.util.spreadsheet.Cell {
- private final ZoneId zoneId = ZoneId.systemDefault();
+ private final @lombok.NonNull ZoneId zoneId;
private transient Object value = null;
- static boolean isValid(Object value) {
- return value instanceof LocalDateTime
- || value instanceof Number
- || value instanceof String;
- }
-
@Nullable
OdCell withValue(@NonNull Object value) {
this.value = value;
- return isValid(value) ? this : null;
+ return isValidValue(value) ? this : null;
+ }
+
+ private static boolean isValidValue(Object value) {
+ return value instanceof LocalDateTime
+ || value instanceof LocalDate
+ || value instanceof Number
+ || value instanceof String;
}
@Override
public boolean isDate() {
- return value instanceof LocalDateTime;
+ return value instanceof LocalDateTime || value instanceof LocalDate;
}
@Override
@@ -61,16 +64,20 @@ public boolean isString() {
}
@Override
- public Date getDate() {
+ public @NonNull Date getDate() {
try {
- return Date.from(((LocalDateTime) value).atZone(zoneId).toInstant());
- } catch (ClassCastException ex) {
- throw new UnsupportedOperationException(ex);
+ return OdSheet.toDate((LocalDateTime) value, zoneId);
+ } catch (ClassCastException ex1) {
+ try {
+ return OdSheet.toDate((LocalDate) value, zoneId);
+ } catch (ClassCastException ex2) {
+ throw new UnsupportedOperationException(ex2);
+ }
}
}
@Override
- public Number getNumber() {
+ public @NonNull Number getNumber() {
try {
return (Number) value;
} catch (ClassCastException ex) {
@@ -79,7 +86,7 @@ public Number getNumber() {
}
@Override
- public String getString() {
+ public @NonNull String getString() {
try {
return (String) value;
} catch (ClassCastException ex) {
diff --git a/spreadsheet-od/src/main/java/ec/util/spreadsheet/od/OdSheet.java b/spreadsheet-od/src/main/java/ec/util/spreadsheet/od/OdSheet.java
index 3b161813..9365e4a2 100644
--- a/spreadsheet-od/src/main/java/ec/util/spreadsheet/od/OdSheet.java
+++ b/spreadsheet-od/src/main/java/ec/util/spreadsheet/od/OdSheet.java
@@ -20,8 +20,10 @@
import com.github.miachm.sods.Sheet;
import ec.util.spreadsheet.Cell;
import org.checkerframework.checker.index.qual.NonNegative;
+import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
+import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
@@ -35,15 +37,16 @@ final class OdSheet extends ec.util.spreadsheet.Sheet {
private final String name;
private final Range sheet;
private final int columnCount;
+ private final ZoneId zoneId;
@Deprecated
private final OdCell flyweightCell;
- private final ZoneId zoneId = ZoneId.systemDefault();
public OdSheet(Sheet sheet) {
this.name = sheet.getName();
this.sheet = sheet.getDataRange();
this.columnCount = computeColumnCount(this.sheet);
- this.flyweightCell = new OdCell();
+ this.zoneId = ZoneId.systemDefault();
+ this.flyweightCell = new OdCell(zoneId);
}
static int computeColumnCount(Range sheet) {
@@ -72,6 +75,14 @@ static boolean isNullOrEmpty(Range sheet, int rowIdx, int columnIdx) throws Inde
return sheet.getCell(rowIdx, columnIdx).getValue() == null;
}
+ static Date toDate(LocalDateTime value, ZoneId zoneId) {
+ return Date.from(value.atZone(zoneId).toInstant());
+ }
+
+ static Date toDate(LocalDate value, ZoneId zoneId) {
+ return Date.from(value.atStartOfDay(zoneId).toInstant());
+ }
+
@Override
public int getRowCount() {
return sheet.getNumRows();
@@ -91,17 +102,20 @@ public Cell getCell(int rowIdx, int columnIdx) {
@Override
public @Nullable Object getCellValue(@NonNegative int rowIdx, @NonNegative int columnIdx) throws IndexOutOfBoundsException {
Object value = sheet.getCell(rowIdx, columnIdx).getValue();
- if (OdCell.isValid(value)) {
- if (value instanceof LocalDateTime) {
- return Date.from(((LocalDateTime) value).atZone(zoneId).toInstant());
- }
+ if (value instanceof LocalDateTime) {
+ return toDate((LocalDateTime) value, zoneId);
+ } else if (value instanceof LocalDate) {
+ return toDate((LocalDate) value, zoneId);
+ } else if (value instanceof Number) {
+ return value;
+ } else if (value instanceof String) {
return value;
}
return null;
}
@Override
- public String getName() {
+ public @NonNull String getName() {
return name.replace("_", " ");
}
}
diff --git a/spreadsheet-od/src/main/java/module-info.java b/spreadsheet-od/src/main/java/module-info.java
index 96ca4fd0..c6639c4d 100644
--- a/spreadsheet-od/src/main/java/module-info.java
+++ b/spreadsheet-od/src/main/java/module-info.java
@@ -19,10 +19,11 @@
requires static org.checkerframework.checker.qual;
requires static nbbrd.service;
+ requires static lombok;
requires nbbrd.spreadsheet.api;
requires com.github.miachm.sods;
-
+
provides ec.util.spreadsheet.Book.Factory with
ec.util.spreadsheet.od.OpenDocumentBookFactory;
}
diff --git a/spreadsheet-od/src/test/java/ec/util/spreadsheet/od/OdBookTest.java b/spreadsheet-od/src/test/java/ec/util/spreadsheet/od/OdBookTest.java
new file mode 100644
index 00000000..fd07a83f
--- /dev/null
+++ b/spreadsheet-od/src/test/java/ec/util/spreadsheet/od/OdBookTest.java
@@ -0,0 +1,57 @@
+package ec.util.spreadsheet.od;
+
+import com.github.miachm.sods.SpreadSheet;
+import ec.util.spreadsheet.tck.BookAssert;
+import ec.util.spreadsheet.tck.SheetAssert;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+
+import static java.util.Objects.requireNonNull;
+import static org.assertj.core.api.Assertions.assertThatNullPointerException;
+
+public class OdBookTest {
+
+ @SuppressWarnings({"DataFlowIssue", "resource"})
+ @Test
+ public void testFactory() {
+ assertThatNullPointerException().isThrownBy(() -> new OdBook(null));
+ }
+
+ @Test
+ public void testContent() throws IOException {
+ try (OdBook book = new OdBook(loadResource("/Top5Browsers.ods"))) {
+ BookAssert.assertThat(book).hasSheetCount(3);
+ SheetAssert.assertThat(book.getSheet(0))
+ .hasName("Top 5 Browsers - Monthly")
+ .hasRowCount(42)
+ .hasColumnCount(7)
+ .hasCellValue(0, 0, null)
+ .hasCellValue(0, 1, "IE")
+ .hasCellValue(1, 0, OdSheet.toDate(LocalDateTime.of(2008, 7, 1, 0, 0), ZoneId.systemDefault()))
+ .hasCellValue(1, 1, 68.57);
+ }
+
+ try (OdBook book = new OdBook(loadResource("/world_libre_office.ods"))) {
+ BookAssert.assertThat(book).hasSheetCount(4);
+ SheetAssert.assertThat(book.getSheet(0))
+ .hasName("Europe")
+ .hasRowCount(383) // FIXME: should be 382?
+ .hasColumnCount(4)
+ .hasCellValue(0, 0, "date")
+ .hasCellValue(0, 1, "France")
+ .hasCellValue(1, 0, OdSheet.toDate(LocalDate.of(1990, 1, 1), ZoneId.systemDefault()))
+ .hasCellValue(1, 1, 395.8926090299);
+ }
+ }
+
+ private static SpreadSheet loadResource(String name) throws IOException {
+ try (InputStream stream = OdBookTest.class.getResourceAsStream(name)) {
+ return new SpreadSheet(requireNonNull(stream));
+ }
+ }
+}
diff --git a/spreadsheet-od/src/test/resources/world_libre_office.ods b/spreadsheet-od/src/test/resources/world_libre_office.ods
new file mode 100644
index 00000000..c87edbbc
Binary files /dev/null and b/spreadsheet-od/src/test/resources/world_libre_office.ods differ
diff --git a/spreadsheet-poi/pom.xml b/spreadsheet-poi/pom.xml
index 7f627760..d429eb7e 100644
--- a/spreadsheet-poi/pom.xml
+++ b/spreadsheet-poi/pom.xml
@@ -5,7 +5,7 @@
com.github.nbbrd.spreadsheet4j
spreadsheet-parent
- 2.5.8
+ 2.5.9
spreadsheet-poi
@@ -100,7 +100,7 @@
org.apache.logging.log4j
log4j-api
- 2.23.0
+ 2.23.1
diff --git a/spreadsheet-standalone/pom.xml b/spreadsheet-standalone/pom.xml
index 74f795fe..807b8983 100644
--- a/spreadsheet-standalone/pom.xml
+++ b/spreadsheet-standalone/pom.xml
@@ -7,7 +7,7 @@
com.github.nbbrd.spreadsheet4j
spreadsheet-parent
- 2.5.8
+ 2.5.9
spreadsheet-standalone
diff --git a/spreadsheet-xl/pom.xml b/spreadsheet-xl/pom.xml
index c1fac03e..e30a7c79 100644
--- a/spreadsheet-xl/pom.xml
+++ b/spreadsheet-xl/pom.xml
@@ -6,7 +6,7 @@
com.github.nbbrd.spreadsheet4j
spreadsheet-parent
- 2.5.8
+ 2.5.9
spreadsheet-xl
diff --git a/spreadsheet-xmlss/pom.xml b/spreadsheet-xmlss/pom.xml
index 079a1b2f..b30fa123 100644
--- a/spreadsheet-xmlss/pom.xml
+++ b/spreadsheet-xmlss/pom.xml
@@ -5,7 +5,7 @@
com.github.nbbrd.spreadsheet4j
spreadsheet-parent
- 2.5.8
+ 2.5.9
spreadsheet-xmlss