Мне нужно сохранить часовой пояс, из которого было отправлено электронное письмо. Как лучше всего извлечь его из заголовка электронного письма «Дата:» (дата RFC822)? И в каком формате рекомендуется хранить его в базе данных (я использую спящий режим)?




Извлеките данные из заголовка, используя какую-то подстроку или регулярное выражение. Разберите дату с помощью SimpleDateFormatter, чтобы создать объект Date.
Вероятно, проще всего выполнить синтаксический анализ с помощью JodaTime, поскольку он поддерживает ISO8601, см. Разбор и форматирование даты и времени в Java с помощью Joda Time.
DateTimeFormatter parser2 = ISODateTimeFormat.dateTimeNoMillis();
System.out.println(parser2.parseDateTime(your_date_string));
Время всегда должно храниться в формате UTC (GMT) с часовым поясом, то есть после синтаксического анализа преобразовать часовой пояс в GMT и удалить смещение перехода на летнее время и сохранить исходный часовой пояс.
Вы должны сохранить дату с часовым поясом после преобразования в UTC.
Если вы удалите или не обработаете часовой пояс, это вызовет проблемы при работе с данными, поступившими из другого часового пояса.
@AdamGent Это то, что я имел в виду, говоря «если вы удалите или не обработаете часовой пояс, это может вызвать проблемы ....». Я отредактирую, чтобы сделать это кристально ясным.
Удалите также сообщение в блоге или обратите внимание на серьезную опасность параллелизма при создании общедоступного статического массива simpledateformat.
Я отказался от использования SimpleDateFormat для использования JodaTime, хотя рассмотрел тот, который встроен в JAXB
Спасибо (извините за требовательность)! Также я понятия не имел, что JAXB имеет форматирование / синтаксический анализ времени. Какие классы JAXB это делают? Также ISO8601 несовместим с форматом RFC822. ISO - это превосходный формат, но, к сожалению, в электронных письмах используется формат RFC822.
@AdamGent javax.xml.bind.DatatypeConverter.parseDateTime (...). Также у меня нет проблем с вашими комментариями - они были полезны и улучшили качество ...
Часовой пояс в электронном письме не будет показывать, в каком часовом поясе оно было отправлено. Некоторые программы используют любое время по Гринвичу или Гринвичу. Конечно, часовой пояс является частью значения даты и времени и также должен быть проанализирован.
Зачем тебе это знать. - Вы хотите нормализовать метку времени? Затем используйте DateFormat для его анализа. - Вы хотите определить часовой пояс пользователя, отправившего электронное письмо? Это не будет работать правильно.
Я хочу определить часовой пояс пользователя, отправившего электронное письмо. Почему это не сработает?
Потому что некоторые программы отправляют время в формате UTC или GMT независимо от часового пояса пользователя. Это часовой пояс сформированной строки даты, а не пользовательского компьютера.
Похоже, вы уже упоминали об этом в одном из своих комментариев, но я думаю, что это ваш лучший ответ. Библиотека JavaMail содержит код разбора заголовка RFC822 Date в javax.mail.internet.MailDateFormat. К сожалению, он не предоставляет прямой доступ к синтаксическому анализу часового пояса, поэтому вам нужно будет скопировать необходимый код прямо из javax.mail.internet.MailDateParser, но стоит воспользоваться уже проделанной тщательной работой.
Что касается его хранения, синтаксический анализатор выдаст вам дату в виде смещения, поэтому вы сможете сохранить его как int (позволяя Hibernate переводить это в вашу базу данных за вас).
Он может использовать парсер Mime4J DateTime вместо дружественного (ироничного) MailDateParser с ограниченной областью видимости. Смотрите мой ответ.
Я рекомендую вам использовать Mime4J.
Библиотека предназначена для разбора всяческой ерунды. Для разбора дат вы должны использовать его DateTimeParser.
int zone = new DateTimeParser(new StringReader("Fri, 27 Jul 2012 09:13:15 -0400")).zone();
После этого я обычно конвертирую время в Дата и время Джоды. Не используйте SimpleDateFormatter, поскольку он не охватывает все случаи для RFC822.
Ниже вы получите Joda TimeZone (из зоны int выше), который превосходит Java TZ.
// Stupid hack in case the zone is not in [-+]zzzz format
final int hours;
final int minutes;
if (zone > 24 || zone < -24 ) {
hours = zone / 100;
minutes = minutes = Math.abs(zone % 100);
}
else {
hours = zone;
minutes = 0;
}
DateTimeZone.forOffsetHoursMinutes(hours, minutes);
Теперь единственная проблема заключается в том, что часовой пояс, который вы всегда будете получать, будет числовым часовым поясом, который все еще может быть неправильным часовым поясом пользователя, отправляющего электронное письмо (при условии, что почтовое приложение отправило пользователям TZ, а не только UTC).
Например, -0400 не является EDT (т.е. America / New_York), потому что не учитывает летнее время.
Спасибо jhawk28. Однако я могу получить дату с помощью класса MailDateFormat. Этот класс также анализирует часовой пояс, но, похоже, нет простого способа найти этот часовой пояс, кроме копирования кода из MailDateParser.