java.sql.Timestamp
не имеет информации о часовом поясе. Он имеет только одно значение*: количество наносекунд с эпохи Unix (1970-01-01T00:00Z
или "1st 1 января 1970 года, полночь по Гринвичу"). Вы не конвертируете это значение в часовой пояс, поскольку это число не привязано ни к какому конкретному часовому поясу.
При печати Timestamp
он вызывает метод toString()
, и он печатает соответствующую дату и время в часовом поясе JVM по умолчанию. Но к самому Timestamp
не привязан часовой пояс.
Взгляните на эту статью. больше информации. В нем говорится о java.util.Date
, но концепция та же: эти объекты не несут никакой информации о формате или часовом поясе, поэтому вы не можете преобразовать их между часовыми поясами. Вы можете изменить представление этих значений в разных зонах.
Пример: если я возьму 1505308230333000000
за количество наносекунд с начала эпохи. Это же число представляет 13:10 в UTC, 10:10 в Сан-Паулу, 14:10 в Лондоне, 22:10 в Токио, 18:40 в Калькутте и так далее.
Класс Timestamp
просто сохраняет значение большого числа*. Одно и то же значение соответствует разным дате/времени в каждом часовом поясе, но его значение всегда одинаково для всех.
Вот почему преобразование Timestamp
между разными зонами не имеет смысла: ваш объект Timestamp
уже представляет оба 13:10 по UTC и 18:40 по Калькутте (он содержит большое числовое значение, соответствующее этим дате/времени). в соответствующих часовых поясах — изменение этого значения изменит соответствующую местную дату/время для всех часовых поясов).
Что вы можете изменить, так это String
представление этого большого числового значения (соответствующая локальная дата/время в указанном часовом поясе).
Если вы хотите получить String
с соответствующей датой и временем в другом часовом поясе, вы можете использовать классы java.time
.
Сначала вам нужно преобразовать java.sql.Timestamp
в java.time.Instant
, а затем преобразовать его в часовой пояс, в результате чего получится java.time.ZonedDateTime
. Наконец, я форматирую его в String
, используя java.time.format.DateTimeFormatter
:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
// convert the timestamp to a zoneddatetime
ZonedDateTime z = timestamp.toInstant().atZone(ZoneId.of("Asia/Calcutta"));
// format it
System.out.println(z.format(fmt)); // 2017-09-13 18:40:30.333
Результат:
2017-09-13 18:40:30.333
Если вы уже знаете, какой часовой пояс использовать (в данном случае Asia/Calcutta
), не используйте часовой пояс по умолчанию (ZoneID.systemDefault()
) — конечно, вы можете использовать его, если хотите, просто имейте в виду, что он может быть изменен без предварительного уведомления, даже во время выполнения, поэтому лучше всегда указывать явно, какой из них вы используете.
*На самом деле, Timestamp
хранит значение большого числа в двух полях: одно для секунд, а другое для значения в наносекундах. Но это деталь реализации, которая не меняет концепции того, что это значение не привязано ни к какому часовому поясу, и поэтому нет смысла преобразовывать Timestamp
между поясами
person
Community
schedule
11.09.2017