Как вы уже догадались, основная причина ошибки - несоответствие между шаблоном, в котором указана строка даты и времени, и шаблоном, который вы использовали в DateTimeFormatter
. Если вы уже знаете все шаблоны даты и времени, в которых вы получаете строки даты и времени, вы можете создать DateTimeFormatter
с несколькими необязательными шаблонами (заключив шаблоны в квадратные скобки). Если вы получаете дату и время в неизвестном шаблоне (т.е. шаблоне, который вы не указали в DateTimeFormatter
), вы можете выбросить исключение или обработать его в соответствии с вашими требованиями.
Мне нужно проанализировать любую входящую строку даты и времени с указанными пользователем локалью и часовым поясом для единственного шаблона, чтобы впоследствии правильно сохранить ее в базе данных:
Это требование состоит из двух частей: A. Анализировать и преобразовывать дату и время в указанном пользователем языковом стандарте и часовом поясе в эквивалентную дату и время в UTC
(не только рекомендуется, но и требуется некоторыми базами данных. например, PostgreSQL
) Б. Сохраните его в базе данных.
Шаги для выполнения первой части требований:
- Поскольку полученная дата и время находится в указанном пользователем часовом поясе, игнорируйте часовой пояс, содержащийся в строке даты и времени, и анализируйте его до
LocalDateTime
.
- Преобразуйте
LocalDateTime
в ZonedDateTime
в указанном пользователем часовом поясе.
- Преобразуйте это
ZonedDateTime
в ZonedDateTime
в UTC.
- Наконец, преобразуйте
ZonedDateTime
в OffsetDateTime
.
Получив OffsetDateTime
, вы можете сохранить его в базе данных следующим образом:
PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
st.setObject(1, odt);// odt is the instance of OffsetDateTime
st.executeUpdate();
st.close();
Для проверки первой части требования вы можете использовать следующую тестовую программу:
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;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.Locale;
import java.util.Objects;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// Test
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("Enter the date-time string (press Enter without entering anything to quit): ");
String strDateTime = scanner.nextLine();
if (strDateTime.isBlank()) {
break;
}
boolean valid;
// Create Locale
Locale locale = null;
do {
valid = true;
System.out.print("Enter language code e.g. en, fr, in: ");
String languageTag = scanner.nextLine();
if (!isValidForLocale(languageTag)) {
System.out.println("Invalid code. Please try again.");
valid = false;
} else {
locale = Locale.forLanguageTag(languageTag);
}
} while (!valid);
// Create ZoneId
ZoneId zoneId = null;
do {
valid = true;
System.out.print("Enter timezone in the format Continent/City e.g. Asia/Calcutta: ");
String timezone = scanner.nextLine();
try {
zoneId = ZoneId.of(timezone);
} catch (Exception e) {
System.out.println("Invalid timezone. Please try again.");
valid = false;
}
} while (!valid);
try {
System.out.println(getDateTimeInUTC(strDateTime, locale, zoneId));
} catch (DateTimeParseException e) {
System.out.println("The date-time string has the following problem:\n" + e.getMessage());
System.out.println("Please try again.");
}
}
}
static OffsetDateTime getDateTimeInUTC(String strDateTime, Locale locale, ZoneId zoneId)
throws DateTimeParseException {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("[uuuu-M-d H:m:s][EEE MMM d H:m:s zzz uuuu]", locale);
// Ignore the timezone contained in strDateTime and parse strDateTime to
// LocalDateTime. Then, convert the LocalDateTime to ZonedDateTime at zoneId.
// Then, convert this ZonedDateTime to ZonedDateTime at UTC. Finally, convert
// the ZonedDateTime to OffsetDateTime and return the same.
ZonedDateTime zdt = LocalDateTime.parse(strDateTime, dtf).atZone(zoneId).withZoneSameInstant(ZoneOffset.UTC);
return zdt.toOffsetDateTime();
}
static boolean isValidForLocale(String languageTag) {
return Arrays.stream(Locale.getISOLanguages()).anyMatch(l -> Objects.equals(l, languageTag));
}
}
Пробный запуск:
Enter the date-time string (press Enter without entering anything to quit): Mon Dec 21 21:18:37 GMT 2020
Enter language code e.g. en, fr, in: en
Enter timezone in the format Continent/City e.g. Asia/Calcutta: Asia/Calcutta
2020-12-21T15:48:37Z
Enter the date-time string (press Enter without entering anything to quit): 2020-1-23 5:15:8
Enter language code e.g. en, fr, in: en
Enter timezone in the format Continent/City e.g. Asia/Calcutta: Asia/Calcutta
2020-01-22T23:45:08Z
Enter the date-time string (press Enter without entering anything to quit):
person
Arvind Kumar Avinash
schedule
23.12.2020
GMT
в качестве указанного смещения. - person Basil Bourque   schedule 24.12.2020