【问题标题】:SimpleDateFormat with TimeZone带时区的 SimpleDateFormat
【发布时间】:2016-06-10 11:45:38
【问题描述】:

我正在尝试从 java.util.Date 格式化日期。我需要这种格式:

2016-06-10T13:38:13.687+02:00

如何正确地将其从标准日期格式转换

May 04 09:51:52 CDT 2009 ?

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss z", Locale.getDefault());
sdf.format(new Date());

不幸的是,这段代码返回的值没有+02:00

【问题讨论】:

  • 只是为了直接设置用法:+02:00 不是时区,它是 UTC 偏移量。非洲/开罗是一个时区,复活节欧洲时间可能作为一个时区过去。时区包含该区域内人们使用的 UTC 偏移量的历史和已知未来变化。
  • 顺便考虑扔掉长期过时且臭名昭著的麻烦SimpleDateFormat和朋友,并将ThreeTenABP添加到您的Android项目中,以便使用java.time,现代Java日期和时间API .使用起来感觉好多了。

标签: java android


【解决方案1】:

根据标准 Java 文档: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

获取日期和时间格式

2001-07-04T12:08:56.235-07:00


您需要使用以下字符串模式:

"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"

所以使用下面的代码,你可以得到你想要的:

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.getDefault());
    simpleDateFormat .format(new Date());

【讨论】:

  • 你确定吗? X 是未知模式。
  • @Algeroth 是的,我 100% 确定,您可以查看我在答案中提到的链接,XXX 是获取时区的有效模式,我建议您尝试一次。跨度>
【解决方案2】:

只需将 z 转为大写

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss Z", Locale.getDefault());
    sdf.format(new Date());

结果:2016-06-10T13:53:22 +0200

【讨论】:

  • @Algeroth 你接受了这个答案,但你发帖说你想要 '2016-06-10T13:38:13.687+02:00' 而不是 '2016-06-10T13:53:22 + 0200'
【解决方案3】:

是时候有人提供现代答案了。

    OffsetDateTime now = OffsetDateTime.now(ZoneId.of("Africa/Cairo"));
    String formatted = now.toString();
    System.out.println(formatted);

这是刚刚打印出来的

2018-02-28T16:42:59.628526+02:00

编辑:我要求在秒上输入 3 位小数,而不是 6。 要对格式进行更多控制,请使用显式格式化程序:

    DateTimeFormatter formatterWithThreeDecimals
            = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXXXX");
    String formatted = now.format(formatterWithThreeDecimals);
    System.out.println(formatted);

此打印(在我编辑时):

2018-04-30T15:47:41.749+02:00

如果不是非洲/开罗,请替换您想要的时区。为 JVM 的时区设置指定 ZoneId.systemDefault()。您的程序的其他部分或在同一 JVM 中运行的其他程序可以随时更改该设置。

使用现代 Java 日期和时间 API java.time,如果您只想要一个符合 ISO 8601 的输出并且不关心有多少小数(或者如果它们为 0,则是否打印秒),我们不根本不需要显式格式化程序。您所需的字符串采用 ISO 8601 格式,这是现代类的 toString 方法生成的标准格式。根据您的需要,toString 的结果可能会被接受。

您使用的类DateSimpleDateFormat 早已过时,而后者尤其是出了名的麻烦。我建议您避免使用它们并改用现代 API。使用起来感觉好多了。

如果您现在不想更改旧 API 中的 java.util.Date,请将其转换为现代的 Instant,然后从那里进行进一步的转换。在 Java 8 及更高版本中,情况如下:

    ZonedDateTime dateTime = oldfashionedDateFromLegacyApi.toInstant()
            .atZone(ZoneId.of("Africa/Cairo"));
    String formatted = dateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);

如果您使用的是 ThreeTen Backport 和/或 ThreeTenABP,则转换发生的方式略有不同,如下所示:

    ZonedDateTime dateTime = DateTimeUtils.toInstant(oldfashionedDateFromLegacyApi)
            .atZone(ZoneId.of("Africa/Cairo"));

同样,如果您想严格控制输出格式,请不要使用 DateTimeFormatter.ISO_OFFSET_DATE_TIME,因为它会输出 1 到 9 位小数之间的任何内容,并且如果它们为 0,也可能会省略秒数。而是使用我的 formatterWithThreeDecimals从上面。

问题:我可以在 Android 上使用 java.time 吗?

是的,java.time 在 Android 上运行良好。它只需要至少 Java 6

  • 在 Java 8 及更高版本以及更新的 Android 设备上,内置了现代 API。
  • 在 Java 6 和 7 中,获取 ThreeTen Backport,即新类的后向端口(对于 JSR 310,ThreeTen;请参阅底部的链接)。
  • 在(较旧的)Android 上使用 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。并确保从 org.threeten.bp 导入日期和时间类以及子包。

链接

【讨论】:

  • 在大多数情况下,我强烈建议不要使用toString 来格式化任何内容,尤其是日期和时间。甚至 JavaDoc 都说它将使用 5 种不同时间格式中的一种,以最简洁的字符串表示形式为准。如果要格式化日期或时间,请使用格式化程序。也可以使用新的 API。
  • 感谢您的编辑,取消了我的反对意见,因为现在您的回答很全面,回答了原始问题。
【解决方案4】:

您在末尾添加 (ZZZZZ) 以获得如下格式

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss ZZZZZ", Locale.getDefault());

【讨论】:

  • 使用示例输出,这个答案会更好。
【解决方案5】:

您只是犯了一个简单的错误,您需要使用大写字母z。你需要的是:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss z Z", Locale.getDefault());

除了你的小写z。小写的 z 只提供时区,而大写的则提供基于 RFC 822 的时区。

编辑

如果你不想要一个通常的时区,只需要 +2:00 没有例如 PST,你只需要一个大写 Z:

   SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss Z", Locale.getDefault());

来自(非常简单易懂的)Docs

z/zz/zzz:PST zzzz:Pacific Standard Time
Z/ZZ/ZZZ:-0800 ZZZZ:GMT-08:00 ZZZZZ:-08:00

【讨论】:

  • 完美,避免了不规范的XXX
【解决方案6】:

按格式添加SSSZ

"yyyy-MM-dd'T'HH:mm:ss z" => "yyyy-MM-dd'T'HH:mm:ss.SSSZ"

只要改变这一行

旧: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss z", Locale.getDefault()); sdf.format(new Date());

新功能: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.getDefault());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-23
    • 2018-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 2012-05-24
    相关资源
    最近更新 更多