Ошибка синтаксического анализа однозначного часового времени: 3:00 - PullRequest
1 голос
/ 11 ноября 2019

, поэтому я пытался преобразовать строку Hour из 12-часового формата в 24-часовой формат, код выглядит следующим образом:

public String convertAM(String checkinCheckoutTime) {
String withoutAM = checkinCheckoutTime.replaceAll("AM", "").trim();
if (withoutAM.length() == 1 || withoutAM.length() == 2) {
  return LocalTime.parse(
      withoutAM + ":00 AM", DateTimeFormatter.ofPattern("hh:mm a", Locale.US))
      .format(DateTimeFormatter.ofPattern("HH:mm"));
} else {
  return LocalTime.parse(
      checkinCheckoutTime, DateTimeFormatter.ofPattern("hh:mm a", Locale.US))
      .format(DateTimeFormatter.ofPattern("HH:mm"));
}

}

Я получил зеленый в этом тесте:

    @Test
  public void convertCheckinCheckoutTime12AMWithSpace() {
    String checkOutTime = "12 AM";
    String expectedCheckOutTime = "00:00";

    String result = this.service.convertAM(checkOutTime);

    Assert.assertEquals(expectedCheckOutTime, result);
  }

Но в этом тесте я получаю ошибку:

    @Test
  public void convertCheckinCheckoutTimeAMNoRangeWithSpace() {
    String checkOutTime = "3 AM";
    String expectedCheckOutTime = "3:00";

    String result = this.service.convertAM(checkOutTime);

    Assert.assertEquals(expectedCheckOutTime, result);
  }

Ошибка:

java.time.format.DateTimeParseException: Text '3:00 AM' could not be parsed at index 0

Могу я узнать, что не так в 3 часа ночи? Заранее спасибо

Ответы [ 5 ]

1 голос
/ 11 ноября 2019

Оказывается, мне нужно изменить формат для одно или двузначного часа, если 12 формат чч: мм, если 3 формат ч: мм

0 голосов
/ 11 ноября 2019

TL; DR Просто используйте строку шаблона формата h[:mm] a.

Хотелось бы, чтобы вы сказали нам, как могут выглядеть ваши исходные строки времени. Для этого ответа я предполагаю:

  • Час в пределах AM или PM может состоять из 1 или 2 цифр.
  • Может присутствовать или отсутствовать двухзначная минута часа, разделенная двоеточием.
  • AM или PM, разделенные пробелом, всегда присутствуют.

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

  • Одна буква шаблона h соответствует один или два цифры часа, например 3, 03 и 12.
  • Квадратные скобки заключают дополнительные части формата. Поэтому [:mm] соответствует необязательному двоеточию и минутам.

Чтобы увидеть его в действии:

    DateTimeFormatter timeFormatter
            = DateTimeFormatter.ofPattern("h[:mm] a", Locale.US);

    String[] timeStrings = {
            "3 AM", "12 AM", "3:00 AM", "3:40 AM", "12 PM", "12:20 PM", "4 PM", "04 PM"
    };
    for (String ts : timeStrings) {
        LocalTime time = LocalTime.parse(ts, timeFormatter);
        System.out.format(Locale.ENGLISH, "%-8s is parsed into %s%n", ts, time);
    }

Вывод:

3 AM     is parsed into 03:00
12 AM    is parsed into 00:00
3:00 AM  is parsed into 03:00
3:40 AM  is parsed into 03:40
12 PM    is parsed into 12:00
12:20 PM is parsed into 12:20
4 PM     is parsed into 16:00
04 PM    is parsed into 16:00

Это сказало, что мне не нравится весь ваш подход. Ситуации, когда вам нужно преобразовать строку времени в 12-часовом формате в строку времени в 24-часовом формате, встречаются редко. Как правило, вы должны хранить время в LocalTime объекте, а не в строке. Принимая входную строку, немедленно проанализируйте ее в LocalTime. И только когда вам нужно обеспечить вывод строки, отформатируйте LocalTime в строку.

