Мне нужен унифицированный метод для анализа любой строки, совместимой с ISO-8601 .К сожалению, ни Joda, ни fastxml StdDateFormat не обладают достаточной квалификацией для этого.
Я хочу интерпретировать следующие два атрибута
- String start;
- String timezone;
start
- строка, соответствующая ISO-8601, может быть в любом совместимом формате, например "2020-05-15T20: 30: 52 + 03: 00" или 2020-05-15 ". timezone
- это часовой пояс IANA , например, "Европа / Москва".
Желаемая логика:
Если timezone
, если не указано,Расширить start
до полностью определенного UTC независимо от того, какую информацию о часовом поясе он включает. Например, расширить «2020-05-15T20: 30» до «2020-05-15T20: 30: 00.000Z».
Если указано timezone
, а информация о часовом поясе в start
конфликтует с timezone
, то сообщить об ошибке. Например, timezone
= "Азия / Шанхай" и start
= "2020-05-15T20: 30: 52 + 03: 00 ".
Если указано timezone
и не конфликтует с информацией о часовом поясе в start
, тогда расширьте start
доквалифицированный формат ISO-8601. Для экзаменаple, timezone
= "Европа / Москва", start
= "2020-05-15T20: 30 + 03: 00", затем расширить start
до "2020-05-15T20: 30: 00.000 + 03: 00".
Если указано timezone
, а start
не имеет информации о часовом поясе, то добавьте timezone
к start
и расширите его до полностью определенного формата ISO-8601.Например, timezone
= "Европа / Москва" и start
= "2020-05-15", а затем расширить start
до "2020-05-15T00: 00: 00.000 + 03: 00".
Этот фрагмент кода фокусируется на разборе строк, соответствующих ISO-8601.Параметр timezone
пока не задействован.Он пытается с Joda DateTime
и fasterxml StdDateFormat
.
import java.util.Date;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import com.fasterxml.jackson.databind.util.StdDateFormat;
public class ISOTest2 {
public void test() {
String [] inputs = new String [] {
"2019-06-16T09:30:20+06:00",
"2019-06-16T09:30Z",
"2019-06-16T09:30:20",
"2019-06-16T09:30",
"2019-06-16T",
"2019-06-16",
"20190616T09:30:20+06:00",
"20190618T110044Z"
};
StdDateFormat df = new StdDateFormat();
for (String input : inputs) {
System.out.println();
DateTime output = null;
boolean isStdDateFormatFail = false;
try {
Date date = df.parse(input);
output = new DateTime(date);
System.out.println("Valid for StdDateFormat:\t\t" + input);
print(input, output);
} catch (Exception e) {
isStdDateFormatFail = true;
System.out.println("=============");
System.out.println("Invalid for StdDateFormat:\t\t" + input);
}
if (isStdDateFormatFail) {
try {
output = DateTime.parse(input);
System.out.println("Valid for Joda:\t\t" + input);
print(input, output);
} catch (Exception e) {
System.out.println("=============");
System.out.println("Invalid for Joda:\t\t" + input);
}
}
}
}
private void print(String input, DateTime output) {
System.out.println("=============");
System.out.println("Input:\t\t" + input);
System.out.println("Output:\t\t" + output);
DateTimeZone zone = output.getZone();
System.out.println("Zone:\t\t" + zone);
}
public static void main(String[] args) {
ISOTest2 test = new ISOTest2();
test.test();
}
}
Примечание Мой местный часовой пояс "Азия / Шанхай", то есть +08: 00
Ожидаемый результат
=============
Input: 2019-06-16T09:30:20+06:00
Output: 2019-06-16T09:30:20.000+06:00
Zone: +0600
=============
Input: 2019-06-16T09:30Z
Output: 2019-06-16T09:30:00.000Z
Zone: UTC
=============
Input: 2019-06-16T09:30:20
Output: 2019-06-16T09:30:20.000Z
Zone: UTC
=============
Input: 2019-06-16T09:30
Output: 2019-06-16T09:30:00.000Z
Zone: UTC
=============
Input: 2019-06-16T
Output: 2019-06-16T00:00:00.000Z
Zone: UTC
=============
Input: 2019-06-16
Output: 2019-06-16T00:00:00.000Z
Zone: UTC
=============
Input: 20190616T09:30:20+06:00
Output: 2019-06-16T09:30:20.000+06:00
Zone: +0600
=============
Input: 20190618T110044Z
Output: 2019-06-18T11:00:44.000Z
Zone: UTC
Фактический результат
Valid for StdDateFormat: 2019-06-16T09:30:20+06:00
=============
Input: 2019-06-16T09:30:20+06:00
Output: 2019-06-16T11:30:20.000+08:00
Zone: Asia/Shanghai
Valid for StdDateFormat: 2019-06-16T09:30Z
=============
Input: 2019-06-16T09:30Z
Output: 2019-06-16T17:30:00.000+08:00
Zone: Asia/Shanghai
Valid for StdDateFormat: 2019-06-16T09:30:20
=============
Input: 2019-06-16T09:30:20
Output: 2019-06-16T17:30:20.000+08:00
Zone: Asia/Shanghai
Valid for StdDateFormat: 2019-06-16T09:30
=============
Input: 2019-06-16T09:30
Output: 2019-06-16T17:30:00.000+08:00
Zone: Asia/Shanghai
=============
Invalid for StdDateFormat: 2019-06-16T
Valid for Joda: 2019-06-16T
=============
Input: 2019-06-16T
Output: 2019-06-16T00:00:00.000+08:00
Zone: Asia/Shanghai
Valid for StdDateFormat: 2019-06-16
=============
Input: 2019-06-16
Output: 2019-06-16T08:00:00.000+08:00
Zone: Asia/Shanghai
=============
Invalid for StdDateFormat: 20190616T09:30:20+06:00
Valid for Joda: 20190616T09:30:20+06:00
=============
Input: 20190616T09:30:20+06:00
Output: 20190616-01-01T09:30:20.000+06:00
Zone: +06:00
=============
Invalid for StdDateFormat: 20190618T110044Z
=============
Invalid for Joda: 20190618T110044Z
Проблемы с блокировкой
Существует три проблемы с блокировкой.
fasterxml StdDateFormat
изменит original timezone
на local timezone
неявно.Например, строка ввода - «2019-06-16T09: 30: 20 + 06: 00», дата вывода - «2019-06-16T11: 30: 20.000 + 08: 00».
Когда информация о часовом поясе не включена в start
, оба Joda
и fasterxml
неявно добавляют местный часовой пояс.Например, строка ввода - «2019-06-16T09: 30», дата вывода - «2019-06-16T17: 30: 00.000 + 08: 00».(Мой местный часовой пояс - "Азия / Шанхай", например, +08: 00). Я ожидаю, что это шанс добавить timezone
к нему.Например, есть другой параметр, заданный как «Азия / Шанхай», start
= «2019-06-16T09: 30», желаемый вывод выглядит примерно так: «2019-06-16T09: 30» + «Азия / Шанхай"=" 2019-06-16T09: 30: 00.000 + 08: 00 ".
fasterxml
невозможно проанализировать" 20190616T09: 30: 20 + 06: 00 ".Ни Joda, ни fastmxl не могут проанализировать "20190618T110044Z".