java.util.Date到XMLGregorianCalendar

mac*_*mac 582 java xml date xmlgregoriancalendar

是不是有一种方便的方法从java.util.Date到XMLGregorianCalendar?

Ben*_*and 1027

GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
Run Code Online (Sandbox Code Playgroud)

  • 如果您愿意使用JodaTime,您可以在一行中执行此操作:DatatypeFactory.newInstance().newXMLGregorianCalendar(new DateTime().toGregorianCalendar()) (35认同)
  • 是否保存将getInstance()保留为某些转换器类中的静态变量?我试图在JavaDoc中查找它但找不到任何东西.有点难以知道并发使用是否会出现问题? (4认同)
  • XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar(YYYY, MM, DD)); (3认同)
  • 请注意,日历不是线程安全的,因此GregorianCalender也不是。另请参见http://stackoverflow.com/questions/12131324/is-java-util-calendar-thread-safe-or-not (3认同)

Nun*_*ado 203

对于那些可能在这里结束了寻找相反的转换(从XMLGregorianCalendarDate):

XMLGregorianCalendar xcal = <assume this is initialized>;
java.util.Date dt = xcal.toGregorianCalendar().getTime();
Run Code Online (Sandbox Code Playgroud)


sas*_*uke 31

这是一种从GregorianCalendar转换为XMLGregorianCalendar的方法; 我将把从java.util.Date转换为GregorianCalendar的部分作为练习:

import java.util.GregorianCalendar;

import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

public class DateTest {

   public static void main(final String[] args) throws Exception {
      GregorianCalendar gcal = new GregorianCalendar();
      XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar(gcal);
      System.out.println(xgcal);
   }

}
Run Code Online (Sandbox Code Playgroud)

编辑:Slooow :-)

  • 这是一个将GregorianCalendar转换为XMLGregorianCalendar的解决方案,而不是问题中指出的内容 (5认同)

Chr*_*ght 22

使用Joda-Time库的一行示例:

XMLGregorianCalendar xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(new DateTime().toGregorianCalendar());
Run Code Online (Sandbox Code Playgroud)

感谢尼古拉酒店距离Mommaerts从他的评论接受的答案.


Ole*_*.V. 17

我想退后一步,以现代的眼光看待这个已有10年历史的问题。Date和和提到的类XMLGregorianCalendar现在已经很旧了。我挑战使用它们并提供替代方法。

  • Date总是设计不当,已有20多年的历史了。这很简单:不要使用它。
  • XMLGregorianCalendar也很老旧,并具有过时的设计。据我了解,它用于以XML格式为XML文档生成日期和时间。喜欢2009-05-07T19:05:45.678+02:002009-05-07T17:05:45.678Z。这些格式与ISO 8601足够吻合,因此java.time(现代的Java日期和时间API)类可以生成它们,我们更喜欢。

无需转换

对于许多(大多数?)目的,现代替代Date将会是Instant。An Instant是一个时间点(按原样Date)。

    Instant yourInstant = // ...
    System.out.println(yourInstant);
Run Code Online (Sandbox Code Playgroud)

此代码段的示例输出:

2009-05-07T17:05:45.678Z

XMLGregorianCalendar上面的示例字符串中的后者相同。如您所知,它来自Instant.toString被隐式调用System.out.println。随着java.time,在许多情况下,我们并不需要,在过去的日子,我们之间进行的转换DateCalendarXMLGregorianCalendar和其他类(在某些情况下,我们确实需要转换,但是,我向您展示一对情侣在下一节) 。

控制偏移

a Date和in 都没Instant有时区或UTC偏移量。本·诺兰德(Ben Noland)先前接受并仍是投票最高的答案,它使用JVM当前的默认时区来选择的偏移量XMLGregorianCalendar。为了在现代对象中包含偏移量,我们使用OffsetDateTime。例如:

    ZoneId zone = ZoneId.of("America/Asuncion");
    OffsetDateTime dateTime = yourInstant.atZone(zone).toOffsetDateTime();
    System.out.println(dateTime);
Run Code Online (Sandbox Code Playgroud)

2009-05-07T13:05:45.678-04:00

同样,这符合XML格式。如果要再次使用当前的JVM时区设置,请设置zoneZoneId.systemDefault()

如果我绝对需要XMLGregorianCalendar怎么办?

有更多的方法可以转换InstantXMLGregorianCalendar。我将介绍几个优点和缺点。首先,就像XMLGregorianCalendar产生类似的字符串一样2009-05-07T17:05:45.678Z,它也可以从这样的字符串构建:

    String dateTimeString = yourInstant.toString();
    XMLGregorianCalendar date2
            = DatatypeFactory.newInstance().newXMLGregorianCalendar(dateTimeString);
    System.out.println(date2);
Run Code Online (Sandbox Code Playgroud)

2009-05-07T17:05:45.678Z

优点:很短,我认为这不会给您带来任何惊喜。缺点:对我来说,将即时信息格式化为字符串并将其解析回是一种浪费。

    ZonedDateTime dateTime = yourInstant.atZone(zone);
    GregorianCalendar c = GregorianCalendar.from(dateTime);
    XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
    System.out.println(date2);
Run Code Online (Sandbox Code Playgroud)

2009-05-07T13:05:45.678-04:00

优点:这是官方转换。控制偏移量自然而然。缺点:它要经过更多步骤,因此会更长。

如果我们有个约会怎么办?

如果您Date从旧的API中获得了一个老式的对象,而现在又无法更改,则将其转换为Instant

    Instant i = yourDate.toInstant();
    System.out.println(i);
