Мне нужно преобразовать дату/время Joda-Time в java.util.Date
. Я делаю следующее.
DateTimeFormatter dateTimeFormatter=DateTimeFormat.forPattern("dd-MMM-yyyy hh:mm:ss aa");
DateTime dateTime = dateTimeFormatter.parseDateTime("2-Oct-2013 11:34:26 AM").withZone(DateTimeZone.UTC);
System.out.println(dateTime);
Это отображает дату/время, обозначенное зоной UTC, как ожидалось. В этом случае это 2013-10-02T06:04:26.000Z
Когда этот dateTime
преобразуется в java.util.Date
следующим образом,
System.out.println(dateTime.toDate());
он показывает, Wed Oct 02 11:34:26 IST 2013
. Он должен быть в формате UTC
.
Есть ли способ представить Date
в UTC
после ее преобразования из Joda-Time?
Я хочу, чтобы дата была сохранена в базе данных, представленной зоной UTC
.org.joda.time.DateTime
необходимо преобразовать в java.util.Date
(или java.sql.Timestamp
) перед тем, как вставить его в базу данных.Как преодолеть эту ситуацию?
Объект java.util.Date
для определения всегда находится в UTC!
(временная метка - это количество миллисов с 1.1.1970 UTC)
Но вы должны установить timeZone для utc до формирования времени:
TimeZone utc = TimeZone.getTimeZone("UTC")
SimpleDateFormatter df = new SimpleDateFormatter (PATTERN);
df.setTimeZone(utc);
System.out.println(df.format(date));
В вашем коде вы использовали метод java.util.Date.toString()
который использует TimeZone вашей системы по умолчанию.
java.util.Date
Строковый вывод не UTCИз вашего вопроса:
он показывает, Wed Oct 02 11:34:26 IST 2013. Он должен быть в формате UTC.
Нет, это не должно быть в формате UTC. Это может быть то, что вы хотите, но это не так, как описывается поведение класса.
Ваш код:
System.out.println(dateTime.toDate());
... сначала преобразует Joda-Time DateTime
в объект java.util.Date
, а затем неявно вызывает метод toString
для этого объекта juDate. Документированное поведение метода juDate для метода toString
заключается в том, чтобы применить часовой пояс JVM в настоящий момент к сгенерированной строке. Внутри, juDate действительно в UTC, но его сгенерированная строка не является. Такое поведение его toString
было toString
намерением, но в конечном счете очень плохим дизайнерским решением команды Java, которое не привело к путанице с бесчисленными программистами. Но это документированное поведение. Вы всегда должны внимательно читать библиотечную документацию, а не предполагать, что библиотека ведет себя так, как вы себе представляете.
DateTime
В UTCИз вашего вопроса:
Есть ли способ представить дату в UTC после ее преобразования из Joda-Time?
Да, создание строкового представления Joda-Time DateTime
в UTC является простым и понятным, в отличие от работы с java.util.Date/.Calendar/SimpleDateFormat. Просто позвоните с помощью withZone
чтобы создать экземпляр нового DateTime на основе оригинала, но настроен на другой часовой пояс.
Исходный код небольшого примера в Joda-Time 2.5 должен сделать его очевидным. Также найдите StackOverflow для сотен других примеров, используя Joda-Time.
DateTimeZone zoneMontréal = DateTimeZone.forID( "America/Montreal" );
DateTime nowInMontréal = DateTime.now( zoneMontréal );
DateTimeZone zoneKolkata = DateTimeZone.forID( "Asia/Kolkata" );
DateTime nowInKolkata = nowInMontréal.withZone( zoneKolkata ); // Instantiating a new date-time object based on the original but adjusted for another time zone.
DateTime nowInUtc = nowInMontréal.withZone( DateTimeZone.UTC ); // Ditto, new object, adjusted time zone.
Когда вы сбрасываете консоль, вызывая toString
для каждого DateTime:
nowInMontréal: 2014-11-14T02:03:19.932-05:00
nowInKolkata: 2014-11-14T12:33:19.932+05:30
nowInUtc: 2014-11-14T07:03:19.932Z
Все три из них представляют один и тот же одновременный момент на временной шкале Вселенной. Время в Монреале на пять часов меньше UTC, время Индии - на пять с половиной часов до UTC. В тот же момент, но разные часы настенных часов.
DateTime
в базе данныхИз вашего вопроса:
Я хочу, чтобы дата была сохранена в базе данных, представленной зоной UTC. org.joda.time.DateTime необходимо преобразовать в java.util.Date (или java.sql.Timestamp) перед тем, как вставить его в базу данных. Как преодолеть эту ситуацию?
Легко. Постройте объект java.sql.Timestamp, передав счет миллисекунд с эпохи Unix. Обратите внимание, что счетчик должен быть long
не int
.
java.sql.Timestamp ts = new java.sql.Timestamp( dateTime.getMillis() );
Совет. Помните о характере типов данных даты и времени базы данных. Postgres, например, имеет отличную поддержку для таких типов, включая те, которые определены спецификацией SQL. Во многих базах данных нет, они имеют старые устаревшие типы или только несколько слабых типов. Прочтите документ и поэкспериментируйте, чтобы убедиться, что вы понимаете поведение.
public Дата toDate (TimeZone timeZone)
Получите время даты как java.util.Date, используя указанный часовой пояс.
Созданный объект Date имеет те же поля, что и дата, за исключением случаев, когда время будет недействительным из-за пробела в дневном свете. В этом случае время будет установлено на самое раннее допустимое время после разрыва.
В случае перекрытия перехода на летнее время выбирается предыдущий момент.
Преобразование в дату JDK полон осложнений, так как конструктор даты JDK не ведет себя так, как вы могли бы ожидать, в период перехода DST. Этот метод работает, беря первое предположение и затем корректируя. Это также относится к ситуации, когда данные часового пояса JDK отличаются от данных часовых поясов Joda-Time.
В отличие от toDate(), эта реализация не зависит от логики инициализации синхронизированного времени Java и должна демонстрировать лучшие параллельные характеристики производительности.
Таким образом, это будет выглядеть так:
Timezone utc = Timezone.getTimezone("UTC")
System.out.println(dateTime.toDate(utc));
сообщите мне, если это сработает.