Android конвертировать строку в дату меняет всю дату и время - PullRequest
0 голосов
/ 27 сентября 2018

Почему выходные данные не совпадают?

   Date currentTrueSystemDate = Calendar.getInstance().getTime();
    SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kuwait"));
    String newConvertedDate = sdf.format(currentTrueSystemDate.getTime());
    System.out.println(newConvertedDate);
    try {
        Date newConvertedDate2 = sdf.parse(newConvertedDate);
        System.out.println(newConvertedDate2);
    } catch (ParseException e) {
        System.out.println(e.getLocalizedMessage());
    }

output:

 I/System.out: 27-Sep-2018 09:16:52
 I/System.out: Thu Sep 27 07:16:52 GMT+01:00 2018

Причина, по которой я преобразовываю "newConvertedDate" из строки в дату, потому что я хочу использовать.before и .after работают на нем.Я не понимаю, почему разбор строки в дату меняет время?

Ответы [ 4 ]

0 голосов
/ 27 сентября 2018

tl; dr

Используйте современные java.time классы.

Вот краткий, но бессмысленный пример перехода от текущего момента в часовом поясе к тексту вжелаемый формат без зоны / смещения, а затем снова вернитесь к моменту в часовом поясе.

LocalDateTime.parse(                                                   // Represent a date and time-of-day without a time zone or offset-from-UTC. **NOT* a moment, but represents potential moments along a range of about 26-27 hours.
    ZonedDateTime.now( ZoneId.of( "Asia/Kuwait" ) )                    // Represents a moment, a point on the timeline, a date and time-of-day with an assigned time zone.
    .format( DateTimeFormatter.ofPattern( "dd-MMM-yyyy HH:mm:ss" , Locale.US ) )  // Generate a `String` with text representing the value of our `ZonedDateTime` object.
    ,
    DateTimeFormatter.ofPattern( "dd-MMM-yyyy HH:mm:ss" , Locale.US )  // Specify `Locale` to determine the human language and cultural norms used in localizing such as parsing the name of the month.
)                                                                      // Returns a `LocalDateTime` object.
.atZone( ZoneId.of( "Asia/Kuwait" ) )                                  // Assign a time zone to the `LocalDateTime` to determine a moment, to generate a `ZonedDateTime` object.

java.time

Вы используете ужасные старые классы даты и времени, которые были вытесненылет назад классами java.time .

Кроме того, я подозреваю, что вы имели в виду HH для 24-часовых часов, а не строчные hh для 12-часовых часов.

Сначала получите текущий момент.

ZoneId z = ZoneId.of( "Asia/Kuwait" ); // FYI, `Asia/Kuwait` is an alias of `Asia/Riyadh`.
ZonedDateTime zdt = ZonedDateTime.now( z );

zdt.toString (): 2018-09-27T22: 41: 45.314343 + 03: 00 [Азия / Кувейт]

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

Определение шаблона форматирования.Укажите Locale, чтобы определить: - человеческий язык для перевода названия дня, названия месяца и т. Д.- культурные нормы , решающие вопросы аббревиатур, заглавных букв, пунктуации, разделителей и т. П.

Получите DateTimeFormatter объект.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MMM-yyyy HH:mm:ss" , Locale.US );

Генерация текста.

String output = zdt.format( f );

27-Sep-2018 22: 41: 45

Возвращение в другом направлении сложнее, поскольку желаемый формат для этой строкиотсутствует какой-либо индикатор часового пояса или смещения от UTC.Такая строка не представляет момент.Взятые по номиналу, это может быть любой из множества потенциальных моментов в диапазоне 26-27 часов (диапазон часовых поясов вокруг земного шара).Я знаю, и вы знаете, что строка должна быть моментом в часовом поясе Asia/Kuwait со смещением от UTC на три часа вперед.Но строка не буквально говорит это.

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

LocalDateTime ldt = LocalDateTime.parse( output , f );

ldt.toString (): 2018-09-27T22: 41: 45

Затем мы вводим предполагаемую зону, чтобы определить момент.

ZonedDateTime zdt2 = ldt.atZone( z );

zdt2.toString (): 2018-09-27T22: 41: 45 + 03: 00 [Азия / Кувейт]

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

boolean sameZdt = zdt.truncatedTo( ChronoUnit.SECONDS ).isEqual( zdt2 );

true


О java.time

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

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

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

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

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

  • Java SE 8 , Java SE 9 , Java SE 10, Java SE 11 и более поздних версий - часть стандартного Java API с связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и JavaSE 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… .
0 голосов
/ 27 сентября 2018

Я не понимаю, почему разбор строки в дату меняет время?

format() преобразует дату (у которой нет часового пояса, это количество пройденных миллисекундс 1970-01-01 00:00:00 UTC) в строковое представление в указанном вами часовом поясе, в данном случае в Кувейте.

Итак, когда вы впервые получаете строку в часовом поясе Кувейта и просто печатаете ее,Это просто строка без информации о часовом поясе.Но время - время Кувейта.

Затем вы конвертируете строку в дату, используя parse (), которая предполагает, что дата в кувейтском времени, так как экземпляр sdf совпадает.Теперь эта строка преобразуется в дату, и System.out.println печатает ее в вашем местном часовом поясе.

Следует отметить, что оба времени одинаковы, только разные часовые пояса.

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

Сделайте так

Date currentTrueSystemDate = Calendar.getInstance().getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss");
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kuwait"));
        String newConvertedDate = sdf.format(currentTrueSystemDate.getTime());
        System.out.println(newConvertedDate);
        try {
            sdf = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss");
            Date newConvertedDate2 = sdf.parse(newConvertedDate);
            System.out.println(newConvertedDate2);
        } catch (ParseException e) {
            System.out.println(e.getLocalizedMessage());
        }
0 голосов
/ 27 сентября 2018

Если под «изменением времени» вы подразумеваете момент времени, то форматирование и синтаксический анализ не изменяют его.

Сначала вы форматируете время, используя средство форматирования, которое использует кувейтское время (стандартное время Аравии, равноеUTC + 03: 00).Мы видим, что когда это произошло, время в Кувейте было 09: 16: 52.

Затем вы печатаете объект Date, который (близко к) равен первому.System.out.println неявно вызывает newConvertedDate2.toString, чтобы узнать, что печатать.Date.toString использует часовой пояс по умолчанию вашей JVM - GMT + 01: 00 - для рендеринга строки для печати.Когда время в Кувейте 9:16:52, это просто 07:16:52 в UTC + 01: 00.Таким образом, вы действительно получаете то же самое время снова.

Другие советы:

  • Используемые вами классы даты и времени - SimpleDateFormat и Date - давно устарели ибывший в особенности заведомо хлопотным.Вместо того, чтобы использовать их, рассмотрите возможность добавления библиотеки ThreeTenABP в ваш проект Android, чтобы вы могли использовать java.time, современный Java-интерфейс даты и времени.С ним гораздо приятнее работать и, между прочим, гораздо понятнее с часовыми поясами.
  • GMT + 01: 00 - забавная настройка часового пояса для вашей JVM.Вы, вероятно, были бы счастливее с настоящим часовым поясом, таким как Европа / Лондон, например.
  • В строке шаблона формата есть ошибка: строчные буквы hh для часа с AM или PM с 01 по 12.Вам нужно прописные буквы HH для часов дня с 00 до 23.
  • Когда я сказал «близко к» равно, это просто потому, что при форматировании и разборе вы теряете миллисекунды секунды, так как ваш формат нет включить это.Таким образом, между этими двумя значениями может быть разница до 999 миллисекунд.Кроме этой разницы, вы ничего не получите от форматирования Date в String и анализа его обратно в Date.Вы также можете использовать .before и .after на currentTrueSystemDate.

Ссылки

0 голосов
/ 27 сентября 2018
    Date currentTrueSystemDate = Calendar.getInstance().getTime();
    SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kuwait"));
    String newConvertedDate = sdf.format(currentTrueSystemDate.getTime());
    System.out.println(newConvertedDate);
    try {
        Date newConvertedDate2 = sdf.parse(newConvertedDate);
        System.out.println(newConvertedDate2);
        // Format the Date back to String here
        System.out.println(sdf.format(newConvertedDate2));
    } catch (ParseException e) {
        System.out.println(e.getLocalizedMessage());
    }

выход: 27 сентября 2018 года 10:03:41 чт 27 сентября 03:03:41 EDT 2018 27 сентября 2018 10: 03: 41

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