POI - Проблемы при конвертации между Excel и Java датой и наоборот - PullRequest
1 голос
/ 06 марта 2020

Я пытаюсь сохранить время в ячейке книги Excel, используя Apache POI (4.0.1).

Я конвертирую время в java.util.Date, а затем пытаюсь используйте метод org.apache.poi.ss.usermodel.DateUtil.getExcelDate, чтобы затем сохранить его в ячейке.

Я обнаружил, что, поскольку время совпадает с эпохой (1899 г.), в * 1007 есть жестко заданная проверка * который запрещает преобразование дат с годами до 1900 года, не позволяя мне делать то, что я делал.

Пример приложения:

import java.util.Date;
import java.util.stream.DoubleStream;
import org.apache.poi.ss.usermodel.DateUtil;

public class POIQuery {
    public static void main(final String[] args) {
    final String format = "%-20s%-35s%-20s%n"; //$NON-NLS-1$

    System.out.format(format, "Input Excel Date", "Java Date", "Converted Excel Date");

    DoubleStream.of(0, 0.5d, 1.5d).forEach(excelDate -> {
        final Date date = DateUtil.getJavaDate(excelDate);
        System.out.format(format, excelDate, date, DateUtil.getExcelDate(date));
    });
    }
}

Вывод (обратите внимание, согласно документации - "Преобразовано" Дата Excel "of" -1 "указывает на ошибку).

Input Excel Date    Java Date                          Converted Excel Date
0.0                 Sun Dec 31 00:00:00 GMT 1899       -1.0                
0.5                 Sun Dec 31 12:00:00 GMT 1899       -1.0                
1.5                 Mon Jan 01 12:00:00 GMT 1900       1.5

Здесь вы можете видеть, что я запрашиваю дату Java, представляющую дату Excel" 0.5 ". Затем я беру предоставленную дату Java, но POI говорит, что ей не соответствует дата Excel, хотя я сгенерировал ее из этого.

Я что-то упустил ...?

1 Ответ

2 голосов
/ 06 марта 2020

Excel значения даты в системе дат 1900 начинаются со значения 0 = день 0 в январе 1900 года. До этого значения даты Excel отсутствуют.

Если у вас есть следующие ячейки в Excel:

     A                  B
1  Value      Excel date
2      0      01/00/1900 00:00:00
3    0.5      01/00/1900 12:00:00
4      1      01/01/1900 00:00:00
5    1.5      01/01/1900 12:00:00

, где значения в столбце B такие же, как в столбце A, но отформатированы как даты в числовом формате MM/DD/YYYY hh:mm:ss, вы видите это.

Таким образом, нет Excel даты 31 декабря 1899 года. Вот почему DateUtil.getExcelDate(date) терпит неудачу, когда date является Java датой Sun Dec 31 00:00:00 GMT 1899 или Sun Dec 31 12:00:00 GMT 1899.

Но DateUtil.getJavaDate(excelDate) возвращает 31 декабря 1899 года, когда excelDate является значением double от 0.0 до 0.999.... Это потому, что Java дата января 0 1900 невозможна. Но возможны Excel значения даты от 0.0 до 0.999....

Другими словами, Excel значения даты от 0.0 до 0.999... в действительности являются значениями времени до первого возможного целого дня в Excel, который является датой 01 января 1900 года. Они на самом деле не в дне, а вместо этого в дне 0.

Поскольку значения даты от 0.0 до 0.999... и преобразованные Java даты 31 декабря 1899 г. являются особыми случаями, и их можно обрабатывать как таковые.

Расширяя код:

import java.util.Date;
import java.util.Calendar;
import java.util.stream.DoubleStream;
import org.apache.poi.ss.usermodel.DateUtil;

public class POIQuery {
    public static void main(final String[] args) {
    final String format = "%-20s%-35s%-20s%n"; //$NON-NLS-1$

    System.out.format(format, "Input Excel Date", "Java Date", "Converted Excel Date");

    DoubleStream.of(0, 0.5d, 1d, 1.5d, 44000d, 44000.5d).forEach(excelDate -> {
        final Date date = DateUtil.getJavaDate(excelDate);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        double excelDateFromDate = -1d;
        if (cal.get(Calendar.YEAR) == 1899 && cal.get(Calendar.MONTH) == 11 && cal.get(Calendar.DATE) == 31) {
         cal.add(Calendar.DATE, 1);
         excelDateFromDate = DateUtil.getExcelDate(cal.getTime());
         excelDateFromDate -= 1d; 
        } else {
         excelDateFromDate = DateUtil.getExcelDate(date);
        }
        System.out.format(format, excelDate, date, excelDateFromDate);
    });
    }
}

Если преобразованная дата Java это 31 декабря 1899 года, и мы знаем, что это значение было преобразовано из Excel, затем при преобразовании его в Excel значение даты сначала добавьте за один день до использования DateUtil.getExcelDate. Так что DateUtil.getExcelDate конвертируется с 01 января 1900 года. Затем вычтите 1 из результата DateUtil.getExcelDate.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...