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

Java 以任何符合ISO-8601的格式解析字符串的统一方法,java,datetime,timezone,jodatime,fasterxml,Java,Datetime,Timezone,Jodatime,Fasterxml,我需要一个统一的方法来解析任何兼容的字符串。不幸的是,Joda和fastxml StdDateFormat都不能完全胜任这项工作 我想解释以下两个属性 字符串开始 字符串时区 start是符合ISO-8601标准的字符串,可以是任何符合标准的格式,例如“2020-05-15T20:30:52+03:00”或2020-05-15.时区是,例如“欧洲/莫斯科” 所需的逻辑是: 如果时区如果未指定,则将开始扩展到完全限定的UTC,无论其包含什么时区信息。例如,将“2020-05-15T20:30”

我需要一个统一的方法来解析任何兼容的字符串。不幸的是,Joda和fastxml StdDateFormat都不能完全胜任这项工作

我想解释以下两个属性

  • 字符串开始
  • 字符串时区
start
是符合ISO-8601标准的字符串,可以是任何符合标准的格式,例如“2020-05-15T20:30:52+03:00”或2020-05-15.
时区是,例如“欧洲/莫斯科”

所需的逻辑是:

  • 如果
    时区
    如果未指定,则将
    开始
    扩展到完全限定的UTC,无论其包含什么时区信息。例如,将“2020-05-15T20:30”扩展到“2020-05-15T20:30:00.000Z”

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

  • 如果指定了
    时区
    ,并且与
    开始
    中的时区信息没有冲突,则将
    开始
    扩展到完全合格的ISO-8601格式。例如,
    时区
    =“欧洲/莫斯科”、
    开始
    =“2020-05-15T20:30+03:00”,然后将
    开始
    扩展到“2020-05-15T20:30:00.000+03:00”“

  • 如果指定了
    时区
    ,并且
    开始
    没有时区信息,则将
    时区
    添加到
    开始
    ,并将其扩展为完全合格的ISO-8601格式。例如,
    时区
    =“欧洲/莫斯科”和
    开始
    =“2020-05-15”,然后将
    开始
    扩展到“2020-05-15T00:00:00.000+03:00”

  • 此代码段主要用于解析符合ISO-8601的字符串。尚未涉及
    时区
    参数。它尝试使用
    Joda DateTime
    fasterxml StdDateFormat

    
    导入java.util.Date;
    导入org.joda.time.DateTime;
    导入org.joda.time.DateTimeZone;
    导入com.fasterxml.jackson.databind.util.StdDateFormat;
    公共类等温线2{
    公开无效测试(){
    字符串[]输入=新字符串[]{
    “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=新的StdDateFormat();
    for(字符串输入:输入){
    System.out.println();
    DateTime输出=null;
    布尔值isStdDateFormatFail=false;
    试一试{
    日期=df.parse(输入);
    输出=新日期时间(日期);
    System.out.println(“对StdDateFormat:\t\t“+输入有效);
    打印(输入、输出);
    }捕获(例外e){
    isStdDateFormatFail=true;
    System.out.println(“======================”);
    System.out.println(“对于StdDateFormat:\t\t”+输入无效);
    }
    如果(isStdDateFormatFail){
    试一试{
    输出=DateTime.parse(输入);
    System.out.println(“对Joda:\t\t”+输入有效);
    打印(输入、输出);
    }捕获(例外e){
    System.out.println(“======================”);
    System.out.println(“对于Joda:\t\t”+输入无效);
    }
    }
    }
    }
    私有void打印(字符串输入、日期时间输出){
    System.out.println(“======================”);
    System.out.println(“输入:\t\t”+输入);
    System.out.println(“输出:\t\t”+输出);
    DateTimeZone=output.getZone();
    System.out.println(“区域:\t\t”+区域);
    }
    公共静态void main(字符串[]args){
    等温线2试验=新等温线2();
    test.test();
    }
    }
    
    注意我的本地时区是“亚洲/上海”,即+08:00

    预期结果 实际结果 封锁问题 有三个阻碍问题

  • fasterxml StdDateFormat
    原始时区
    隐式更改为
    本地时区
    。例如,输入字符串为“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)我期待的是有机会将
    时区添加到其中。例如,另一个参数指定为“亚洲/上海”
    start
    =“2019-06-16T09:30”,所需的输出类似于:“2019-06-16T09:30”+“亚洲/上海”=“2019-06-16T09:30:00.000+08:00”

  • fasterxml
    无法解析“20190616T09:30:20+06:00”。Joda和fastermxl都无法解析“20190618T110044Z”


  • 您甚至没有涵盖所有可能的ISO变体,例如:
    2019-W01-7T03:59Z
    。不,我没有。但即使是不完整的变体列表也无法正确处理。您甚至没有涵盖所有可能的ISO变体,例如:
    2019-W01-7T03:59Z
    。不,我没有。但即使是不完整的变体列表也无法得到妥善处理。
    =============
    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