Запрос данных между двумя датами
Мне нужно получить данные между двумя датами из данных Mongodb, которые размещены на онлайн-сервере. Я попробовал этот код, и он хорошо работает на моем Localhost (локальные данные и живые данные). Но когда я загрузил приложение в Интернете, оно не работает должным образом в Live.
Результаты не точны в живом сайте. Извлекает некоторые записи до и после указанных дат. Например, я даю даты 01-02-2018 и 28-02-2018, а результаты приводятся с записями 31-01-2018 и 01-03-2018.
Я думаю, что проблема в том, что даты хранятся в часовом поясе UTC ( 2018-02-15T23:33:30.000Z).
Код:
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
Date fromDate = format.parse(from + " 00:00:00");
Date toDate = format.parse(to + " 23:59:59");
Calendar cal = Calendar.getInstance();
cal.setTime(order.getOrderDate());
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
String strDate = sdf.format(cal.getTime());
Date orderDate = sdf.parse(strDate);
for(Order order : orders){
if(orderDate.after(fromDate) || orderDate.equals(fromDate) && orderDate.before(toDate) || orderDate.equals(toDate)){
//do something
}
}
1 ответ
java.util.Date
там нет часового пояса, поэтому нет смысла разбирать и форматировать дату заказа. Форматирование преобразует его в String
и анализ преобразует его обратно в Date
, что бессмысленно, потому что дата заказа уже Date
объект.
Вы должны установить часовой пояс в первом форматере (format
переменная), а затем проанализируйте даты от и до: они будут установлены на соответствующие даты и время в часовом поясе Калькутты - в этом случае это допустимо, потому что у вас есть строки и вы хотите преобразовать их в даты.
Затем вы делаете сравнение, используя дополнительные скобки, чтобы избежать двусмысленности (как указано в комментариях). И нет смысла устанавливать Date
к Calendar
просто чтобы вернуть его позже - Calendar
Экземпляр не имеет цели в вашем коде.
И призыв к getOrderDate
не должно быть внутри for
цикл?
Полный код будет таким:
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
// from and to dates are from Kolkata's timezone, so the formatter must know that
format.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
// dates will be equivalent to this date and time in Kolkata, although
// the date itself doesn't store the timezone in it
Date fromDate = format.parse(from + " 00:00:00");
Date toDate = format.parse(to + " 23:59:59");
for(Order order : orders){
Date orderDate = order.getOrderDate();
// note the extra parenthesis, they make all the difference
if( (orderDate.after(fromDate) || orderDate.equals(fromDate)) &&
(orderDate.before(toDate) || orderDate.equals(toDate)) ) {
....
}
}
Если у вас Java >= 8, лучше использовать java.time
API:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd-MM-yyyy");
ZoneId zone = ZoneId.of("Asia/Kolkata");
ZonedDateTime fromDate = LocalDate
// parse "from" string
.parse(from, fmt)
// start of day at Kolkata timezone
.atStartOfDay(zone);
ZonedDateTime toDate = LocalDate
// parse "to" string
.parse(to, fmt)
// get start of next day
.plusDays(1).atStartOfDay(zone);
// convert the Date to ZonedDateTime
for (Order order : orders) {
ZonedDateTime orderDate = order.getOrderDate().toInstant().atZone(zone);
if ((orderDate.isAfter(fromDate) || orderDate.isEqual(fromDate)) && (orderDate.isBefore(toDate))) {
...
}
}
Это другой код, потому что этот API вводит новые типы и концепции, но это довольно улучшение по сравнению с предыдущим API (Date
а также Calendar
грязные, глючные и устаревшие).
Потратьте некоторое время на изучение этого API, оно того стоит: https://docs.oracle.com/javase/tutorial/datetime/