0 голосов
/ 11 ноября 2019

Пояснение

Вы используете шаблон hh для часов. Это требует двухзначных часов, например 12 или 03. Но ваш ввод представляет собой одну цифру, 3 для поля часа.


Решение

Либо настройте ваши входные данные, чтобы они были двухзначными, поэтому 03 вместо 3,Или используйте шаблон, который в порядке с одной цифрой, которая будет просто h.

Из официальной документации :

ч, часычас ночи (1-12), число, 12

число: если количество букв равно единице, то значение выводится с использованием минимального количества цифр и без дополнения. В противном случае, count цифр используется как width поля вывода, со значением с добавлением нуля при необходимости. Следующие буквы шаблона имеют ограничения на количество букв. Можно указать только одну букву «с» и «F». Можно указать до двух букв «d», «H», «h», «K», «k», «m» и «s». Можно указать до трех букв «D».


Примечания

Вы можете упростить свой код и уменьшить дублирование, удалив единственную отличающуюся часть, а именно входную строку. И поскольку вы возвращаете свой if, else не требуется. Вы также можете еще больше упростить и сделать код более читабельным, разбив некоторые вложенные операторы и поместив их в переменные. Вы также должны добавить быстрый комментарий, чтобы объяснить, что происходит:

DateTimeFormatter inputFormatter =  DateTimeFormatter.ofPattern("hh:mm a", Locale.US);
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("HH:mm", Locale.US);

// Patch time without minutes, 3 AM to 3:00 AM
String withoutAM = checkinCheckoutTime.replaceAll("AM", "").trim();
boolean hasOnlyHours = withoutAM.length() == 1 || withoutAM.length() == 2;
String timeInput = hasOnlyHours ? withoutAM + ":00 AM" : checkinCheckoutTime;

return LocalTime.parse(timeInput, inputFormatter)
      .format(outputFormatter);

Обратите внимание, что ваш код не будет работать для таких вводов, как 3 PM, поскольку вы удаляете только AM. Вы можете просто добавить еще один вызов, чтобы также удалить PM или поместить оба в одно регулярное выражение, так как вы используете вместо регулярного выражения replaceAll вместо не-регулярного выражения replace в любом случае:

String withoutSuffix = checkinCheckoutTime.replaceAll("(AM|PM)", "").trim();

А проверку длины можно упростить до <= 2 (пустой ввод в любом случае завершится неудачей на этапе анализа).

0 голосов
/ 11 ноября 2019

вместо отправки в 3 часа ночи попробуйте отправить в 3 часа ночи, все будет работать нормально. Но при работе с PM вы должны заменить свой метод этим.

public static String convertAM(String checkinCheckoutTime) {
            String withoutAM = checkinCheckoutTime.replaceAll("AM", "").trim();
            String withoutPM = checkinCheckoutTime.replaceAll("PM", "").trim();
            System.out.println(withoutAM);
            System.out.println(withoutPM);
            if (withoutAM.length() == 1 || withoutAM.length() == 2) {
                System.out.println("length below 2");
                return LocalTime.parse(withoutAM + ":00 AM", DateTimeFormatter.ofPattern("hh:mm a", Locale.US))
                        .format(DateTimeFormatter.ofPattern("HH:mm"));
            } else {
                System.out.println("lengh high");
                return LocalTime.parse(withoutPM + ":00 PM", DateTimeFormatter.ofPattern("hh:mm a", Locale.US))
                        .format(DateTimeFormatter.ofPattern("HH:mm"));
            }
        }
0 голосов
/ 11 ноября 2019

3 AM должно быть 03 AM. Вы можете обновить свой код следующим образом:

...
if (withoutAM.length() == 1 || withoutAM.length() == 2) {
    if(withoutAM.length()==1){
        withoutAM = "0"+withoutAM;
    }
...

в convertAM функция

...