Как преобразовать ja.sql.timestamp в заданный формат с помощью java

#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 не очень совместимо с понятиями «месяцы», «дни», «годы» и «часовые пояса». время встреч намного лучше, поэтому сначала конвертируйте в это, а затем это легко. Таким образом, формула:

  1. Преобразуйте временную метку в наиболее подходящий тип java.time, который Instant (потому что технически это то, что временная метка реализована как: millis-since-epoch nanos-in-that-milli)
  2. Преобразуйте свой Instant в ZonedDateTime, потому что желаемый рендеринг включает в себя понятия, которые Instant не понимает: человеческие понятия, такие как «месяц».
  3. Преобразуйте ваш ZDT в ZDT в нужном вам месте. Мгновенные значения не включают никакого понятия местоположения / зоны, поэтому вам нужно явно указать, что вам нужна странная, никогда не используемая людьми 0800 зона по какой-то странной причине.
  4. Отформатируйте правильно расположенный ZDT с помощью DateTimeFormatter.

NB1: Вы уверены, что хотите 0800? Бьюсь об заклад, вы хотите Asia/Singapore или что-то в этом роде, нет 0800 , а затем визуализируете это так, хотя, на самом деле, вы не должны этого делать, это сбивает с толку, когда страны решают переключать зоны, что они делают все время. Указание подобных вещей 0800 — отличный способ пропустить встречи с парикмахером.

NB2: Шаги 2 и 3, описанные выше, могут быть выполнены за один шаг, но хорошо осознавать, что вы объединяете вещи.

Комментарии:

1. Я только что привел пример. Если это Азия / Калькутта, то это должно быть 0530 .. В основном часовой пояс будет настраиваться. Исходя из этого, нам нужно преобразовать.