Общая поддержка формата ISO 8601 в Java 6
Java 7 представила поддержку в SimpleDateFormat
класс для формата ISO 8601, через символ X
(вместо нижнего или верхнего регистра Z
). Поддержка таких форматов в Java 6 требует предварительной обработки, поэтому лучшим подходом является вопрос.
этот новый формат является надмножеством Z
(верхний регистр Z), с 2 дополнительными вариациями:
- поле "минуты" является необязательным (т. е. допустимы 2-значные вместо 4-значные часовые пояса)
- A символ двоеточия ( ' :') может использоваться для отделения 2-значного поля "часы" от 2-значного поля "минуты").
Итак, как можно наблюдать из Java 7 документация SimpleDateFormat
, следующие 3 формата теперь действительны (вместо только второго, покрытого Z
в Java 6) и, конечно, эквивалент:
- -08
- -0800
- -08:00
как обсуждается в ранее вопрос о специальном случае поддержки такого "расширенного" формата часового пояса, всегда с": "в качестве разделителя, лучший подход для обратной передачи функциональности Java 7 в Java 6-подкласс SimpleDateformat
класс и переопределить его parse()
метод, я.е:
public Date parse(String date, ParsePosition pos)
{
String iso = ... // Replace the X with a Z timezone string, using a regex
if (iso.length() == date.length())
{
return null; // Not an ISO 8601 date
}
Date parsed = super.parse(iso, pos);
if (parsed != null)
{
pos.setIndex(pos.getIndex()+1); // Adjust for ':'
}
return parsed;
}
обратите внимание, что подкласс SimpleDateFormat
объекты выше должны быть инициализированы соответствующим Z
на основе шаблона, т. е. если подкласс ExtendedSimpleDateformat
и вы хотите проанализировать даты, соответствующие шаблону yyyy-MM-dd'T'HH:mm:ssX
, то вы должны использовать объекты, созданные как
new ExtendedSimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
в вышеуказанном ранее вопрос регулярное выражение :(?=[0-9]{2}$)
было предложено избавиться от": "и в аналогичный вопрос регулярное выражение (?<=[+-]d{2})$
было предложено добавить поле "минута" как 00
, если это необходимо.
очевидно, что запуск 2 замены успешно может быть использован для достижения полной функциональности. Итак,iso
локальная переменная в переопределенном parse()
метод будет установлен как
iso = date.replaceFirst(":(?=[0-9]{2}$)","");
или
iso = iso.replaceFirst("(?<=[+-]d{2})$", "00");
С if
проверьте между, Чтобы убедиться, что pos
значение также устанавливается правильно позже, а также для length()
сравнение ранее.
вопрос в том, можем ли мы использовать одно регулярное выражение для достижения того же эффекта, включая информацию, необходимую для не ненужной проверки длины и для правильной настройки pos
a спустя несколько строк?
реализация предназначено для кода, который читает очень большое количество строковых полей, которые могут быть в любом формате (даже без даты), выбирает только те, которые соответствуют формату и возвращает разобранный Ява
2 ответов
Кажется, что вы можете использовать это:
import java.util.Calendar;
import javax.xml.bind.DatatypeConverter;
public class TestISO8601 {
public static void main(String[] args) {
parse("2012-10-01T19:30:00+02:00"); // UTC+2
parse("2012-10-01T19:30:00Z"); // UTC
parse("2012-10-01T19:30:00"); // Local
}
public static Date parse(final String str) {
Calendar c = DatatypeConverter.parseDateTime(str);
System.out.println(str + "\t" + (c.getTime().getTime()/1000));
return c.getTime();
}
}
вы можете использовать java.время, современный API даты и времени Java, в Java 6. Это казалось бы мне хорошим, а также перспективным решением. Он имеет хорошую поддержку ISO 8601.
import org.threeten.bp.OffsetDateTime;
import org.threeten.bp.format.DateTimeFormatter;
public class DemoIso8601Offsets {
public static void main(String[] args) {
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+0200",
DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXX")));
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+02",
DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssX")));
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+02:00"));
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00Z"));
}
}
выход из этой программы-это:
2012-10-01T19:30+02:00 2012-10-01T19:30+02:00 2012-10-01T19:30+02:00 2012-10-01T19:30Z
требуется добавить библиотеку Backport ThreeTen в настройку проекта.
- в Java 8 и более поздних версиях и на новых устройствах Android (от уровня API 26) современный API поставляется встроенный.
- в Java 6 и 7 получите Threeten Backport, backport новых классов (ThreeTen для JSR 310; см. Ссылки внизу).
- на (Старше) Android использовать Android издание ThreeTen Backport. Это называется ThreeTenABP. И убедитесь, что вы импортируете классы даты и времени из
org.threeten.bp
С подпакетами.
как вы можете видеть из кода +02
и +0200
требует форматирования, в котором можно указать формат смещения, а +02:00
(и Z
too) соответствует формату по умолчанию и не нуждается в указании.
можем ли мы проанализировать все форматы смещения, используя один и тот же форматер?
при чтении смешанных данных, вы не хотите обрабатывать каждый формат офсетная специально. Лучше использовать дополнительные части в формате pattern string:
DateTimeFormatter allInOne
= DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss[XXX][XX][X]");
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+0200", allInOne));
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+02", allInOne));
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00+02:00", allInOne));
System.out.println(OffsetDateTime.parse("2012-10-01T19:30:00Z", allInOne));
выход такой же, как и выше. Квадратные скобки в [XXX][XX][X]
означает, что либо format +02:00
, +0200
или +02
может быть подарок.
ссылки
-
Oracle учебник: дата и время объясняя, как использовать
java.time
. -
запрос спецификации Java (JSR) 310, где
java.time
была впервые описана. -
ThreeTen Backport project на базу
java.time
к Java 6 и 7 (ThreeTen для JSR-310). - ThreeTenABP, Android издание ThreeTen Backport
- вопрос: Как использовать ThreeTenABP в проекте Android с очень подробного объяснения.