使用Apache Commons CSV 'CSVFormat'类解析日期/时间格式

ct3nt3jp  于 2022-12-25  发布在  Apache
关注(0)|答案(1)|浏览(288)

我使用的是Apache Commons CSV library.
我正在尝试将日期/时间格式解析为CSVFormat,这会导致,如果有任何时间/日期列,它将根据提供给CSVFormat的格式进行格式化。
当我删除日期/时间格式,它的工作完美,但它不工作时,添加日期/时间格式。
我想添加的日期/时间格式示例:

  • 年-月-日
  • 日-月-年时:分:秒
  • 年-月-日时:分:秒

这里还有我试图添加日期/时间格式的代码;

public ByteArrayInputStream dataToCSV(List<?> dataList, char delimiter){
        final CSVFormat format = CSVFormat.DEFAULT.withDelimiter(delimiter);
//        final String format = CSVFormat.DEFAULT.withDelimiter(delimiter).format("MM-YYYY-DD HH:mm:SS");
        try (ByteArrayOutputStream out = new ByteArrayOutputStream();
             CSVPrinter csvPrinter = new CSVPrinter(new PrintWriter(out), format);) {
            if (dataList.size() > 0){
                // headers will be written just one time
                csvPrinter.printRecord(this.getHeaders(dataList.get(0)));
                for (Object objectClass : dataList) {
                    List<String> data = getRecordData(objectClass);
                    csvPrinter.printRecord(data);
                }
            }
            csvPrinter.flush();
            return new ByteArrayInputStream(out.toByteArray());
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

我评论的那一行是不工作的那一行。上面的第一行是工作正常的那一行。
数据来自PostgreSQL数据库,我还使用了hib和commons-csv依赖项

<dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-csv</artifactId>
            <version>1.8</version>
</dependency>

DB中的时间戳字段示例
2022年11月23日11时12分13秒123456
我在CSV格式中得到的相同字段的示例
2022年11月23日11时12分13秒123456
所需格式示例
2022年11月23日11时12分13秒
任何帮助都很感激,
先谢了!

sirbozc5

sirbozc51#

CSVFormat#format * 不 * 做你想的

您在注解行中对CSVFormat#format的调用:

final String format = CSVFormat.DEFAULT.withDelimiter(delimiter).format("MM-YYYY-DD HH:mm:SS");

...是不正确的。这表明您误解了Apache Commons CSV的工作原理。
不幸的是,该命令的Javadoc几乎毫无用处:
格式化指定的值。
我们来看一下the source code

1427    /**
1428     * Formats the specified values.
1429     *
1430     * @param values the values to format
1431     * @return the formatted values
1432     */
1433    public String format(final Object... values) {
1434        final StringWriter out = new StringWriter();
1435        try (CSVPrinter csvPrinter = new CSVPrinter(out, this)) {
1436            csvPrinter.printRecord(values);
1437            final String res = out.toString();
1438            final int len = recordSeparator != null ? res.length() - recordSeparator.length() : res.length();
1439            return res.substring(0, len);
1440        } catch (final IOException e) {
1441            // should not happen because a StringWriter does not do IO.
1442            throw new IllegalStateException(e);
1443        }
1444    }

我们可以看到,您应该传递 * values *,而不是日期-时间格式模式。
我们还可以看到,这个方法 * 不 * 写入CSV文件。相反,如果CSV文件是输出的实际目标,这个方法只是使用CSVPrinter生成要写入CSV文件的文本的一个快捷方式。使用这个format方法,生成的文本只是返回给调用代码。
你需要明白CommonsCSV并不做 * binding *,这个库只是把CSV解析为纯文本,而不是对象,所以用 * CommonsCSV * 指定一个日期-时间格式是没有意义的;这不是一个功能。
您必须编写自己的Java代码来生成要通过 * Commons CSV * 发送到CSV文件的字符串。
所以你需要自己解析文本到日期时间对象。如果你有一个像2022-11-23 00:00:00.0000这样的字符串,你应该作为一个LocalDateTime对象来解析。要做到这一点,你可以用DateTimeFormatter类定义你自己的格式化模式。但是我会做一些字符串操作来改变输入,用T替换中间的SPACE:

LocalDateTime myLocalDateTime = LocalDateTime.parse( "2022-11-23 00:00:00.0000".replace( " " , "T" ) ) ;

要了解更多关于使用 * Apache Commons CSV * 的信息,请搜索Stack Overflow。许多帖子已经发布,包括一些由我撰写的帖子。

ISO 8601标准

重要提示:始终使用ISO 8601标准格式进行日期-时间值的数据交换。使用 * java. time * 类很容易做到,因为它们在解析/生成文本时默认使用ISO 8601格式。

String output = myLocalDateTime.toString() ;

...以及:

LocalDateTime myLocalDateTime = LocalDateTime.parse( "2022-11-23T00:00:00.0000" ) ;

看那个code run at Ideone.com
另一个提示:如果您试图表示某个时刻,即时间线上的特定点,请始终包含UTC的偏移量或时区。LocalDateTime类无法表示时刻,因为它缺少偏移量或时区的上下文。

相关问题