#java #postgresql
#java #postgresql
Вопрос:
Сохранение времени в часовом поясе UTC в БД. После извлечения из БД необходимо преобразовать время в заданный формат «20201218064312 0800»
здесь также следует позаботиться о летнем времени.
Комментарии:
1. Что не так с использованием класса DateTimeFormat?
2. проблема в том, как позаботиться о летнем времени здесь
3. Java вместе с ОС позаботятся об этом.
4. Попробуйте. SO не является сервисом программирования. Если вы все еще не поняли, вставьте сюда свои попытки, свои данные, свои ожидания и результаты.
Ответ №1:
Вы должны извлечь дату и время в LocalDate
объект, как показано ниже:
LocalDate ldt = rs.getObject(1, LocalDate.class));
Затем преобразовать ldt
в OffsetDateTime odt
using LocalDateTime#atOffset
. Наконец, преобразуйте odt
в ZonedDateTime
с тем же моментом, используя odt.atZoneSameInstant
, которому вам нужно будет передать в ZoneId
качестве аргумента. ZonedDateTime
был разработан, чтобы автоматически учитывать изменения во времени из-за смены лета / зимы.
Наконец, используйте соответствующий DateTimeFormatter
для печати даты и времени в желаемом формате.
ДЕМОНСТРАЦИЯ:
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// I have created this instance of LocalDateTime for the purpose of demo. This
// should come from your ResultSet
LocalDateTime ldt = LocalDateTime.parse("2020-12-15 17:38:40.962",
DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS"));
OffsetDateTime odt = ldt.atOffset(ZoneOffset.UTC);
System.out.println(odt);
// Convert the odt to Zone
ZoneId zoneId = ZoneId.of("Europe/Vatican");
ZonedDateTime zdt = odt.atZoneSameInstant(zoneId);
System.out.println(zdt);
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuuMMddHHmmssXX");
System.out.println(zdt.format(dtf));
}
}
Вывод:
2020-12-15T17:38:40.962Z
2020-12-15T18:38:40.962 01:00[Europe/Vatican]
20201215183840 0100
Краткая демонстрация того, как ZonedDateTime
автоматически настраивается смещение часового пояса:
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
LocalDateTime ldtSummer = LocalDateTime.of(2017, 06, 02, 6, 0, 0);
LocalDateTime ldtWinter = LocalDateTime.of(2017, 12, 02, 6, 0, 0);
ZoneId nyZone = ZoneId.of("America/New_York");
ZonedDateTime nyZdtSummer = ldtSummer.atZone(nyZone);
ZonedDateTime nyZdtWinter = ldtWinter.atZone(nyZone);
System.out.println(nyZdtSummer);
System.out.println(nyZdtWinter);
}
}
Вывод:
2017-06-02T06:00-04:00[America/New_York]
2017-12-02T06:00-05:00[America/New_York]
Комментарии:
1. как это позаботится о летнем времени
2. @Rekha —
ZonedDateTime
автоматически настраивает смещение часового пояса. Я добавил демонстрацию, чтобы проиллюстрировать это. Не стесняйтесь комментировать в случае каких-либо дальнейших сомнений.3. Спасибо за демонстрацию. В базе данных есть «2020-12-15 17:38:40.962». Я пытаюсь отобразить в зоне Европы / Ватикана. Я получаю неправильное значение 20201215130840 01:00. Не могли бы вы, пожалуйста, поправить меня в этом
4. общедоступная строка getTimeWithSpecifiedTimeZoneWithDayLightSavings(временная метка dbTimeStamp) { OffsetDateTime objOffsetDateTime = OffsetDateTime.ofInstant(Instant.ofEpochMilli(dbTimeStamp.getTime()), ZoneId.of(«UTC»)); ZonedDateTime zdt = objOffsetDateTime.atZoneSameInstant(ZoneId.of(«Европа /Ватикан»)); DateTimeFormatter dtf = DateTimeFormatter. ofPattern(«uuuuMMddHHmmssXXX»); возвращает zdt.format(dtf); }
5. @Rekha — Я обновил ответ на основе этой информации. Не стесняйтесь комментировать в случае каких-либо дальнейших сомнений. Вы должны добавить все эти детали в вопрос. В следующий раз, когда вы будете публиковать вопрос, постарайтесь указать всю соответствующую информацию, чтобы избежать этих многочисленных сообщений.
Ответ №2:
java.sql.Timestamp
представляет время солнечных вспышек: момент времени, не зависящий от часового пояса или политических изменений часовых поясов. Поэтому его рендеринг as 20201218064312 0800
невозможен; в этот объект Timestamp вложено недостаточно информации для этого.
Сначала преобразуйте в appointments-time, и оттуда это легко.
- время solarflares — это момент времени, не зависящий от политики или местоположения. Это произошло / произойдет ровно через X секунд. Часовые пояса или политические указы о смене зон, переходе на летнее время и т. Д. Имеют нулевой эффект. Указано в миллисекундах; дни, месяцы, годы и т. Д. Здесь Не имеют смысла. Представлен
Instant
. - время встреч — это то, как люди обычно проводят время, и как можно более конкретно. Указывается в годах, месяцах, днях и часовом поясе. Обратите внимание, что
0800
это не часовой пояс, в любом случае бесполезный, и не зона, в которой кто-либо когда-либо назначает встречи.Europe/Amsterdam
, это часовой пояс. Это используется для назначений: если я звоню своему парикмахеру и назначаю встречу на следующий вторник08:00
, вы должны сохранить это как время встречи. Это важно: если политическая организация, которая определяет время для местоположения, в котором находится мой парикмахер, решает, что в конце концов мы не собираемся переходить на летнее время в этом году в короткие сроки, это означает, что моя встреча теперь фактически на час раньше или позже по абсолютному времени (solarflares). В этом разница между solarflares и временем встреч. ПредставленZonedDateTime
. - время будильника — это то, как вы обычно настраиваете свой будильник. Со временем назначения, если я лечу из Европы в США, абсолютное количество секунд до моей встречи с парикмахером не изменится. Однако, если я установлю будильник, потому что хочу проснуться в 8 утра, это изменится; «8 утра» теперь другое. Представлен
LocalDate
,LocalTime
, иLocalDateTime
. - API
j.u.Date
иj.u.Calendar
глупы, не используйте их: они не понимали, что время работает 3 разными способами, и объединяют все 3. Это означает, что методы не имеют смысла (а в случае Date API все устарели, потому что они не имеют смысла) и дают неправильные ответы. Следовательно, не используйте их. Используйтеjava.time
API, единственный, который имеет смысл. Если вы не можете, потому что, например, спецификация JDBC навязывает вам дрянные API, конвертируйте в java.time как можно скорее и сначала в правильное из 3 представлений, ЗАТЕМ выполните свои преобразования.
Важно понять, что j.s.Timestamp — это время solarflares (и так оно и есть j.u.Date
— да, это эпически неправильное название). Фактически, тогда вы просите включить время 20201218064312 0800
solarflares , и это странно, потому что время solarflares не очень совместимо с понятиями «месяцы», «дни», «годы» и «часовые пояса». время встреч намного лучше, поэтому сначала конвертируйте в это, а затем это легко. Таким образом, формула:
- Преобразуйте временную метку в наиболее подходящий тип java.time, который
Instant
(потому что технически это то, что временная метка реализована как: millis-since-epoch nanos-in-that-milli) - Преобразуйте свой Instant в ZonedDateTime, потому что желаемый рендеринг включает в себя понятия, которые Instant не понимает: человеческие понятия, такие как «месяц».
- Преобразуйте ваш ZDT в ZDT в нужном вам месте. Мгновенные значения не включают никакого понятия местоположения / зоны, поэтому вам нужно явно указать, что вам нужна странная, никогда не используемая людьми
0800
зона по какой-то странной причине. - Отформатируйте правильно расположенный ZDT с помощью DateTimeFormatter.
NB1: Вы уверены, что хотите 0800? Бьюсь об заклад, вы хотите Asia/Singapore
или что-то в этом роде, нет 0800
, а затем визуализируете это так, хотя, на самом деле, вы не должны этого делать, это сбивает с толку, когда страны решают переключать зоны, что они делают все время. Указание подобных вещей 0800
— отличный способ пропустить встречи с парикмахером.
NB2: Шаги 2 и 3, описанные выше, могут быть выполнены за один шаг, но хорошо осознавать, что вы объединяете вещи.
Комментарии:
1. Я только что привел пример. Если это Азия / Калькутта, то это должно быть 0530 .. В основном часовой пояс будет настраиваться. Исходя из этого, нам нужно преобразовать.