【问题标题】:Formatting ISO 8601 date with a colon seperator使用冒号分隔符格式化 ISO 8601 日期
【发布时间】:2015-04-15 08:15:58
【问题描述】:

我正在尝试将日期以毫秒为单位转换为以下 ISO 8601 格式:

但我使用 SimpleDateFormat 得到以下信息:

    /**
     * It converts the time from long to the ISO format
     * 
     * @param timestampMillis
     * @return isoDate
     */
    public String convertTimeMillisToISO8601(String timestampMillis)
    {
        long timeInLong= Long.parseLong(timestampMillis);
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
        df.setTimeZone(TimeZone.getTimeZone("UTC"));
        String isoDate = df.format(new java.util.Date(timeInLong));
        return isoDate;
    }

输出:

"ts":"2015-06-18T09:56:21+0000"

我知道我可以使用子字符串来附加额外的冒号,但是有没有更好的方法呢?

【问题讨论】:

标签: java date iso8601


【解决方案1】:

对于 Java 7 及更高版本,您可以在日期格式字符串中使用 XXX(ISO 8601 时区)。根据the documentationX的结果可以是:

X    => -08
XX   => -0800
XXX  => -08:00

但对于所有这些,它还不如返回Z

对于 Java 6 及更早版本,没有 X (J6 doc),并且由于 X 的结果可能会或可能不会做你想要的,我强烈建议你自己插入那个冒号。

【讨论】:

  • X 将为 UTC 生成 Z,而不是 +00:00
  • 是的,在我喜欢的文档中是这样说的。它可能会生成所需的结果,或Z。这就是为什么我真的会自己插入冒号。
【解决方案2】:

你可以随时use a StringBuilder:

new StringBuilder(
      new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
      .format(date))
    .insert(22,':')
    .toString();

【讨论】:

【解决方案3】:

对于 Java 8,如果您使用标准的 ISO_DATE_* 格式模式之一,则当偏移量为 +00:00 时,输出 格式的字符串将被截断(UTC 通常只附加 Z) .

OffsetDateTime utcWithFractionOfSecond = ZonedDateTime.parse("2018-01-10T12:00:00.000000+00:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME);

utcWithFractionOfSecond.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);     // 2018-01-10T12:00:00Z ... not what you want!

我找到的唯一解决方案是使用outputPattern(如下所示),它使用小写 `xxx' 来确保时区偏移中包含冒号。

为了完整起见,我已经包含了一个每秒派系的示例(您可以在您的情况下删除SSSSSS

DateTimeFormatter inputPattern = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
DateTimeFormatter outputPattern = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSxxx");

OffsetDateTime utcWithFractionOfSecond = OffsetDateTime.parse("2018-01-10T12:00:00.000000+00:00", inputPattern);
OffsetDateTime utcNoFractionOfSecond = OffsetDateTime.parse("2018-01-10T12:00:00+00:00", inputPattern);
OffsetDateTime utcWithZ = OffsetDateTime.parse("2018-01-10T12:00:00Z", inputPattern);
OffsetDateTime utcPlus3Hours = OffsetDateTime.parse("2018-01-10T12:00:00.000000+03:00", inputPattern);|

utcWithFractionOfSecond.format(outputPattern );     // 2018-01-10T12:00:00.000000+00:00
utcNoFractionOfSecond.format(outputPattern);        // 2018-01-10T12:00:00.000000+00:00
utcWithZ.format(outputPattern);                     // 2018-01-10T12:00:00.000000+00:00
utcPlus3Hours.format(outputPattern);                // 2018-01-10T12:00:00.000000+03:00

在这些示例中,我仅使用 ISO_OFFSET_DATE_TIME 来为测试用例创建输入值。在所有情况下,输出模式yyyy-MM-dd'T'HH:mm:ss.SSSSSSxxx 控制如何在生成的格式化字符串的时区部分中包含冒号。

请注意,如果您的输入数据包含像 [Europe/London] 这样的区域 ID,那么您将使用 ZonedDateTime 而不是 OffsetDateTime 创建输入数据

【讨论】:

  • 输入字符串只表示一个偏移量,而不是一个时区。所以OffsetDateTime 类在这里是合适的,而不是ZonedDateTime
  • 同意,我已经更新了答案,以便在这个特定示例中更具体地使用 OffsetDateTime
【解决方案4】:

你会使用 Java 8 吗?

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("YYYY-MM-dd'T'HH:mm:ssXXX");
System.out.println(formatter.format(ZonedDateTime.now()));

2015-04-15T17:24:19+09:00

【讨论】:

  • 也适用于 UTC?这就是SimpleDateFormat 的 XXX 出错的地方。
  • 对于 UTC,它将打印 Z
  • @Raniz - 是的,所以我说的是 UTC。
  • 无需指定格式模式。默认情况下,输入字符串的标准 ISO 8601 格式在 java.time 类中处理。
  • OffsetDateTime 适合此问题,因为输入涉及+00:00。问题中没有指明时区,因此ZonedDateTime 不是最合适的。
【解决方案5】:

tl;博士

OffsetDateTime.parse( "2014-06-18T09:56:21+00:00" )

2014-06-18T09:56:21Z

详情

其他一些答案很接近,正确地使用了取代可怕的旧遗留类(DateCalendarSimpleDateFormat)的现代 java.time 类。但他们要么工作太努力,要么选错了课程。

ISO 8601

您的格式是标准的ISO 8601 格式。 java.time 类在解析/生成表示其日期时间值的文本时默认使用这些标准格式。因此,您根本不需要指定任何格式模式。默认工作。

OffsetDateTime

您的输入表明offset-from-UTC 为零小时零分钟。所以我们应该使用OffsetDateTime 类。

String input = "2014-06-18T09:56:21+00:00";
OffsetDateTime odt = OffsetDateTime.parse( input );

祖鲁时间

我们只需调用toString 就可以生成标准ISO 8601 格式的字符串。末尾的Z 表示UTC,发音为“Zulu”。

odt.toString(): 2014-06-18T09:56:21Z

ZonedDateTime

如果您的输入指示时区,而不仅仅是偏移量,我们将使用ZonedDateTime 类。偏移量只是小时、分钟和秒数——仅此而已。时区更多。时区是特定地区的人们使用的偏移量的过去、现在和未来变化的历史。


关于java.time

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

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

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

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

从哪里获得 java.time 类?

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多