【问题标题】:How to achive this date format in calendar如何在日历中实现这种日期格式
【发布时间】:2020-05-29 16:26:28
【问题描述】:

我必须使用这种日期格式“YYYY-MM-DDTHH:MI:SS±TZ”创建 XMLGregorianCalendar 对象,例如“2015-07-01T17:42:49+04”

我不知道该怎么做。我使用了多种方法来转换日期,但这种模式似乎不起作用。

经过一些实验,我发现“YYYY-MM-dd'T'HH:mm:ssX”会给我想要的输出。但它是一个字符串,我无法使用 XMLGregorianCalendar 实现相同的格式。

它给了我“2015-07-01T17:42:4234+05:00”,正如你所见,我不需要其他符号。

【问题讨论】:

  • 尝试并记住,Date 对象(包括Calendar)仅包含自锚点以来经过的时间量(即自 Unix 纪元以来的毫秒数),除了“一般人类可读的表示”之外,它们不带有格式的概念,这实际上并不意味着调试。相反,您使用某种DateFormatter。您需要将 Calendar 转换为格式化程序期望的适当对象类型,但这不应该那么难
  • 您的意思是最后一段引用的文本包含+04:00 而不是+05:00 以匹配第一段?
  • 我希望(并且怀疑)你弄错了。 (1) 正如@BasilBourque 在他的回答中所说,您不需要XMLGregorianCalendar。 (2) 以小时为单位的格式,+04,在 XML 中无效。因此XMLGregorianCalendar 无法生成它。 可以在值的末尾添加一个可选的时区表达式。字母Z 用于表示协调世界时(UTC)。所有其他时区均由它们与协调世界时的差异表示,格式为 +hh:mm-hh:mm. xsd:dateTime
  • DatatypeFactory.newInstance().newXMLGregorianCalendar("2015-07-01T17:42:49+04") 是一种简单的方法,可以看出您在问不可能的问题。这会引发java.lang.IllegalArgumentException: 2015-07-01T17:42:49+04newXMLGregorianCalendar(String) 接受 XMLGregorianCalendar 能够打印回来的所有格式。

标签: java date calendar date-format xmlgregoriancalendar


【解决方案1】:

日期时间对象没有格式

具有此日期格式的 XMLGregorianCalendar 对象

XMLGregorianCalendar 等日期时间对象没有“格式”。它们以某种方式在内部表示日期时间值,但不太可能以文本形式出现。

您可以通过解析文本来实例化日期时间对象。您的日期时间对象可以生成表示其内部价值的文本。但是文本和日期时间对象是不同的,并且彼此分开。

java.time

XMLGregorianCalendar 类现已过时。被 JSR 310 中定义的现代 java.time 类所取代。

将您的输入字符串解析为 OffsetDateTime,因为其中包含与 UTC 的偏移量,但不包含时区。

OffsetDateTime odt = OffsetDateTime.parse( "2015-07-01T17:42:49+04" );

以标准ISO 8601 格式生成文本。

String output = odt.toString() ;  // Generates text in ISO 8601 format.

2015-07-01T17:42:49+04:00

部分偏移

最后的部分是与 UTC 的偏移量,即本初子午线之前或之后的小时-分钟-秒数。在 ISO 8601 中,加号是一个正数,表示 领先 UTC。减号是一个负数,表示 UTC。

抑制部分偏移

有些人可能会在零时放弃秒,或者在零时放弃分钟。但是抑制这些数字并不会改变含义。这三个字符串都代表同一个时刻:

  • 2015-07-01T17:42:49+04
  • 2015-07-01T17:42:49+04:00
  • 2015-07-01T17:42:49+04:00:00

你说:

“2015-07-01T17:42:4234+05:00”,如您所见,我不需要其他符号。

[我猜你的意思是"2015-07-01T17:42:49+04:00",但打错字了。]

你真的不应该关心这个。实际上,我建议您始终同时包含小时和分钟,因为我已经看到多个库/协议期望同时包含小时和分钟,如果省略则会中断。虽然在 ISO 8601 中分钟和秒的值为零时确实是可选的,但我建议您始终在为零时包含分钟。

DateTimeFormatter

如果您坚持不这样做,您将需要使用DateTimeFormatter 类,可能还有DateTimeFormatterBuilder,来抑制零时的分钟数。也许是这样:

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ssx" );
String output = odt.format( f );

2015-07-01T17:42:49+04

该格式模式中的x 代码抑制了分钟和秒,如果它们的值为零。

如果您自己进行格式化,请确保在非零时不要截断,否则您的结果将是错误的(不同的时刻)。举个例子,代表在印度看到的这一时刻,当前使用的偏移量是五个半小时(包括 30 分钟而不是零的偏移量)。

ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );
OffsetDateTime odtKolkata = zdt.toOffsetDateTime();

转储到控制台。

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

2015-07-01T19:12:49+05:30

XMLGregorianCalendar

如果您绝对必须使用旧的遗留类 XMLGregorianCalendar,您可以从上面代码中看到的 OffsetDateTime 对象的 ISO 8601 输出创建一个。请在另一个问题上查看 this Answer

XMLGregorianCalendar xgc = null;
try
{
    xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar( odt.toString() );
}
catch ( DatatypeConfigurationException e )
{
    e.printStackTrace();
}
System.out.println( "xgc.toString(): " + xgc );

xgc.toString(): 2015-07-01T17:42:49+04:00


关于java.time

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

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

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

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。

从哪里获得 java.time 类?

【讨论】:

    猜你喜欢
    • 2017-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-07
    相关资源
    最近更新 更多