анализ даты и времени без изменения часового пояса - PullRequest
0 голосов
/ 20 января 2019

У меня есть значения даты и времени в строковом типе.

  • appDate = 19.02.2009
  • startTime = 16:15

Я хочу вставить событие в календарь Google через API.

Когда я анализирую строку даты, она конвертируется в соответствии с моими региональными настройками.Я живу в часовом поясе GMT ​​+ 03.00.Но я хочу вставить дату и время как есть в строке.

Как выводится: {dateTime = 2019-01-19T04: 15: 00.000 + 03: 00, timeZone = America / New_York}

Мне нужно получить это: {dateTime = 2019-01-19T04: 15: 00.000-05: 00, timeZone = America / New_York}

С этим блоком кода ниже он вставляет 20:15в календарь Google.

SimpleDateFormat formatter = new SimpleDateFormat("mm/dd/yyyy HH:mm a", Locale.US);

String dateInString = appDate + " " + startTime;
Date date = formatter.parse(dateInString);
DateTime startDateTime = new DateTime(date);

EventDateTime start = new EventDateTime().setDateTime(startDateTime).setTimeZone("America/New_York");

Ответы [ 2 ]

0 голосов
/ 20 января 2019

java.time

Вы сталкиваетесь с очень распространенными источниками путаницы, окружающими наследие java.util.Date и связанные с ним классы. Вы должны использовать более новые java.time классы, представленные в Java 8:

System.out.printf("INFO - System default timezone: %s%n", ZoneId.systemDefault().getId());
// INFO - System default timezone: Europe/Moscow

// test data
String appDate = "2/19/2019";
String startTime = "4:15 PM";
String targetTimezone = "America/New_York";

String dateInString = appDate + " " + startTime;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d/yyyy h:mm a");
LocalDateTime ldt = LocalDateTime.parse(dateInString, formatter);
ZonedDateTime zdt = ldt.atZone(ZoneId.of(targetTimezone));

System.out.println(zdt);  // 2019-02-19T16:15-05:00[America/New_York]

Как видите, ZonedDateTime был создан с правильным местным временем (16:15 = 4:15 PM), правильным смещением (-05: 00) и явно указанным часовым поясом (Америка / New_York).

Если вам повезет, API Календаря Google сможет работать с классами java.time. Однако, если вам нужно по какой-либо причине вернуться к java.util.Date, вы всегда можете конвертировать, вызывая новые методы, добавленные к старым классам. Извлеките Instant из ZonedDateTime (для регулировки из зоны в UTC ), затем перейдите к новому Date.from метод.

java.util.Date date = java.util.Date.from( zdt.toInstant() );

System.out.println(date);  // Wed Feb 20 00:15:00 MSK 2019
System.out.println(date.getTime());  // 1550610900000

Обратите внимание, что java.util.Date печатается с использованием текущего часового пояса JVM по умолчанию, Europe/Moscow, поэтому дата и время были настроены соответствующим образом. Однако оба значения (2019-02-19T16:15-05:00[America/New_York] и Wed Feb 20 00:15:00 MSK 2019) представляют один и тот же момент времени: 1550610900000 миллисекунд после эпохи (1970-01-01 00:00:00 UTC).

0 голосов
/ 20 января 2019

SimpleDateFormat позволяет указать TimeZone для анализа.

например: formatter.setTimeZone(TimeZone.getTimeZone("America/New_York"));

Или, если вы просто хотели использовать часовой пояс GMT-5 (т.е. без каких-либо правил перехода на летнее время): formatter.setTimeZone(TimeZone.getTimeZone("GMT-5"));

Редактировать : имея возможность взглянуть на вторую часть вашей проблемы и взглянуть на используемые вами API-интерфейсы календаря - и предположим, что используемые вами классы API-интерфейсов Google приведены в com.google.apisgroupId, google-api-services-calendar artifactId, затем вы также хотите указать TimeZone смещения при создании экземпляра com.google.api.client.util.DateTime.

Использование SimpleDateFormat с указанным часовым поясом для Нью-Йорка для анализа строки «19.02.2009 16:15» в дату даст вам java.util.Date, который переносит длинное значение 1550610900000 (независимо от вашего фактического местного часового пояса). Обратите внимание, что если вы напечатаете toString() из этого Date, он даст дату в часовом поясе вашего локального компьютера.Например: для меня это говорит: «Ср 20 Фев 05:15:00 SGT 2019».

DateTime извлекает это длинное значение из указанной даты с помощью getTime () и сохраняет его как внутреннее длинное значение.

DateTime (или, по крайней мере, версия класса DateTime Iбыстро схваченный для экспериментов ( v3-rev364-1.25.0 )) также имеет конструктор, который принимает TimeZone, откуда он извлекает смещение из UTC через getOffset().Если вы не передадите его, он будет использовать TimeZone.getDefault().getOffset(value) для внутреннего использования.Позже, когда вызывается его toString (), он будет отображать его, используя смещение, которое он сохранил (полученное из часового пояса).

Пример:

SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy hh:mm a", Locale.US);
formatter.setTimeZone(TimeZone.getTimeZone("America/New_York"));
Date date = formatter.parse("2/19/2019 4:15 PM");

DateTime startDateTimeNY = new DateTime(date,TimeZone.getTimeZone("America/New_York")); 
DateTime startDateTimeSG = new DateTime(date,TimeZone.getTimeZone("Asia/Singapore"));   
DateTime startDateTimeNBO = new DateTime(date,TimeZone.getTimeZone("Africa/Nairobi"));  
System.out.println(startDateTimeNY); //prints 2019-02-19T16:15:00.000-05:00
System.out.println(startDateTimeSG); //prints 2019-02-20T05:15:00.000+08:00
System.out.println(startDateTimeNBO); //prints 2019-02-20T00:15:00.000+03:00

(Вы можете увидеть различные локальныераз в выводе есть)

У меня не было времени, чтобы подтвердить это, но похоже, EventDateTime просто использует toString() из DateTime для значения dateTime (если вы неJsonFactory установлено в нем).(TimeZone хранит его для другой цели?)

TLDR: указание TimeZone на SimpleDateFormat позволяет правильно считывать дату из ее часового пояса источника и форматировать выходные данные так, как вам нужно.изменить ваш вызов на DateTime конструктор, чтобы использовать желаемый часовой пояс таким образом:

DateTime startDateTime = new DateTime(date,TimeZone.getTimeZone("America/New_York"));

...