Почему запрос даты до нашей эры меняется на AD в Java?

Моя программа на Java подключается к базе данных (Oracle XE 11g), которая содержит много дат (формат даты OracleXE установлен в syyyy/mm/dd).

Выполнение запроса в базе данных с отрицательными датами (до Рождества Христова) работает нормально. Когда я делаю это на Java, они все меняются на AD (Anno Domini). Как я могу получить даты в Java относительно AD/BC?

Мой Java-код здесь выполняет запрос к БД и помещает результат в таблицу.

try {
    Object item=cbPD.getSelectedItem();                                 
    String dacercare=item.toString();
    query = "SELECT DISTINCT PD.Titolo,PD.Inizio,(Select E.nome From Evento E WHERE PD.Inizio_Evento=E.CODE),
            PD.Fine, (Select E.nome From Evento E  WHERE PD.Fine_Evento=E.CODE ) FROM Periododelimitato PD WHERE PD.Titolo=?";
    PreparedStatement stAccess = Login.connessione.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
    stAccess.setString(1,dacercare);
    rset = stAccess.executeQuery(); 
    j = modelPD.getRowCount();
    for (i=0; i<j; i++) modelPD.removeRow(0);
    Date data;
    while (rset.next()) {
        data = rset.getDate(2);
        modelPD.addRow(new Object[]{rset.getString(1),data, rset.getString(3), rset.getString(4), rset.getString(5)});
    }       
}

Вот пример использования конкретного запроса:

try {
    query = "SELECT PD.Inizio FROM PeriodoDelimitato PD WHERE PD.CodP=?";
    String dacercare="8"; //look for record with this specific Primary key
    PreparedStatement stAccess = Login.connessione.prepareStatement(query,
            ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
    stAccess.setString(1, dacercare);
    rset = stAccess.executeQuery(); 
    while(rset.next()) {
        Date dateBC = rset.getDate(1);
        modelPD.addRow(new Object[]{null, dateBC, null, null, null});
    }

Выход в Java:

0509-01-01

Вывод с использованием того же запроса (замена? С указанным первичным ключом) в Sql developer:

-0509/01/01

Примечание по запросу: столбец, выбранный в этом примере, относится к типу DATE в Oracle.

Добавление информации: СУБД - Oracle (XE 11g), БД построена на IDE (разработчик SQL). Программа написана на Java через Netbeans 8.2. Я подключаюсь к базе данных в Netbeans, добавляя библиотеку "ojdbc6.jar".

2 ответа

Во-первых, не сразу понятно, как вы должны обращаться с историческими и не в последнюю очередь доисторическими датами и как вы должны ожидать их поведения. Это не то, что я знаю, но я сомневаюсь, что какой-либо календарь общего пользования сегодня использовался в 6 веке до нашей эры (до нашей эры, "до нашей эры"). Может быть, вы уже знали, я просто хотел упомянуть об этом для всех, кто читает этот ответ.

Благодаря ответу (теперь удаленному) Бэзила Бурка, то, что вы наблюдали, похоже, является предполагаемым поведением с java.sql.Date, Я пробовал печатать даты 2 года до н.э. (обычная эра, "AD"), а затем 2 года до н.э. и сравнивал. Первые 2 CE:

    LocalDate ld = LocalDate.of(2, 1, 1);
    java.sql.Date sqlDate = java.sql.Date.valueOf(ld);
    System.out.println("java.sql.Date " + sqlDate + " millis " + sqlDate.getTime());

java.sql.Date 0002-01-01 millis -62104237200000

Это как и ожидалось. Для 2 до н.э. нам нужно поставить -1 к LocalDate так как 0 означает 1 год до н.э., а -1 означает 2 год до н.э. Вставить LocalDate.of(-1, 1, 1) в приведенном выше коде, и вывод

java.sql.Date 0002-01-01 millis -62198931600000

Отметим, что дата печатается одинаково. 0002 едва ли неверен, но он не говорит нам, будет ли это год 2 CE или BCE. Я считаю, что это объясняет поведение, которое вы наблюдали. Далее отметим, что значения в миллисекундах отличаются, поэтому даты отличаются, как и должно быть. Разница составляет 94694400000 миллисекунд, что составляет 1096 дней или 3 года, если один из них является високосным. Високосный год может удивить, но в остальном я думаю, что это правильно.

Хотя есть что-то подозрительное. Когда я преобразовал дату sql обратно в LocalDateэра была потеряна, у меня всегда было свидание в общую эру. Поскольку вам не нужно это преобразование, вам, вероятно, не нужно заботиться.

Я считаю, что хорошим решением будет отказаться от устаревшего Date класс полностью и использовать современный LocalDate на протяжении. Вы должны знать, что это следует так называемому пролептическому григорианскому календарю, который не всегда может давать точно такие же даты, как Date, Также для этого требуется драйвер, совместимый с JDBC 4.2, поэтому ваш ojdbc6.jar не буду делать Несмотря на то, что это может означать, что вам помешали, я оставляю это предложение для всех, кто читает. Я не проверял, но я думаю, что должно работать следующее:

LocalDate dateBC = rset.getObject(1, LocalDate.class);

Решение, использующее старый тип Date для запроса SQL-дат BC и AC, которые работают, заключается в объявлении в моем классе SimpleDataFormat в формате, указанном ниже.

public SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd G");

Затем я объявил Date dataOUT, вызывая метод формата SimpleDataFormat, предоставляя в качестве входных данных Date BC, запрашиваемую из базы данных.

dataOUT=sdf.format(rset.getDate(2));

Спасибо всем за время, посвященное моему вопросу!

Другие вопросы по тегам