Почему запрос даты до нашей эры меняется на 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));
Спасибо всем за время, посвященное моему вопросу!