【问题标题】:String date to xmlgregoriancalendar conversion字符串日期到 xmlgregoriancalendar 的转换
【发布时间】:2014-01-25 01:04:17
【问题描述】:

我已经写了这个函数:

public static XMLGregorianCalendar getXMLGregorianCalendar(String date) throws OmniException{
    XMLGregorianCalendar xmlCalender=null;
    GregorianCalendar calender = new GregorianCalendar();
    calender.setTime(Util.stringToJavaDate(date));
    xmlCalender = DatatypeFactory.newInstance().newXMLGregorianCalendar(calender);
    return xmlCalender;
}

public static Date  stringToJavaDate(String sDate)  throws OmniException{
    Date date=null;
    date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH).parse(sDate);        
    return date;  
}

当我以"2014-01-07" 传递日期时,我将输出日期为2014-01-06T18:30:00:000Z 我哪里错了? 如果我只想获得2014-01-06T18:30:002014-01-06T18:30:00Z,该怎么办
任何帮助表示赞赏

【问题讨论】:

  • 您是否正确设置了区域设置?
  • 我将它设置为 locale.ENGLISH in simpledateformat ;这样对吗 ??请指导我! :)
  • 您必须将其设置为您所在国家/地区的语言环境,而不仅仅是英语。此处给出示例 - docs.oracle.com/javase/tutorial/i18n/locale/create.html
  • 得到了一些帮助:在 XMLGregorianCalendar[1] [1] 中指定日期格式:stackoverflow.com/questions/14060161/…
  • 仅供参考,这个问题中显示的类现在已经过时,现在是遗留的,被 java.time 类所取代。

标签: java string date


【解决方案1】:

找到如下解决方案....发布它,因为它也可以帮助其他人:)

DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date = format.parse("2014-04-24 11:15:00");

GregorianCalendar cal = new GregorianCalendar();
cal.setTime(date);

XMLGregorianCalendar xmlGregCal =  DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);

System.out.println(xmlGregCal);

输出:

2014-04-24T11:15:00.000+02:00

【讨论】:

  • 在你解析了 Date 并设置了 GregorianCalendar 的时间之后,你可以将 calendar 作为参数传递给 newXMLGregorianCalendar(GregorianCalendar cal)
【解决方案2】:

对我来说,最优雅的解决方案是这个:

XMLGregorianCalendar result = DatatypeFactory.newInstance()
    .newXMLGregorianCalendar("2014-01-07");

使用 Java 8。

扩展示例:

XMLGregorianCalendar result = DatatypeFactory.newInstance()
    .newXMLGregorianCalendar("2014-01-07");
System.out.println(result.getDay());
System.out.println(result.getMonth());
System.out.println(result.getYear());

打印出来:

7
1
2014

【讨论】:

  • 这个答案对我对xml类型没有什么经验非常有帮助。
  • 此解决方案仅对 XML Schema 中指定的 XML 日期格式有用:w3.org/TR/xmlschema-2/#dateTime-lexical-representation
  • 如果你有日期和时间,这行得通吗?比如说,以这种格式:“2014-01-07 23:47”
【解决方案3】:

tl;博士

  • 尽可能使用现代的java.time 类,而不是糟糕的遗留类。
  • 始终指定所需/预期的时区或与 UTC 的偏移量,而不是隐式依赖 JVM 的当前默认值。

示例代码(无异常处理):

XMLGregorianCalendar xgc = 
    DatatypeFactory                           // Data-type converter.
    .newInstance()                            // Instantiate a converter object.
    .newXMLGregorianCalendar(                 // Converter going from `GregorianCalendar` to `XMLGregorianCalendar`.
        GregorianCalendar.from(               // Convert from modern `ZonedDateTime` class to legacy `GregorianCalendar` class.
            LocalDate                         // Modern class for representing a date-only, without time-of-day and without time zone.
            .parse( "2014-01-07" )            // Parsing strings in standard ISO 8601 format is handled by default, with no need for custom formatting pattern. 
            .atStartOfDay( ZoneOffset.UTC )   // Determine the first moment of the day as seen in UTC. Returns a `ZonedDateTime` object.
        )                                     // Returns a `GregorianCalendar` object.
    )                                         // Returns a `XMLGregorianCalendar` object.
;

将仅日期输入字符串解析为 XMLGregorianCalendar 类的对象

尽可能避免使用糟糕的遗留日期时间类,例如XMLGregorianCalendarGregorianCalendarCalendarDate。仅使用现代 java.time 类。

当出现"2014-01-07" 等字符串时,解析为LocalDate

LocalDate.parse( "2014-01-07" )

要获取带有时间的日期,假设您想要一天中的第一刻,请指定一个时区。让 java.time 确定一天中的第一个时刻,因为在某些日期的某些区域中,它并不总是 00:00:00.0。

LocalDate.parse( "2014-01-07" )
         .atStartOfDay( ZoneId.of( "America/Montreal" ) )

这将返回一个ZonedDateTime 对象。

ZonedDateTime zdt = 
        LocalDate
        .parse( "2014-01-07" )
        .atStartOfDay( ZoneId.of( "America/Montreal" ) )
;

zdt.toString() = 2014-01-07T00:00-05:00[美国/蒙特利尔]

但显然,您希望以 UTC 格式显示一天的开始时间(零时分秒的偏移量)。所以我们指定ZoneOffset.UTC 常量作为我们的ZoneId 参数。

ZonedDateTime zdt = 
        LocalDate
        .parse( "2014-01-07" )
        .atStartOfDay( ZoneOffset.UTC )
