在XMLGregorianCalendar中指定日期格式

27

我希望将一个以 XMLGregorianCalendar 格式表示的日期发送给一个 Web 服务,该服务希望收到以 yyyy-dd-mm 格式表示的信息。我使用以下代码创建一个 XMLGregorianCalendar 并将其发送给 Web 服务。

Date dob = null;
DateFormat df = new SimpleDateFormat("dd/MM/yyyy");

try {
    XMLGregorianCalendar date2;
    dob = df.parse("13/06/1983");

    GregorianCalendar c = new GregorianCalendar();
    c.setTimeInMillis(dob.getTime());
    date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
    System.out.println(date2);
}
catch(DatatypeConfigurationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
catch(ParseException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

很不幸我总是得到日期 1983-06-13T00:00:00.000-04:00,并且时间也会被包含在输出结果中。是否可能只获取日期?你能帮我吗?

5个回答

34

你不需要指定一个“SimpleDateFormat”,它很简单: 你必须在不想显示的地方指定常量“DatatypeConstants.FIELD_UNDEFINED”

GregorianCalendar cal = new GregorianCalendar();
cal.setTime(new Date());
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH), DatatypeConstants.FIELD_UNDEFINED);

在上述代码中出现了“javax.xml.datatype.DatatypeConfigurationException: Provider org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl not found”错误。请建议该怎么做。 - Neha
5
从Java 8开始,你应该使用以下代码:DatatypeFactory.newInstance().newXMLGregorianCalendar(c.get(Calendar.YEAR), c.get(Calendar.MONTH)+1, c.get(Calendar.DAY_OF_MONTH), DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED)来创建XMLGregorianCalendar对象。 - leccionesonline

17

只使用SimpleDateFormat就可以简单地实现,不需要传递所有的参数:

    String FORMATER = "yyyy-MM-dd'T'HH:mm:ss'Z'";

    DateFormat format = new SimpleDateFormat(FORMATER);

    Date date = new Date();
    XMLGregorianCalendar gDateFormatted =
        DatatypeFactory.newInstance().newXMLGregorianCalendar(format.format(date));

完整示例在此处

注意:此方法仅适用于使用格式化程序yyyy-MM-dd以删除最后2个字段:毫秒和时区,或删除整个时间组件。


这是最好的答案。 - Panadol Chong
不要将 Z 视为文字。它是距离 UTC 零偏移量,这很可能是不正确的。 - Ole V.V.

16

好的,我明白了...

Date dob=null;
DateFormat df=new SimpleDateFormat("dd/MM/yyyy");
dob=df.parse( "13/06/1983" );
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(dob);
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH), DatatypeConstants.FIELD_UNDEFINED);

这将以正确的格式呈现它。


1
为什么在cal.get(Calendar.MONTH)+1中要加上+1 - Manu Artero
6
在java.util.Calendar中,1月被表示为0,因此每个月都向后移动了1个位置。不要问我原因...人们建议在适当的情况下使用Joda Time(http://www.joda.org/joda-time/)。 @Manu - foki

3

这是一种非常简单的方法,适用于任何格式。只需将其转换为所需的格式字符串即可。

XMLGregorianCalendar gregFmt = DatatypeFactory.newInstance().newXMLGregorianCalendar(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(new Date()));
System.out.println(gregFmt);

最简单的解决方案! - cmg_george
非常简单并且棒极了的解决方案。谢谢。 - apr

2

并没有一个理想的转换方式,但我想提供几个选项。

java.time

首先,您应该使用java.time中的LocalDate,它是现代Java日期和时间API,用于解析和保存日期。避免使用DateSimpleDateFormat,因为它们存在设计问题,并且已经过时了。后者尤其令人头疼。

最初的回答:

没有最佳的转换方式,但建议使用现代Java日期和时间API中的LocalDate类来解析和保存日期。不要使用已经过时的DateSimpleDateFormat类,因为它们存在设计问题和缺陷。SimpleDateFormat类尤其容易出错。

    DateTimeFormatter originalDateFormatter = DateTimeFormatter.ofPattern("dd/MM/uuuu");

    String dateString = "13/06/1983";
    LocalDate date = LocalDate.parse(dateString, originalDateFormatter);
    System.out.println(date);

输出结果为:

1983-06-13

你需要继续吗?LocalDate.toString()会生成你所要求的格式。

格式化和解析

假设你确实需要一个XMLGregorianCalendar,最简单的转换选项是:

    XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar(date.toString());
    System.out.println(xmlDate);

1983年6月13日

将日期转换为字符串并解析回去对我来说感觉浪费,但正如我所说,这很容易,而且我认为结果符合预期。

逐个传递年、月和日


    XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance()
            .newXMLGregorianCalendarDate(date.getYear(), date.getMonthValue(),
                    date.getDayOfMonth(), DatatypeConstants.FIELD_UNDEFINED);

结果与以前相同。我们需要明确表示我们不想要时区偏移量(这就是DatatypeConstants.FIELD_UNDEFINED的含义)。如果有人想知道,LocalDateXMLGregorianCalendar都像人类一样计算月份,因此不需要加1或减1。 通过GregorianCalendar进行转换 我只向您展示此选项,因为我认为这是官方方式:将LocalDate转换为ZonedDateTime,然后转换为GregorianCalendar,最后转换为XMLGregorianCalendar
    ZonedDateTime dateTime = date.atStartOfDay(ZoneOffset.UTC);
    GregorianCalendar gregCal = GregorianCalendar.from(dateTime);
    XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar(gregCal);
    xmlDate.setTime(DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED,
            DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED);
    xmlDate.setTimezone(DatatypeConstants.FIELD_UNDEFINED);

我喜欢转换本身,因为我们既不需要使用字符串,也不需要传递单个字段(注意以正确的顺序执行)。我不喜欢的是我们必须传递一个白天时间和时区偏移量,然后手动清除这些字段。

最初的回答:

我喜欢转换本身,因为它不需要使用字符串或传递单个字段(需要注意正确的顺序)。但我不喜欢的是,我们必须传递一个时间和时区偏移量,然后手动清除这些字段。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接