代码之家  ›  专栏  ›  技术社区  ›  Andez

将Java日期转换为XML日期格式(反之亦然)

  •  20
  • Andez  · 技术社区  · 14 年前

    干杯,

    安德仕

    9 回复  |  直到 14 年前
        1
  •  23
  •   Paweł Dyda    9 年前

    原始答案

    我猜这里的“XML日期格式”是指类似“2010-11-04T19:14Z”的内容。实际上是 ISO 8601 格式。

    如其他人所建议的,您可以使用SimpleDateFormat、FastDateFormat或使用 Joda Time 我相信它是专门为 this purpose .

    作为 在评论中指出,这个答案可以通过例子加以改进。

    java.time 包裹应该很有趣。如果您有幸使用Java 8,您应该使用其中一个。然而,这些事情令人惊讶地难以纠正。

    不是的本地日期(时间)

    举个例子:

    LocalDateTime dateTime = LocalDateTime.parse("2016-03-23T18:21");
    System.out.println(dateTime); // 2016-03-23T18:21
    

    一开始我们使用的可能是本地的(用户日期和时间)。但是,如果你敢问,你会得到不同的结果:

    System.out.println(dateTime.getChronology()); // ISO
    

    实际上,这是ISO时间。我认为应该是“UTC”,但这并没有本地时区的概念。所以我们应该认为它是普遍的。
    请注意,我们正在解析的字符串末尾没有“Z”。如果您在日期和时间之外添加任何内容,您将收到 java.time.format.DateTimeParseException . 所以,如果我们想解析ISO8601字符串,这个类似乎没有用处。

    指定救援时间

    java.time.ZonedDateTime .

    ZonedDateTime zonedDateTime = ZonedDateTime.parse("2016-03-23T18:21+01:00");
    System.out.println(zonedDateTime); // 2016-03-23T18:21+01:00
    ZonedDateTime zonedDateTimeZulu = ZonedDateTime.parse("2016-03-23T18:21Z");
    System.out.println(zonedDateTimeZulu); // 2016-03-23T18:21Z
    

    这里唯一的问题是,您实际上需要使用时区指定。尝试分析原始日期时间(即“2016-03-23T18:21”)将导致 RuntimeException . 视情况而定 LocalDateTime ZonedDateTime .

    System.out.println(zonedDateTimeZulu.toLocalDateTime()); // 2016-03-23T18:21
    // Zone conversion
    ZonedDateTime cetDateTime = zonedDateTimeZulu.toLocalDateTime()
       .atZone(ZoneId.of("CET"));
    System.out.println(cetDateTime); // 2016-03-23T18:21+01:00[CET]
    

    我建议现在使用这些课程。然而,如果你的工作描述包括考古学(这意味着你没有足够的运气与超过2岁的Java 8一起工作…),你可能需要使用其他东西。

    SimpleDateFormat的乐趣

    我不是https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html的忠实粉丝,但有时候你别无选择。问题是,它不是线程安全的,它将抛出一个检查 Exception ParseException )如果它不喜欢你的脸。因此,代码片段相当难看:

    private Object lock = new Object();
    // ...
    try {
        synchronized (lock) {
            // Either "2016-03-23T18:21+01:00" or "2016-03-23T18:21Z"
            // will be correctly parsed (mind the different meaning though)
            Date date = dateFormat.parse("2016-03-23T18:21Z");
            System.out.println(date); // Wed Mar 23 19:21:00 CET 2016
        }
    } catch (ParseException e) {
        LOG.error("Date time parsing exception", e);
    }
    

    快速日期格式

    FastDateFormat Apache Commons Lang 而且它使用得很彻底,我想这是可以接受的。实际上它的用法与 SimpleDateFormat

    FastDateFormat fastDateFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mmX");
    try {
        Date fastDate = fastDateFormat.parse("2016-03-23T18:21+01:00");
        System.out.println(fastDate);
    } catch (ParseException e) {
        LOG.error("Date time parsing exception", e);
    }
    

    乔达蒂姆

    随着乔达时代的到来,你可能会认为以下是可行的:

    DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser();        
    LocalDateTime dateTime = LocalDateTime.parse("2016-03-23T20:48+01:00", parser);
    System.out.println(dateTime); // 2016-03-23T20:48:00.000
    

    不幸的是,不管你在最后一个位置(Z,+03:00,…)放什么,结果都是一样的。很明显,它不起作用。

    DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser();
    DateTime dateTime = parser.parseDateTime("2016-03-23T21:12:23+04:00");
    System.out.println(dateTime); // 2016-03-23T18:12:23.000+01:00
    

    现在没事了。请注意,与其他答案不同,我使用 dateTimeParser() dateTime() . 我注意到他们之间行为上细微但重要的差异(Joda Time 2.9.2)。但是,我把它留给读者去测试和确认。

        2
  •  20
  •   Kennet    14 年前

    如前所述,使用SimpleDateFormat。

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    String date = sdf.format(new Date());
    System.out.println(date);
    Date d = sdf.parse(date);
    

    我猜你要找的格式/模式是 yyyy-MM-dd'T'HH:mm:ss 也看看 http://www.w3schools.com/schema/schema_dtypes_date.asp

        3
  •  9
  •   Piotr Kochański    10 年前

    使用 Joda Time

    DateTimeFormatter fmt = ISODateTimeFormat.dateTime(); // ISO8601 (XML) Date/time
    DateTime dt = fmt.parseDateTime("2000-01-01T12:00:00+100"); // +1hr time zone
    System.out.println(fmt.print(dt)); // Prints in ISO8601 format
    

    线程安全,不可变,简单。

        4
  •  8
  •   Belz    10 年前

    完美的方法,使用XMLGregorianCalendar:

    GregorianCalendar calendar = new GregorianCalendar();
    calendar.setTime(v);
    DatatypeFactory df = DatatypeFactory.newInstance();
    XMLGregorianCalendar dateTime = df.newXMLGregorianCalendar(calendar);
    return dateTime.toString();
    
        5
  •  7
  •   3urdoch    11 年前

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
    Date date = sdf.parse("2011-12-31T15:05:50+1000");
    
        6
  •  4
  •   stenix Khalil    6 年前

    我建议使用java内置类 javax.xml.bind.DatatypeConverter . 它可以处理大多数xml简单类型之间的转换。约会有点麻烦 Calendar 对象,但另一方面它处理xml中可能出现的区域信息的所有变体 datetime 字段。

        Calendar c = DatatypeConverter.parseDateTime("2015-10-21T13:25");
        Date d = c.getTime();
    

    到xml:

        Date yourDate = new Date()
        Calendar c = Calendar.getInstance();
        c.setTime(yourDate);
        String xmlDateTime = DatatypeConverter.printDateTime(c);
    

    编辑

    DatatypeConverter类在Java 9及更高版本中不再公开,因为它属于javax.xml.bind包。见 this question 卢瓦吉欧 在这种情况下,使用xmlgerigoriancalendar要好得多。

        7
  •  3
  •   Eugene Kuleshov    14 年前
        8
  •  2
  •   arkhos    9 年前

    为了符合ISO8601,时区的格式必须是+HH:MM或-HH:MM

    对于Simpledateformat,您必须使用XXX而不是Z(请参见NovelGuy答案)

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
    
        9
  •  1
  •   javamonkey79    14 年前