Запрос данных между двумя датами

Мне нужно получить данные между двумя датами из данных 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/

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