【问题标题】:java format timestamps with "Z" instead of "+"java格式时间戳用“Z”而不是“+”
【发布时间】:2021-07-22 20:54:39
【问题描述】:

使用 java 我尝试使用 SimpleDateFormat 将当前日期格式化为时区

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

这给了我结果:

   2021-04-28T13:45:52:308+0300

我想用“Z”而不是“+”来获取时区格式

想要的结果:"2021-04-28T13:45:52:308Z03:00"

我将日期输出写入文件日志中,该文件将由用 Go 语言编写的 telegraf 插件解析,该插件期望带有以下格式的时区日期:json_time_format = "2006-01-02T15:04:05Z07:00"

有没有一种模式允许这样做?

【问题讨论】:

  • 如果您至少使用 Java 8,请考虑使用 date-time API。
  • @Abra 即使你不是,它也被反向移植了。
  • 这是旧代码
  • 我建议你不要使用SimpleDateFormatDate。这些类设计不佳且早已过时,尤其是前者,尤其是出了名的麻烦。而是使用来自java.time, the modern Java date and time APILocalDateTimeDateTimeFormatter。如果您仍然需要重写遗留代码,请使用 java.time 重写它。

标签: java java-8 jodatime


【解决方案1】:

你误会了。 2006-01-02T15:04:05Z07:00 并不意味着你应该有一个 Z 而不是一个加号(那么你会用什么来代替减号呢?)这种指定日期和时间格式的方式近似于 Mon 的固定示例日期和时间Jan 2 15:04:05 MST 2006 将被格式化,但这只是一个近似值。具体而言,当涉及到与 UTC 的偏移时,格式需要Z(当偏移为零时)和+hh:mm-hh:mm(当偏移为非零时)。符合 ISO 8601 和 RFC-3339。您会立即看到,仅给出示例日期和时间的正确格式 2006-01-02T15:04:05-07:00,并不会告诉读者偏移量 0 应该作为 Z 给出。因此,此特定要求在格式中指定为Z07:00。根据格式化时间或日期[完整指南](底部的链接),您的特定格式 2006-01-02T15:04:05-0700 表示 ISO 8601 或 RFC-3339。

所以您需要做的就是使用DateTimeFormat.ISO_OFFSET_DATE_TIMEOffsetDateTime.toString()

下面是几个例子。

    String result = OffsetDateTime.now().toString();
    System.out.println(result);

刚刚在我的时区在 Java 8 上运行时的输出:

2021-04-29T17:00:55.716+02:00

如果不允许秒的分数——好吧,根据 ISO 8601,它是可选的,所以应该是,但如果不是:

    String result = OffsetDateTime.now().truncatedTo(ChronoUnit.SECONDS)
            .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);

2021-04-29T17:00:55+02:00

如果您从旧代码中获得了老式的 Date 对象,请在格式化之前对其进行转换:

    Date oldfashionedDate = new Date();
    String result = oldfashionedDate.toInstant()
            .atZone(ZoneId.systemDefault())
            .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);

2021-04-29T17:00:55.739+02:00

链接

【讨论】:

    【解决方案2】:

    Z 代表“祖鲁时间”或零小时偏移,即 UTC +0:00

    如果您不在那个时区,使用它是不正确的。如果用Z 替换它,你怎么知道你是在经络之前还是之后?给定Z03:00,您会将其解析为+03:00 还是-03:00

    【讨论】:

    • 我已经在文件日志中写入了由 telegraf go 插件解析的日期输出,该文件期望带有以下格式的时区日期:json_time_format = "2006-01-02T15:04:05Z07:00"
    【解决方案3】:

    由于 Z 表示 Zulu 时间偏移量,因此您不能将其用作格式字符串的一部分,但您当然可以将 Z 添加为硬编码字符

    ZonedDateTime now = ZonedDateTime.now();
      
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'Z");
    System.out.println(formatter.format(now));
    

    2021-04-29T15:34:17.661Z+0200

    然后,如果您不想要“+”,则可以在之后将其删除,但不清楚如何使用“-”,因此我将其排除在答案之外。

    【讨论】:

      【解决方案4】:

      在语义上,如上所述,它是完全错误的。但是您可以通过一些自定义解析逻辑来实现这一点。 我会假设两件事:

      1. 日期将不包含具有负差异的时区
      2. 日期格式不会改变

      在任何其他情况下,这是不安全的! 但是给你:

      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss:SSSZ");
      String originalDateString = sdf.format(new Date());
      String[] parts = originalDateString.split("\\+");
      StringBuilder sb = new StringBuilder(parts[1]);
      sb.insert(2, ':');
      parts[1] = sb.toString();
      String result = String.join("Z",parts);
      System.out.println(result);
      

      这将由此创建: 2021-04-29T14:12:21:376+0000

      这个: 2021-04-29T14:12:21:376Z00:00

      【讨论】:

      • 请不要教年轻人使用早已过时且臭名昭著的SimpleDateFormat类。至少不是第一选择。而且不是没有任何保留。我们在java.time, the modern Java date and time API, 和它的DateTimeFormatter 中做得更好。
      • 我知道,我同意你的看法。原因是我将其包含在答案中是:1. 发帖人在他提供的示例中使用了它 2. 发帖人提到了它的遗留代码 - 因此可能无法更改。
      • 问题用 java-8 标记,所以 java.time api 应该可用
      猜你喜欢
      • 1970-01-01
      • 2013-08-08
      • 2016-04-26
      • 2020-04-28
      • 2016-04-13
      • 1970-01-01
      • 1970-01-01
      • 2018-11-27
      相关资源
      最近更新 更多