解析任何符合ISO-8601格式的字符串的统一方法

时间:2019-06-20 06:04:10

标签: java datetime timezone jodatime fasterxml

我需要一个统一的方法来解析任何符合ISO-8601的字符串。不幸的是,Joda或fastxml StdDateFormat都不具备这样做的资格。

我想解释以下两个属性

  • 字符串开始;
  • 字符串时区;

start是符合ISO-8601的字符串,可以是任何符合标准的格式,例如“ 2020-05-15T20:30:52 + 03:00”或2020-05-15”。{{1 }}是IANA timezone,例如“欧洲/莫斯科”。

所需的逻辑是:

  1. 如果未指定timezone,则将timezone扩展为完全合格的UTC,而不考虑其包括的时区信息。例如,将“ 2020-05-15T20:30”扩展到“ 2020-05-15T20:30:00.000Z”。

  2. 如果指定了start,并且timezone中的时区信息与start冲突,则报告错误。例如,timezone =“亚洲/上海”和timezone =“ 2020-05-15T20:30:52 + 03:00”。

  3. 如果指定了start,并且与timezone中的时区信息没有冲突,则将start扩展为标准ISO-8601格式。例如,start =“欧洲/莫斯科”,timezone =“ 2020-05-15T20:30 + 03:00”,然后将start扩展为“ 2020-05-15T20: 30:00.000 + 03:00“。

  4. 如果指定了start,并且timezone没有时区信息,则将start添加到timezone并将其扩展为完全合格的ISO-8601格式。例如,start =“ Europe / Moscow”和timezone =“ 2020-05-15”,然后将start扩展到“ 2020-05-15T00:00:00.000 + 03: 00”。

此代码段着重于解析符合ISO-8601的字符串。尚无start参数涉及。它尝试使用timezoneJoda DateTime

fasterxml StdDateFormat

注意,我的本地时区是“亚洲/上海”,即+08:00

预期结果


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();
    }
}

实际结果

=============
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

阻止问题

存在三个阻止问题。

  1. 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。例如,输入字符串为“ 2019-06-16T09:30:20 + 06:00”,输出日期为“ 2019-06-16T11:30:20.000 + 08:00”。

  2. local timezone中不包含时区信息时,startJoda都会隐式添加本地时区。例如,输入字符串为“ 2019-06-16T09:30”,输出日期为“ 2019-06-16T17:30:00.000 + 08:00”。 (我的本地时区是“亚洲/上海”,例如+08:00)我期望有机会在其中添加fasterxml。例如,还有另一个参数指定为“ Asia / Shanghai”,timezone =“ 2019-06-16T09:30”,所需的输出类似于:“ 2019-06-16T09:30” +“ Asia / Shanghai“ =” 2019-06-16T09:30:00.000 + 08:00“。

  3. start无法解析“ 20190616T09:30:20 + 06:00”。 Joda和fastmxl都无法解析“ 20190618T110044Z”。

0 个答案:

没有答案