Отрицательные значения при расчете времени java даты - PullRequest
0 голосов
/ 06 января 2020

просто вопрос, что я делаю не так. У меня есть этот код:

    public static int berechneSekundenwert(String datum, String zeit) throws ParseException {

    Date dt = new Date();
    SimpleDateFormat df = new SimpleDateFormat( "dd.MM.yyyy HH:mm:ss" );
    dt = df.parse( datum+" "+ zeit); 
    int gesamtzeit = (int)dt.getTime();
    return gesamtzeit;
}

Теперь мой формат импорта:

  • 09.11.2019 01: 30: 17

    Что я хочу сделать это рассчитать время, проведенное для этих дат, так что я могу позже отсортировать их по времени. Но я получаю отрицательные значения?!

    Пример вывода (пройденное время, дата, дневное время):

    • -2120215336 30.09.2019 12: 03: 35
    • 1757321960 25.09.2019 16: 06: 25
    • -2111322336 30.09.2019 14: 31: 48
    • -1281127040 21.08.2019 12: 05: 36
    • -1280681040 21.08. 2019 12: 13: 02
    • 377782960 09.09.2019 16: 54: 06
    • 1301386664 09.11.2019 01: 30: 17
    • 710621960 13.09.2019 13:21: 25
    • 712564960 13.09.2019 13: 53: 48

Разве все они не должны быть положительными, поскольку java утверждает, что функция getTime измеряет время с 01.01.1970

Кто-нибудь знает, что я сделал не так?

Ответы [ 3 ]

4 голосов
/ 06 января 2020

Компьютеры используют то, что называется отметка времени для представления дат. В Java, Date::getTime() возвращает миллисекунды, прошедшие с 1970-01-01 UTC до указанной даты, в виде long (64-разрядное целое число).

В представленном коде: это значение сужается до int (32-разрядное целое число). При сужении long до int старшие 32 бита обрезаются. Наибольшее значение, представляемое int, равно 2^31 - 1. Быстрый расчет показывает, что:

(2^31 - 1)      (milliseconds)
/ 1000          (milliseconds per second)
/ 60            (seconds per minute)#
/ 60            (minutes per hour)
/ 24            (hours per day)
= 24.8551348032 (days)

Это означает, что примерно через 25 дней int переполнится (как это определено в комплименте Two ). Не говоря уже о том, что более поздний момент времени может иметь более низкое значение, чем более ранний момент времени, следовательно, отрицательные значения.

Чтобы исправить эту проблему 1 , я бы предложил определить gesamtzeit как long.


Два замечания о вашем коде:

  • java.util.Date считается устаревшим. Я бы предложил вместо этого использовать java.time.Instant.
  • Я бы предложил использовать Engli sh в исходном коде, за исключением того, что вы используете специфичные для домена слова c, которые не могут (хорошо) переводится на английский sh.

1 Это только временное исправление. Все представления с фиксированным количеством битов в конечном итоге будут переполнены. Фактически, все представление с любым ограничением памяти будет переполнено в конечном счете. Я оставляю читателю возможность узнать, когда 64-разрядное целое число переполнится

2 голосов
/ 06 января 2020

tl; dr

Код:

LocalDateTime.parse( 
    "09.11.2019 01:30:17" , 
    DateTimeFormatter.ofPattern( "dd.MM.uuuu HH:mm:ss" ) 
)
.atOffset(
    ZoneOffset.UTC 
)
.toInstant()
.toEpochMilli()

См. Этот код, запущенный на IdeOne.com .

1573263017000

Подробности

Правильный ответ по Turing85 отвечает на ваш конкретный c вопрос о том, почему недопустимые отрицательные числа. Но у вас есть другие проблемы.

ISO 8601

Теперь мой формат импорта: 09.11.2019 01: 30: 17

Я предлагаю вам обучить издатель этих данных о стандарте ISO 8601 , определяющем форматы, используемые при передаче значений даты и времени в виде текста.

Устаревшие классы даты и времени

Вы используете ужасно классы даты и времени, которые были заменены годами go современными java .time классами, определенными в JSR 310. Никогда не используйте Date или SimpleDateFormat.

Table of date-time types in Java, both modern and legacy

Момент

Очевидно, вы хотите получить количество миллисекунд с начала отсчета эпохи первого момента 1970 года в UT C. Но для этого требуется момент, указав c точку на временной шкале.

Ваш вклад не соответствует этому требованию. Ваш ввод - это дата и время дня, но в нем отсутствует контекст смещения от UT C или часового пояса.

Итак, возьмем ваш пример 09.11.2019 01:30:17. Мы не можем знать, будет ли это 1:30 дня в Токио, Япония, или 13:30 в Париже, Франция, или 1:30 в Толедо, Огайо, США, - все это очень разные моменты, с разницей в несколько часов на временной шкале.

Таким образом, мы должны сначала проанализировать ваш ввод как LocalDateTime. Этот класс представляет дату и время без какой-либо концепции смещения или зоны.

String input = "09.11.2019 01:30:17" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd.MM.uuuu HH:mm:ss" ) ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;

Возможно, вы наверняка знаете смещение или зону, намеченные издателем этих данных. Если это так:

  • Предложите издателю этих данных включить в свои данные информацию о зоне / смещении.
  • Примените ZoneOffset, чтобы получить OffsetDateTime или ZoneId для получения ZonedDateTime.

Возможно, вы наверняка знаете это вход был предназначен для UT C, то есть смещения нуля часов-минут-секунд.

OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;

Чтобы получить счетчик миллисекунд с 1970-01-01T00: 00Z преобразовать в основание c класс строительного блока Instant.

Instant instant = odt.toInstant() ;

Запросить количество миллисекунд с начала эпохи.

long millisSinceEpoch = instant.toEpochMilli() ;

Поймите, что ваш исходный код игнорировал решающий вопрос о часовом поясе и смещении от UT C. Таким образом, ваш код неявно применяет текущий часовой пояс JVM по умолчанию. Это означает, что ваши результаты будут отличаться во время выполнения, и означает, что вы, вероятно, также получите неправильные результаты.


О java .time

java .time фреймворк встроен Java 8 и позже. Эти классы заменяют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Чтобы узнать больше, см. Учебник Oracle . И поиск переполнения стека для многих примеров и объяснений. Спецификация: JSR 310 .

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на java .time классов.

Вы можете обмениваться java .time объектами непосредственно с вашей базой данных. Используйте драйвер JDB C , совместимый с JDB C 4.2 или более поздней версией. Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить java. время занятий?

  • Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 и более поздних версий - часть стандартного API Java со связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большинство функций java .time перенесено на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии Android связывают реализации классов java .time .
    • Для более ранних Android (<26) <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP проект адаптируется ThreeTen-Backport (упомянуто выше). См. Как использовать ThreeTenABP… .

ThreeTen-Extra Проект расширяет java .time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java .time. Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и more .

1 голос
/ 06 января 2020

почему вы понижаете возвращаемое значение getTime()?

, просто заставьте ваш метод вернуть long вместо int

и заменить эту строку

int gesamtzeit = (int)dt.getTime();

с

long gesamtzeit = dt.getTime();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...