Получение неправильного результата при проверке даты между двумя другими датами в Java

Я использую приведенный ниже код, чтобы проверить, находится ли час между двумя другими конкретными часами:

String openHour = "08:00 AM";
String currentHour = "10:00 PM";
String closeHour = "11:00 PM"; //Change to 02:00 AM doesn't work!!!

SimpleDateFormat format = new SimpleDateFormat("hh:mm a");
Date openHourDate = format.parse(openHour);
Date currentHourDate = format.parse(currentHour);
Date closeHourDate = format.parse(closeHour);

Calendar openCalendar = Calendar.getInstance();
openCalendar.setTime(openHourDate);

Calendar currentCalendar = Calendar.getInstance();
currentCalendar.setTime(currentHourDate);

Calendar closeCalendar = Calendar.getInstance();
closeCalendar.setTime(closeHourDate);

Date open = openCalendar.getTime();
Date current = currentCalendar.getTime();
Date close = closeCalendar.getTime();

if (current.after(open) && current.before(close)) {
    System.out.println("Correct!");
} else {
    System.out.println("Incorrect!");
}

Если currentHour равно "10:00 PM", как вы видите в моем коде, все работает нормально, но если я изменю его на "02:00 AM", код не будет работать должным образом, даже если currentHour находится между 08:00 AM и 02:00 AM. Как это решить?

Возможно, это связано с тем фактом, что ваша программа видит 02:00AM в тот же день? Если бы это было так, вы говорите, что время закрытия 02:00 AM сегодня, но время открытия 08:00 AM в тот же день. Вам нужно будет добавить день к вашему закрытию времени, если это был следующий день.

Michael Platt 09.04.2019 20:43

Вы пометили свой вопрос с помощью java 8, поэтому взгляните на LocalTime и другие подобные классы, представленные в этой версии JDK.

Joakim Danielson 09.04.2019 20:48

@JoakimDanielson Это то, что я безуспешно делал в последние часы :(

Asyl Paitesh 09.04.2019 20:49

@MichaelPlatt Я не уверен, что понимаю. Да, 02:00 AM второй день, но мой currentHour между ними. Вы говорите добавить день, где, как?

Asyl Paitesh 09.04.2019 20:49

Вы можете добавить день, используя такой класс, как LocalDateTime

Jacob G. 09.04.2019 20:50

Так что это довольно сложно объяснить через текст, но я попытаюсь. Ваша ценность close заключается в том, чтобы получить экземпляр объекта календаря и просто правильно установить время? Это означает, что ваши open, current и close установлены на текущую дату. Это означает, что вы смотрите на open равным 4/9/2019 0800 AM и близким к 4/9/2019 0200AM. Когда вы запускаете проверку, ваш current установлен на 4/9/2019 1000PM не раньше close, потому что close установлен на 02:00 утра того же дня, что и current. Это имеет больше смысла?

Michael Platt 09.04.2019 20:50

@MichaelPlatt Теперь я это вижу. Не могли бы вы дать ответ, как мне добавить день? Спасибо!

Asyl Paitesh 09.04.2019 20:54

Ответ, данный Ричардом, должен стать хорошей отправной точкой для начала работы. Если это работает, не забудьте отметить его как принятый ответ, чтобы другие могли его увидеть :-)

Michael Platt 09.04.2019 20:55

@MichaelPlatt Только что решил это, используя ответ Ричарда Уилдона. Большое спасибо, что нашли время, чтобы объяснить эту проблему.

Asyl Paitesh 09.04.2019 20:55

@MichaelPlatt Да, ты прав. Только что принял ответ Ричарда Уилдона. Спасибо еще раз.

Asyl Paitesh 09.04.2019 20:56

К вашему сведению, ужасно проблемные классы даты и времени, такие как java.util.Date, java.util.Calendar и java.text.SimpleDateFormat, теперь являются наследие, вытесненными классами Java.время, встроенными в Java 8 и более поздние версии. См. Руководство от Oracle.

Basil Bourque 10.04.2019 01:24
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
11
64
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Просто нужно перемотать день, как предложил Майкл Платт:

import java.util.*;
import java.text.*;

public class Foo {
  public static void main(String[] args) throws Exception {

    String openHour = "08:00 AM";
    String currentHour = "10:00 PM";
    String closeHour = "11:00 PM"; //Change to 02:00 AM doesn't work!!!

    SimpleDateFormat format = new SimpleDateFormat("hh:mm a");
    Date openHourDate = format.parse(openHour);
    Date currentHourDate = format.parse(currentHour);
    Date closeHourDate = format.parse(closeHour);

    Calendar openCalendar = Calendar.getInstance();
    openCalendar.setTime(openHourDate);

    Calendar currentCalendar = Calendar.getInstance();
    currentCalendar.setTime(currentHourDate);

    Calendar closeCalendar = Calendar.getInstance();
    closeCalendar.setTime(closeHourDate);

    if (closeCalendar.before(openCalendar)) {
      closeCalendar.add(Calendar.DAY_OF_YEAR, 1);
    }

    Date open = openCalendar.getTime();
    Date current = currentCalendar.getTime();
    Date close = closeCalendar.getTime();

    if (current.after(open) && current.before(close)) {
      System.out.println("Correct!");
    } else {
      System.out.println("Incorrect!");
    }
  }
}

Это сработало. Спасибо, что нашли время ответить на мой вопрос. Еще один небольшой вопрос, если я поменяю closeHour скажем на 01:00 AM, снова не работает, знаете почему?

Asyl Paitesh 09.04.2019 21:05

Это решение менее оптимально. Он злоупотребляет классами даты и времени для хранения значений только времени суток. И он игнорирует важнейшую проблему часовых поясов, которые применяются неявно, используя текущий часовой пояс JVM по умолчанию, поэтому ваши результаты могут отличаться во время выполнения. У нас есть современный класс для этой работы: LocalTime. Так что используйте его. См. Ответ Дэниэлсона.

Basil Bourque 10.04.2019 01:27

@BasilBourque Спасибо за указание на современное решение.

Asyl Paitesh 10.04.2019 11:31
Ответ принят как подходящий

Вот решение с использованием LocalTime, которое также правильно обрабатывает текущее время и время закрытия после полуночи.

String openHour = "08:00 AM";
String currentHour = "01:00 PM";
String closeHour = "02:00 AM";

DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "hh:mm a" , Locale.US );
LocalTime openTime = LocalTime.parse(openHour, formatter);
LocalTime currentTime  = LocalTime.parse(currentHour, formatter);
LocalTime closeTime = LocalTime.parse(closeHour, formatter);

boolean isOpen = false;
if (closeTime.isAfter(openTime)) {
  if (openTime.isBefore(currentTime) && closeTime.isAfter(currentTime)) {
    isOpen = true;
  }
} else if (currentTime.isAfter(openTime) || currentTime.isBefore(closeTime)) {
  isOpen = true;
}

if (isOpen) {
  System.out.println("We are open");
} else {
  System.out.println("We are closed");
}

Вау, решил всю мою проблему. Это то, что я искал. Большое спасибо!

Asyl Paitesh 10.04.2019 11:23

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