Унифицированный метод для разбора строки в любом формате, совместимом с ISO-8601 - PullRequest
1 голос
/ 20 июня 2019

Мне нужен унифицированный метод для анализа любой строки, совместимой с ISO-8601 .К сожалению, ни Joda, ни fastxml StdDateFormat не обладают достаточной квалификацией для этого.

Я хочу интерпретировать следующие два атрибута

  • String start;
  • String timezone;

start - строка, соответствующая ISO-8601, может быть в любом совместимом формате, например "2020-05-15T20: 30: 52 + 03: 00" или 2020-05-15 ". timezone - это часовой пояс IANA , например, "Европа / Москва".

Желаемая логика:

  1. Если timezone, если не указано,Расширить start до полностью определенного UTC независимо от того, какую информацию о часовом поясе он включает. Например, расширить «2020-05-15T20: 30» до «2020-05-15T20: 30: 00.000Z».

  2. Если указано timezone, а информация о часовом поясе в start конфликтует с timezone, то сообщить об ошибке. Например, timezone = "Азия / Шанхай" и start = "2020-05-15T20: 30: 52 + 03: 00 ".

  3. Если указано timezone и не конфликтует с информацией о часовом поясе в start, тогда расширьте start доквалифицированный формат ISO-8601. Для экзаменаple, timezone = "Европа / Москва", start = "2020-05-15T20: 30 + 03: 00", затем расширить start до "2020-05-15T20: 30: 00.000 + 03: 00".

  4. Если указано 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

Проблемы с блокировкой

Существует три проблемы с блокировкой.

  1. fasterxml StdDateFormat изменит original timezone на local timezone неявно.Например, строка ввода - «2019-06-16T09: 30: 20 + 06: 00», дата вывода - «2019-06-16T11: 30: 20.000 + 08: 00».

  2. Когда информация о часовом поясе не включена в 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 ".

  3. fasterxml невозможно проанализировать" 20190616T09: 30: 20 + 06: 00 ".Ни Joda, ни fastmxl не могут проанализировать "20190618T110044Z".

...