ТЛ; др
... проанализировано ... из строки ... часовой пояс не указан ... Я хочу установить определенный часовой пояс
LocalDateTime.parse( "2018-01-23T01:23:45.123456789" ) // Parse string, lacking an offset-from-UTC and lacking a time zone, as a `LocalDateTime`.
.atZone( ZoneId.of( "Africa/Tunis" ) ) // Assign the time zone for which you are certain this date-time was intended. Instantiates a `ZonedDateTime` object.
Нет часового пояса в последнее время
Как указано в других правильных ответах, у java.util.Date нет часового пояса † . Он представляет UTC / GMT (без смещения часового пояса). Очень запутанно, потому что его toString
метод применяет часовой пояс JVM по умолчанию при генерации строкового представления.
Избегайте новизны
По этой и многим другим причинам вам следует избегать использования встроенного java.util.Date & .Calendar & java.text.SimpleDateFormat. Они общеизвестно хлопотно.
Вместо этого используйте пакет java.time в комплекте с Java 8 .
java.time
Классы java.time могут представлять момент на временной шкале тремя способами:
- UTC (
Instant
)
- Со смещением (
OffsetDateTime
с ZoneOffset
)
- С часовым поясом (
ZonedDateTime
с ZoneId
)
Instant
В java.time основным строительным блоком является Instant
момент времени на UTC. Используйте Instant
объекты для большей части вашей бизнес-логики.
Instant instant = Instant.now();
OffsetDateTime
Примените смещение-от-UTC, чтобы приспособиться к настенным часам некоторого местоположения .
Применить, ZoneOffset
чтобы получить OffsetDateTime
.
ZoneOffset zoneOffset = ZoneOffset.of( "-04:00" );
OffsetDateTime odt = OffsetDateTime.ofInstant( instant , zoneOffset );
ZonedDateTime
Лучше применить часовой пояс , смещение плюс правила обработки аномалий, такие как летнее время (DST) .
Применить ZoneId
к, Instant
чтобы получить ZonedDateTime
. Всегда указывайте правильное название часового пояса . Никогда не используйте 3-4 аббревиатуры, такие как EST
или IST
которые не являются ни уникальными, ни стандартизированными.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
LocalDateTime
Если во входной строке отсутствовал какой-либо индикатор смещения или зоны, анализируйте как LocalDateTime
.
Если вы уверены в предполагаемом часовом поясе, назначьте a ZoneId
для создания ZonedDateTime
. Смотрите пример кода выше в разделе tl; dr вверху.
Форматированные строки
Вызовите toString
метод любого из этих трех классов, чтобы сгенерировать строку, представляющую значение даты и времени в стандартном формате ISO 8601 . ZonedDateTime
Класс расширяет стандартный формат путем добавления имени временной зоны в скобках.
String outputInstant = instant.toString(); // Ex: 2011-12-03T10:15:30Z
String outputOdt = odt.toString(); // Ex: 2007-12-03T10:15:30+01:00
String outputZdt = zdt.toString(); // Ex: 2007-12-03T10:15:30+01:00[Europe/Paris]
Для других форматов используйте DateTimeFormatter
класс. Обычно лучше, чтобы этот класс генерировал локализованные форматы, используя ожидаемый пользовательский язык и культурные нормы. Или вы можете указать конкретный формат.
О java.time
Java.time каркас встроен в 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?
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь , такие как Interval
, YearWeek
, YearQuarter
, и более .
Joda времени
В то время как Joda-Time все еще активно поддерживается, его создатели сказали нам перейти на java.time, как только это будет удобно. Я оставляю этот раздел нетронутым в качестве ссылки, но я предлагаю java.time
вместо этого использовать раздел выше.
В Joda-Time объект date-time ( DateTime
) действительно знает свой назначенный часовой пояс. Это означает смещение от UTC, а также правила и историю летнего времени (DST) этого часового пояса и другие подобные аномалии.
String input = "2014-01-02T03:04:05";
DateTimeZone timeZone = DateTimeZone.forID( "Asia/Kolkata" );
DateTime dateTimeIndia = new DateTime( input, timeZone );
DateTime dateTimeUtcGmt = dateTimeIndia.withZone( DateTimeZone.UTC );
Вызовите toString
метод для генерации строки в формате ISO 8601 .
String output = dateTimeIndia.toString();
Joda-Time также предлагает богатые возможности для генерации всех видов других форматов String.
При необходимости вы можете преобразовать Joda-Time DateTime в java.util.Date.
Java.util.Date date = dateTimeIndia.toDate();
Ищите StackOverflow по запросу "joda date", чтобы найти еще много примеров, некоторые из которых довольно подробны.
† На самом деле это часовой пояс встроен в java.util.Date, используется для некоторых внутренних функций (см комментариев по этому Ответу). Но этот внутренний часовой пояс не отображается как свойство и не может быть установлен. Этот внутренний часовой пояс не тот, который используется toString
методом при генерации строкового представления значения даты и времени; вместо этого текущий часовой пояс JVM по умолчанию применяется на лету. Поэтому в качестве стенографии мы часто говорим: «У juDate нет часового пояса». Смешение? Да. Еще одна причина, чтобы избежать этих усталых старых классов.