Вопрос по postgresql, java, timezone – Разбор даты с разными часовыми поясами

4

Даже с 15-летним стажем в Java каждый всегда сталкивается с темой обработки дат и времени ...

Вот ситуация: я получаю метку времени от некоторой внешней системы какString представление. Семантика временной метки состоит в том, что она представляет дату UTC. Эта временная метка должна быть помещена в объект, а затем в базу данных PostgreSQL вTIMESTAMP поле. Кроме того, мне нужно поместить ту же метку времени, что и местное время (в моем случае CEST) в объект, а затем в базу данных вTIMESTAMP WITH TIME ZONE поле.

Как правильно гарантировать, что независимо от настроек машины, выполняющей код, временные метки будут правильно храниться в объекте (для выполнения некоторых проверок с другими временными метками UTC) и в базе данных (чтобы использовать их в отчетах позже на)?

Вот код, который отлично работал на моей локальной машине:

SimpleDateFormat sdfUTC = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
sdfUTC.setTimeZone(TimeZone.getTimeZone("UTC"));
Date utcTimestamp = sdfUTC.parse(utcTimestampString);
// getMachinesTimezone is some internal util method giving the TimeZone object of the machines Location
Calendar localTimestamp = new GregorianCalendar(getMachinesTimezone());
localTimestamp.setTimeInMillis(utcTimestamp.getTime());

Но при выполнении одного и того же кода на сервере это приводило к разным временам, поэтому я предполагаю, что это неправильный способ его обработки. Какие-либо предложения?

PS: я читал о Joda Time при поиске на этом форуме, но в данном проекте я не могу вводить новые библиотеки, так как я только меняю существующий модуль, поэтому мне приходится жить со стандартным JDK1.6

Кажется глупым хранить один и тот же элемент данных дважды в базе данных. stew
@stew: Ну, я не тот, кто может судить о глупости существующей системы, но причина этого в том, что для оператора, который позже создает отчет, необходимо использовать utc и местное время непосредственно в качестве входных параметров, а не вычислять его. по этому вопросу. Alexander Rühl
& quot; Даже после примерно 15 лет работы в Java каждый всегда сталкивается с темой обработки дат и времени & quot ;. Потому что даты, время и часовые пояса могли бы быть изобретены для того, чтобы сделать программистов & apos; живет адом, и API даты / времени Java делают его еще хуже. Принятие JodaTime вместо стандартных API Java может помочь в некоторых случаях, но не принесет пользы при взаимодействии с такими вещами, как JDBC. Craig Ringer
Здравствуйте, Geziesfer, если вы не получили ответ, который искали, рассмотрите возможность добавления нескольких примеров реальных результатов, которые вы получили, как на локальном компьютере, так и на сервере. Это даст нам больше контекста о проблеме. +1 за хорошо написанный, аккуратный и грамматически правильный вопрос! jmort253
Похоже, вам следует судить, потому что вы тот, кто применяет глупость. зная количество «вычислений»; что, вероятно, происходит при генерации отчета, сохранение одного целочисленного вычисления - это глупая задача. Если бы вы спросили своего босса. "Вы хотите, чтобы я делал глупости, не задавая вопросов, просто потому, что я попросил вас", действительно ли он сказал бы "да"? stew

Ваш Ответ

3   ответа
0

что вы должны установить целевой часовой пояс в вашем объекте Calendar. что-то вроде:

Calendar localTimestamp = new GregorianCalendar(TimeZone.getTimeZone("GMT+10"));
localTimestamp.setTimeInMillis(utcTimestamp.getTime());

В другом случае Java использует системный часовой пояс по умолчанию для экземпляра Calendar.

@Geziefer Можете ли вы сказать, когда возникает проблема. В базе данных или уже в Java?
Кажется, он правильно хранится в базе данных, так как я вижу неправильную метку времени уже при отладке. Alexander Rühl
Хорошо, я адаптировал это в приведенном выше коде - все еще он не будет работать, как ожидалось на сервере. Alexander Rühl
-1

Date date = new Date();

DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
formatter.setTimeZone(TimeZone.getTimeZone("CET"));

Date date1 = dateformat.parse(formatter.format(date));

// Set the formatter to use a different timezone
formatter.setTimeZone(TimeZone.getTimeZone("IST"));

Date date2 = dateformat.parse(formatter.format(date)); 
// Prints the date in the IST timezone
//    System.out.println(formatter.format(date));
@BhavikAmbani Вы пробовали это с разбором строки, как упоминал Гезифер? У меня это не сработало ни с вашим методом.
Он будет отформатирован в формате UTC.
Проблема в том, что я пришел не с даты, как в вашем примере, а со строки, например & Quot; 2012-01-01T12: 00: 00,000 & Quot ;. Теперь, когда я анализирую это в DF в UTC и сохраняю в db postgreSQL через сущность JPA в поле TIMESTAMP, это приводит к неправильной отметке времени: & quot; 2012-01-01 13: 00: 00 & quot ;. Машина, выполняющая это в GMT. Если я переключаюсь на местное время (CET), он производит что-то другое. И это то, что я не понимаю, так как у меня есть заданная строка и она должна быть отформатирована как UTC. Alexander Rühl
@BhavikAmbani Ах, теперь я вижу. Ваши всепроникающие слова убедили меня сейчас ...
6

вам нужно установить часовой пояс для того же объекта данных / календаря, который вы печатаете. Как это:

private Locale locale = Locale.US;
private static final String[] tzStrings = {
    "America/New_York",
    "America/Chicago",
    "America/Denver",
    "America/Los_Angeles",
};

  Date now = new Date();
  for ( TimeZone z : zones) {
        DateFormat df = new SimpleDateFormat("K:mm a,z", locale);
        df.setTimeZone(z);
        String result = df.format(now);
        System.out.println(result); 
  }

если я устанавливаю часовой пояс SimpleDateFormat, он работает нормально.

вот пример кода ...

String date="05/19/2008 04:30 AM (EST)";
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy hh:mm aaa (z)");
TimeZone.setDefault(TimeZone.getTimeZone("PST"));
long millis = sdf.parse(date).getTime();
sdf.setTimeZone(TimeZone.getDefault());
System.out.println(sdf.format(new Date(millis)));
Дело в том, что я не печатаю, а сохраняю. В приведенном выше ответе я изложил то, что мне кажется странным в этом. Alexander Rühl
У меня была та же проблема, что и у стартера темы: у меня была дата в виде строки, и я хотел проанализировать ее как дату в часовом поясе utc. Использование SimpleDateFormat и установка его часового пояса как utc черезsdf.setTimeZone(TimeZone.getTimeZone("UTC")) было недостаточно. Парсер все еще использовал мое местное время. Что использовал трюкTimeZone.setDefault(TimeZone.getTimeZone("UTC")), Так что спасибо за ваш ответ.

Похожие вопросы