如何在 Java 中存储花费的时间或总持续时间?

How to store time spent or total duration in Java?

我正在使用 Java 的 POI API 自动生成 excel 报告。我将使用 POI 阅读、处理它们并创建新的 excel 报告。

excel 文件中的一列有总花费时间,也就是说,它可以采用以下格式,46:23:12 - 读作 46 hours, 23 minutes and 12 seconds

我了解如何读取日期和时间值,并且通常将它们存储在 java.util.Date 中。这里的问题是这是一个持续时间,花费的时间可能超过 24 小时。哪种数据类型适合这个?我如何使用 POI 阅读此内容?

有一个Period class可以用在Java 8.

LocalDate startDate = LocalDate.of(year, month, day );
LocalDate endDate = new LocalDate(year, month, day);

Period diff = Period.between(startDate , endDate);

当然,我想念这是关于小时、分钟和秒的。

为此,有持续时间

Duration timeDiff = Duration.ofMillis( startTime.getTime() , endTime.getTime() );

在Java8中,时间量由class java.time.Duration表示。

我不确定 Apache POI 是否有直接处理 Duration 的方法,所以我认为最好的方法是获取 String 的值, 然后解析此 String 以获取值并将这些值添加到 Duration:

String s = "46:23:12";
String[] values = s.split(":");
// get the hours, minutes and seconds value and add it to the duration
Duration duration = Duration.ofHours(Integer.parseInt(values[0]));
duration = duration.plusMinutes(Integer.parseInt(values[1]));
duration = duration.plusSeconds(Integer.parseInt(values[2]));

duration 对象将包含相当于输入的数量(在本例中:46 小时 23 分 12 秒)。如果您调用 duration.toString(),它 returns 这个持续时间 ISO 8601 format:

PT46H23M12S


当然,此代码假定输入 String 始终包含三个字段(小时、分钟和秒)。但是您可以在解析值之前检查 values.length(并且仅当相应的值不为零时才调用 plus 方法)。


如果您使用 Java <= 7,您可以使用 ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it ).

唯一的区别是包名称(在 Java 8 中是 java.time,在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp),但是类 和方法 名称 相同。

列出了 Apache POI 支持的数据类型 here

我建议使用 0x15,其中 "h:mm:ss"。

您可以使用以下两个代码块进行读写。但是阅读后你应该手动解析字符串。

要将花费的总时间写入新文件:

final HSSFWorkbook workbook = new HSSFWorkbook();
final Sheet sheet = workbook.createSheet("SHEET ONE");

final CellStyle style = workbook.createCellStyle();
style.setDataFormat((short) 0x15);

final Row completeRow = sheet.createRow(0);
final Cell cell = completeRow.createCell(0);
cell.setCellValue("46:23:12");
cell.setCellStyle(style);

FileOutputStream fileOutputStream = new FileOutputStream(new File("/tmp/one.xls"));
workbook.write(fileOutputStream);
fileOutputStream.close();

读取现有文件所花费的总时间:

FileInputStream fileInputStream = new FileInputStream("/tmp/one.xls");
HSSFWorkbook workbook = new HSSFWorkbook(fileInputStream);
HSSFSheet sheet = workbook.getSheet("SHEET ONE");

for (Row row : sheet) {
    for (Cell cell : row) {
        final String stringCellValue = cell.getStringCellValue();

        System.out.println("stringCellValue = " + stringCellValue);
    }
}

fileInputStream.close();

接受的答案是正确的,完全符合要求。这个答案提供了一些额外的细节以及从 46:23:12.

的给定字符串创建 ISO-8601 standards 字符串的替代方法

java.time.Duration is modelled on ISO-8601 standards and was introduced with Java-8 as part of JSR-310 implementationJava-9 引入了一些更方便的方法。

演示:

import java.time.Duration;

public class Main {
    public static void main(String[] args) {
        String iso8601DurationString = toIso8601DurationString("46:23:12");
        System.out.println(iso8601DurationString);

        Duration duration = Duration.parse(iso8601DurationString);
        // Default format
        System.out.println(duration);

        // Custom format
        // ####################################Java-8####################################
        String formattedDuration = String.format(
                "%02d Day %02d Hour %02d Minute %02d Second %d Millisecond %d Nanosecond", duration.toDays(),
                duration.toHours() % 24, duration.toMinutes() % 60, duration.toSeconds() % 60,
                duration.toMillis() % 1000, duration.toNanos() % 1000000000L);
        System.out.println(formattedDuration);
        // ##############################################################################

        // ####################################Java-9####################################
        formattedDuration = String.format("%02d Day %02d Hour %02d Minute %02d Second %d Millisecond %d Nanosecond",
                duration.toDaysPart(), duration.toHoursPart(), duration.toMinutesPart(), duration.toSecondsPart(),
                duration.toMillisPart(), duration.toNanosPart());
        System.out.println(formattedDuration);
        // ##############################################################################
    }

    static String toIso8601DurationString(String duration) {
        char[] symbols = "HMS".toCharArray();
        String[] durationParts = duration.split(":");
        StringBuilder sb = new StringBuilder("PT");
        for (int i = 0; i < durationParts.length; i++) {
            sb.append(durationParts[i]).append(symbols[i]);
        }
        return sb.toString();
    }
}

输出:

PT46H23M12S
PT46H23M12S
01 Day 22 Hour 23 Minute 12 Second 0 Millisecond 0 Nanosecond
01 Day 22 Hour 23 Minute 12 Second 0 Millisecond 0 Nanosecond

Trail: Date Time.

了解现代日期时间 API
  • 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它向后移植了大部分 java.time Java 6 和 7 的功能。
  • 如果您正在为 Android 项目工作,并且您的 Android API 水平仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring and