Android Date.getTime() добавляет один день к исходной дате
Таким образом, у меня есть календарь, который мне нужно установить конкретную дату..
Date date = TKDateUtils.parseDate("Jun 02, 2016 05:10:30 pm");
Calendar next = Calendar.getInstance();
next.setTime(date);
и я регистрирую их здесь, чтобы увидеть вывод:
Log.i("MainActivity", date.toString());
Log.i("MainActivity", date.getTime() + "");
Выход:
06-02 20:21:29.245 1915-1915/com.cyscorpions.timekeeper I/MainActivity: Thu Jun 02 17:10:30 EDT 2016
06-02 20:21:29.245 1915-1915/com.cyscorpions.timekeeper I/MainActivity: 1464901830000
Поэтому я конвертирую getTime
от миллис до даты, и это вывод:
Итак Date
установлен в June 2, 2016 17:10:30
но getTime()
устанавливается на точный день после этой даты. Я что-то здесь не так делаю?
Вот как я разбираю дату:
public static Date parseDate(@NonNull String dateString) {
try {
mDateFormat = new SimpleDateFormat("MMM dd, yyyy h:mm:ss a");
return mDateFormat.parse(dateString);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
2 ответа
Проблема была на Genymotion's
TimeZone
все это время. Это установлено в другой часовой пояс от моего местоположения.
Укажите часовой пояс
Две разные JVM, каждая со своим (разным) текущим часовым поясом по умолчанию. Каждый из них использовал свой текущий часовой пояс по умолчанию при разборе строки, чтобы интерпретировать значение входных данных.
Решение: всегда указывайте желаемый / ожидаемый часовой пояс.
Текущий часовой пояс JVM по умолчанию можно инициализировать различными способами. И текущий часовой пояс по умолчанию может быть изменен во время выполнения любым кодом в любом потоке любого приложения в JVM. Так что никогда не зависите от этого внешнего вида часового пояса.
Укажите правильное название часового пояса в формате continent/region
, Никогда не используйте 3-4 буквенные сокращения, такие как EDT
, IST
, CST
и т. д. Это не настоящие часовые пояса, они не стандартизированы и не являются уникальными (!).
Укажите Локаль
То же самое касается Locale
, используется при разборе имени дня и месяца, определения запятой и периода и тому подобное. Текущее значение по умолчанию для JVM Locale
вне вашего контроля. Поэтому всегда указывайте желаемое / ожидаемое Locale
соответствует контексту ваших входных данных.
java.time
Вы используете старые классы даты и времени, которые оказались плохо продуманными, запутанными и хлопотными. Избежать их.
Классы java.time встроены в Java 8 и более поздние версии. Большая часть их функциональности была перенесена на Java 6 & 7 в проекте ThreeTen-Backport, а затем адаптирована для Android в проекте ThreeTenABP.
Классы java.time являются преемниками очень успешной библиотеки Joda-Time, оба проекта возглавляются одним и тем же человеком, JodaStephen. Классы java.time вытесняют печально известные старые классы даты и времени, включенные в самые ранние версии Java.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
Locale locale = Locale.CANADA_FRENCH ;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MMM dd, yyyy h:mm:ss a" );
formatter = formatter.withLocale( locale );
formatter = formatter.withZone( zoneId );
ZonedDateTime zdt = ZonedDateTime.parse( input , formatter );
Мы часто хотим работать со значениями в UTC. Для этого используйте Instant
, момент на временной шкале в UTC с разрешением наносекунды.
Instant instant = zdt.toInstant();
Перерабатывать
Если вам нужен один из старых типов, используйте новые методы, добавленные к старым классам даты и времени, для преобразования в / из java.time.
java.util.Date utilDate = java.util.Date.from( instant );
java.util.Calendar utilCal = java.util.GregorianCalendar.from( zdt );