Почему SimpleDateFormat setTimeZone не выдает ошибку для неверного часового пояса - PullRequest
0 голосов
/ 24 апреля 2020

Я использую SimpleDateFormat, чтобы преобразовать строковый тип времени в unix отметку времени, но когда я установил для часового пояса недопустимое значение, я все же получил правильный результат, так ли был определен метод SimpleDateFormat.parse ()? Если я хочу пройти юнит-тест для проверки случая сбоя, как я могу это сделать?

String str = "2016-06-21-10-19-22";

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");
df.setTimeZone(TimeZone.getTimeZone("fewfefewf"));

Date date = df.parse(str);

long epoch = date.getTime();
System.out.println(epoch);

Ответы [ 2 ]

1 голос
/ 24 апреля 2020

Это из-за метода getTimeZone , который возвращает зону по умолчанию GMT, если указанную TimeZone невозможно понять

указанную TimeZone, или зону GMT, если данный идентификатор не может быть понят.

Если бы рекомендовал проверить это с помощью TimeZone.getAvailableIDs , и простая проверка для подтверждения входного часового пояса действительна или нет

Arrays.stream(TimeZone.getAvailableIDs()).anyMatch(tz->tz.equals("fewfefewf"))

И окончательная рекомендация, пожалуйста, используйте классы j ava-8 date time api и начинайте отходить от SimpleDateFormat

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss"); // make sure you use H for hours in format

LocalDateTime dateTime = LocalDateTime.parse(str,formatter);
0 голосов
/ 25 апреля 2020

java .time

Я рекомендую использовать java .time, современный Java API даты и времени, для вашей работы с датой и временем. Одним из его многочисленных преимуществ является то, что во многих случаях он дает гораздо лучшую проверку, чем старые классы, такие как TimeZone, SimpleDateFormat и Date. Вот мой выстрел в современном эквиваленте вашего кода:

    String str = "2016-06-21-10-19-22";

    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd-hh-mm-ss");

    ZonedDateTime dateTime = LocalDateTime.parse(str, dtf)
            .atZone(ZoneId.of("fewfefewf"));

    long epoch = dateTime.toInstant().toEpochMilli();
    System.out.println(epoch);

Запуск его производит:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2016-06-21-10-19-22' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {MicroOfSecond=0, MinuteOfHour=19, NanoOfSecond=0, MilliOfSecond=0, SecondOfMinute=22, HourOfAmPm=10},ISO resolved to 2016-06-21 of type java.time.format.Parsed
    at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:2017)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1952)
    at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
    at ovv.misc.MiscTest.<init>(MiscTest.java:72)
    at ovv.misc.MiscTest.main(MiscTest.java:61)
Caused by: java.time.DateTimeException: Unable to obtain LocalDateTime from TemporalAccessor: {MicroOfSecond=0, MinuteOfHour=19, NanoOfSecond=0, MilliOfSecond=0, SecondOfMinute=22, HourOfAmPm=10},ISO resolved to 2016-06-21 of type java.time.format.Parsed
    at java.base/java.time.LocalDateTime.from(LocalDateTime.java:461)
    at java.base/java.time.format.Parsed.query(Parsed.java:235)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    ... 3 more
Caused by: java.time.DateTimeException: Unable to obtain LocalTime from TemporalAccessor: {MicroOfSecond=0, MinuteOfHour=19, NanoOfSecond=0, MilliOfSecond=0, SecondOfMinute=22, HourOfAmPm=10},ISO resolved to 2016-06-21 of type java.time.format.Parsed
    at java.base/java.time.LocalTime.from(LocalTime.java:431)
    at java.base/java.time.LocalDateTime.from(LocalDateTime.java:457)
    ... 5 more

Удивлен? java .time уже обнаружил ошибку, о которой вы не спрашивали: в строке шаблона формата вам нужно прописные буквы HH для часов дня с 00 до 23. Строчные буквы hh для часовых часов AM или PM от 01 до 12. В сообщении об ошибке указано подробное примечание HourOfAmPm=10 - это не то, что вы хотели. Давайте исправим и снова запустим:

    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss");
Exception in thread "main" java.time.zone.ZoneRulesException: Unknown time-zone ID: fewfefewf
    at java.base/java.time.zone.ZoneRulesProvider.getProvider(ZoneRulesProvider.java:279)
    at java.base/java.time.zone.ZoneRulesProvider.getRules(ZoneRulesProvider.java:234)
    at java.base/java.time.ZoneRegion.ofId(ZoneRegion.java:120)
    at java.base/java.time.ZoneId.of(ZoneId.java:408)
    at java.base/java.time.ZoneId.of(ZoneId.java:356)
    at ovv.misc.MiscTest.<init>(MiscTest.java:73)
    at ovv.misc.MiscTest.main(MiscTest.java:61)

Я считаю, что это то, что вы просили. Если мы исправим и эту ошибку, код будет работать без ошибок:

    ZonedDateTime dateTime = LocalDateTime.parse(str, dtf)
            .atZone(ZoneId.of("America/Eirunepe"));

1466522362000

Я установил случайный часовой пояс, но я думаю, что вы знаете, какой из них Вы хотите.

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

Ссылка: Oracle учебник: Дата Время объясняя, как использовать java .time.

...