Run Code Online (Sandbox Code Playgroud)

输出与以前相同:

2009-05-07T17:05:45.678Z

如果要控制偏移量,请OffsetDateTime按照上述相同的方式进一步转换为。

如果您是老式的,Date并且绝对需要老式的XMLGregorianCalendar,请使用Ben Noland的答案。

链接

  • 您的回答并不是对原始问题的真正回答。当您可以在遗留代码和现代代码之间进行选择时,这很有趣。但如果你带着这个问题来到这里,那就说明你没有选择的权利。即使您要转换的示例也是完全错误的,因为它在 java 7 及更低版本中不起作用。 (3认同)
  • 谢谢@Nagh 的批评,表示赞赏。我承认我曾估计大多数用户都会有选择。对于那些(很多或少数)邪恶老板强迫他们使用 Java 7 的人,我建议通过反向移植使用 java.time,[ThreeTen Backport](https://www.thirden.org/thirdenbp/)。当然,您也可以查看许多其他答案。我仍然认为使用 Java 8 或更高版本的功能的代码是正确的,或者我在工作中编写的大部分代码都是完全错误的。你是对的:我更相信写出“有用的”答案(至少对某些人来说)比“直接”回答所提出的问题更重要。 (2认同)
  • _我更相信写出有用的答案(至少对某些人来说)比直接答案更重要_我同意这一点,但是有用的答案必须包括直接答案才能真正有帮助。我仍然需要处理 Java 5 代码,所以感受一下我的痛苦吧。 (2认同)

khy*_*ylo 12

我以为我会在下面添加我的解决方案,因为上面的答案不符合我的确切需求.我的Xml架构需要单独的Date和Time元素,而不是单独的DateTime字段.上面使用的标准XMLGregorianCalendar构造函数将生成DateTime字段

请注意有几个gothca,例如必须在月份中添加一个(因为java从0开始计算几个月).

GregorianCalendar cal = new GregorianCalendar();
cal.setTime(yourDate);
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH), 0);
XMLGregorianCalendar xmlTime = DatatypeFactory.newInstance().newXMLGregorianCalendarTime(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), 0);
Run Code Online (Sandbox Code Playgroud)


小智 10

我希望我的编码在这里是正确的; D为了使它更快,只需使用GregorianCalendar的丑陋的getInstance()调用而不是构造函数调用:

import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

public class DateTest {

   public static void main(final String[] args) throws Exception {
      // do not forget the type cast :/
      GregorianCalendar gcal = (GregorianCalendar) GregorianCalendar.getInstance();
      XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar(gcal);
      System.out.println(xgcal);
   }

}
Run Code Online (Sandbox Code Playgroud)

  • -1使用.getInstance().`GregorianCalendar.getInstance()`相当于`Calendar.getInstance()`.`Calendar.getInstance()`无法使它更快,因为它使用相同的`new GregorianCalendar()`,但在它之前还检查默认语言环境并且可以创建日语或者Buddish日历,所以对于一些幸运的用户来说它将是`ClassCastException`! (14认同)

Kar*_*rlP 5

假设您要对xml进行解码或编码,并使用JAXB,则可以完全替换dateTime绑定,并对模式中的每个日期使用XMLXMLregorianCalendar之外的其他方式。

这样,您就可以JAXB做重复的工作,同时可以花时间编写可带来价值的出色代码。

jodatime的示例DateTime:(使用java.util.Date进行此操作也可以-但有一定的限制。我更喜欢jodatime,它是从我的代码中复制的,所以我知道它可以工作...)

<jxb:globalBindings>
    <jxb:javaType name="org.joda.time.LocalDateTime" xmlType="xs:dateTime"
        parseMethod="test.util.JaxbConverter.parseDateTime"
        printMethod="se.seb.bis.test.util.JaxbConverter.printDateTime" />
    <jxb:javaType name="org.joda.time.LocalDate" xmlType="xs:date"
        parseMethod="test.util.JaxbConverter.parseDate"
        printMethod="test.util.JaxbConverter.printDate" />
    <jxb:javaType name="org.joda.time.LocalTime" xmlType="xs:time"
        parseMethod="test.util.JaxbConverter.parseTime"
        printMethod="test.util.JaxbConverter.printTime" />
    <jxb:serializable uid="2" />
</jxb:globalBindings>
Run Code Online (Sandbox Code Playgroud)

和转换器:

public class JaxbConverter {
static final DateTimeFormatter dtf = ISODateTimeFormat.dateTimeNoMillis();
static final DateTimeFormatter df = ISODateTimeFormat.date();
static final DateTimeFormatter tf = ISODateTimeFormat.time();

public static LocalDateTime parseDateTime(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        LocalDateTime r = dtf.parseLocalDateTime(s);
        return r;
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printDateTime(LocalDateTime d) {
    try {
        if (d == null)
            return null;
        return dtf.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static LocalDate parseDate(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        return df.parseLocalDate(s);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printDate(LocalDate d) {
    try {
        if (d == null)
            return null;
        return df.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printTime(LocalTime d) {
    try {
        if (d == null)
            return null;
        return tf.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static LocalTime parseTime(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        return df.parseLocalTime(s);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}
Run Code Online (Sandbox Code Playgroud)

请参阅此处: 如何用日期替换XmlGregorianCalendar?

如果您很乐意仅基于时区+时间戳映射到某个时刻,而原始时区并不真正相关,那么java.util.Date也可以。