Как получить правильную дату из строки в Java, используя SimpleDateFormat? - PullRequest
0 голосов
/ 17 мая 2019

Я пишу заявку и должен преобразовать строку в дату.Строка будет содержать недели, дни и другую информацию, и, наконец, рассчитать разницу во времени в минутах от этой даты до текущего времени, как показано ниже.С кодом, который у меня есть, я ожидал, что «прошлый» объект будет иметь определенную календарную дату, которая была «13 недель, 2 дня, 16 часов, 42 минуты» от текущего времени, но то, что я нашел, удивило меня (объект даты - вторник марта24 15:54:00 CST 1970 по состоянию на сейчас).Может кто-нибудь объяснить, почему мой код не работает и как это исправить?Я ссылался на Java Docs , но это мне мало помогло.

        String givenStr = "13 weeks, 2 days, 16 hours, 42 minutes";
        SimpleDateFormat format = new SimpleDateFormat("w 'weeks', u 'days', H 'hours', m 'minutes'");
        try {
            Date past =  format.parse(givenStr);
            Date now = new Date();
            Long minutes = (now.getTime()-past.getTime())/(60*1000);
            System.out.printf("Date: %s Minutes: %s\n", past, minutes);
        } catch (ParseException ex) {
            //DO STH
        }

1 Ответ

2 голосов
/ 17 мая 2019

tl; dr

Используйте стандартное форматирование ISO 8601 для вашего текста промежутка времени: P13W2DT16H42M.

Используйте современные классы даты и времени, найденные вфреймворк java.time и библиотека ThreeTen-Extra : Instant, PeriodDuration и Duration.

Instant
.now()
.plus(
    PeriodDuration
    .parse(
        "P" + 
        "13 weeks, 2 days, 16 hours, 42 minutes"
        .replace( " weeks, " , "W" )
        .replace( " days, " , "DT" )
        .replace( " hours, " , "H" )
        .replace( " minutes" , "M" )
    )
)

2019-08-18T18: 30: 42.007034Z

Подробности

Вы объединяете два разных понятия:

  • a момент , точка на временной шкале
  • a промежуток времени отсоединен от временной шкалы

Момент

На мгновение мы больше не используем класс java.util.Date.Этот ужасный класс был вытеснен несколько лет назад классом java.time.Instant.

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

Интервал времени

Ваша строка ввода не представляет момент.Он представляет промежуток времени.

Для промежутка в единицах лет-месяцев-дней мы используем класс Period.Для промежутка в часах-минутах-секундах мы используем Duration.

PeriodDuration

Вы можете объединить две концепции, используя PeriodDuration класс, найденный во внешней библиотеке, созданной из проекта ThreeTen-Extra .Но вы должны дважды подумать об этом.Практически не имеет смысла объединять две гранулярности.

Но, если вы настаиваете, давайте попробуем.

Сначала измените вашу входную строку, чтобы использовать стандартный формат ISO 8601 из PnYnMnDTnHnMnS.В этом формате P отмечает начало, а T отделяет более грубую гранулярность от более мелкого.

String input = "P" + "13 weeks, 2 days, 16 hours, 42 minutes".replace( " weeks, " , "W" ).replace( " days, " , "DT" ).replace( " hours, " , "H" ).replace( " minutes" , "M" ) ;

P13W2DT16H42M

Анализ этого новоговведите как PeriodDuration.

PeriodDuration pd = PeriodDuration.parse( input );

Записать текущий момент в UTC.

Instant now = Instant.now();

now.toString (): 2019-05-17T01: 48: 42.007034Z

Добавьте продолжительность периода, чтобы определить будущий момент.

Instant later = now.plus( pd );

Later.toString ();2019-08-18T18: 30: 42.007034Z

Если вы хотите, чтобы прошлый момент, а не будущий момент, звоните Instant::minus.

Instant earlier = now.minus( pd ) ;

Прошедшие минуты

Если вы хотите, чтобы между этими двумя моментами прошло общее количество минут, используйте Duration class.

Duration d = Duration.between( now , later ) ;
long minutesTotal = d.toMinutes() ;

minutesTotal: 134922

Часовой пояс

Если вы хотите работать с моментом, который воспринимается через настенные часы, используемые людьми определенного региона (часовой пояс), используйте классы ZonedDateTime и ZoneId.Вызовите те же самые методы с именем plus / minus, как показано выше.

ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;
ZoneDateTime earlier = now.minus( pd ) ;

About java.time

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

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

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

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

Где получить классы java.time?

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

...