;

zdt.toString() = 2014-01-07T00:00Z

末尾的Z 表示UTC(零偏移),发音为“Zulu”。

如果您必须使用旧类,请转换为GregorianCalendar,它是Calendar 的子类。

GregorianCalendar gc = GregorianCalendar.from( zdt ) ;

gc.toString() = java.util.GregorianCalendar[time=1389052800000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="UTC",offset=0 ,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2014,MONTH=0,WEEK_OF_YEAR=2,WEEK_OF_MONTH=2,DAY_OF_MONTH=7, DAY_OF_YEAR=7,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=0,DST_OFFSET=0]

显然,您确实需要一个遗留类XMLGregorianCalendar 的对象。如果调用代码无法更新为使用java.time,请转换。

XMLGregorianCalendar xgc = 
        DatatypeFactory
        .newInstance()
        .newXMLGregorianCalendar( gc ) 
;

实际上,该代码需要 try-catch。

try
{
    XMLGregorianCalendar xgc =
            DatatypeFactory
                    .newInstance()
                    .newXMLGregorianCalendar( gc );
}
catch ( DatatypeConfigurationException e )
{
    e.printStackTrace();
}

xgc = 2014-01-07T00:00:00.000Z

通过适当的异常处理将所有这些放在一起。

// Given an input string such as "2014-01-07", return a `XMLGregorianCalendar` object
// representing first moment of the day on that date as seen in UTC. 
static public XMLGregorianCalendar getXMLGregorianCalendar ( String input )
{
    Objects.requireNonNull( input );
    if( input.isBlank() ) { throw new IllegalArgumentException( "Received empty/blank input string for date argument. Message # 11818896-7412-49ba-8f8f-9b3053690c5d." ) ; }
    XMLGregorianCalendar xgc = null;
    ZonedDateTime zdt = null;

    try
    {
        zdt =
                LocalDate
                        .parse( input )
                        .atStartOfDay( ZoneOffset.UTC );
    }
    catch ( DateTimeParseException e )
    {
        throw new IllegalArgumentException( "Faulty input string for date does not comply with standard ISO 8601 format. Message # 568db0ef-d6bf-41c9-8228-cc3516558e68." );
    }

    GregorianCalendar gc = GregorianCalendar.from( zdt );
    try
    {
        xgc =
                DatatypeFactory
                        .newInstance()
                        .newXMLGregorianCalendar( gc );
    }
    catch ( DatatypeConfigurationException e )
    {
        e.printStackTrace();
    }

    Objects.requireNonNull( xgc );
    return xgc ;
}

用法。

String input = "2014-01-07";
XMLGregorianCalendar xgc = App.getXMLGregorianCalendar( input );

转储到控制台。

System.out.println( "xgc = " + xgc );

xgc = 2014-01-07T00:00:00.000Z

现代日期时间类与旧版

日期时间!= 字符串

不要将日期时间值与其文本表示混为一谈。我们解析字符串以获取日期时间对象,并要求日期时间对象生成一个字符串来表示其值。日期时间对象没有“格式”,只有字符串有格式。

因此,请将您的思维转变为两种不同的模式:模型和演示。确定您想到的日期值,应用适当的时区作为模型。当您需要显示该值时,以用户期望的特定格式生成一个字符串。

避免使用旧的日期时间类

问题和其他答案都使用旧的麻烦的日期时间类,现在被 java.time 类取代。

ISO 8601

您的输入字符串"2014-01-07" 是标准ISO 8601 格式。

中间的T 将日期部分与时间部分分开。

末尾的Z是祖鲁语的缩写,意思是UTC

幸运的是,java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。所以不需要指定格式模式。

LocalDate

LocalDate 类表示没有时间和时区的仅日期值。

LocalDate ld = LocalDate.parse( "2014-01-07" ) ;

ld.toString(): 2014-01-07

一天的开始ZonedDateTime

如果您想查看当天的第一时刻,请指定 ZoneId 时区以获取时间线上的时刻,即 ZonedDateTime。时区至关重要,因为全球各地的日期因地区而异。法国巴黎午夜过后几分钟是新的一天,而魁北克蒙特利尔仍是“昨天”。

永远不要假设一天从 00:00:00 开始。夏令时 (DST) 等异常意味着一天可能从一天中的另一个时间开始,例如 01:00:00。让 java.time 确定第一个时刻。

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ld.atStartOfDay( z ) ;

zdt.toString(): 2014-01-07T00:00:00Z

对于您想要的格式,使用预定义的格式化程序DateTimeFormatter.ISO_LOCAL_DATE_TIME 生成一个字符串,然后用空格替换中间的T

String output = zdt.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME )
                   .replace( "T" , " " ) ; 

2014-01-07 00:00:00


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

从哪里获得 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

  • 这与将java.time对象的字符串表示形式转换为XMLGregorianCalendar无关。
  • @tom_mai78101 你是对的。因此,我修改了第一部分以正面解决问题。谢谢你的批评。答案现在好多了。
  • @George 这种赞赏应该针对Stephen Colebourne,他是领导JSR 310 的人,也是领导其前任Joda-Time 的人。他还领导ThreeTen-ExtraThreeTen-Backport 项目。
【解决方案4】:
GregorianCalendar c = GregorianCalendar.from((LocalDate.parse("2016-06-22")).atStartOfDay(ZoneId.systemDefault()));
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);

【讨论】:

    猜你喜欢
    • 2021-08-15
    • 1970-01-01
    • 1970-01-01
    • 2017-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多