【问题标题】:parsing date from "06/25/2021 10:26:33.0" format to "2021-06-25T10:26:33.000-04:00" using java.time使用 java.time 将日期从“06/25/2021 10:26:33.0”格式解析为“2021-06-25T10:26:33.000-04:00”
【发布时间】:2021-08-24 16:47:43
【问题描述】:

为了使用 junit 进行比较,我必须转换日期。我从数据库中得到一个日期,即“06/25/2021 10:26:33.0”,我必须将其转换为“2021-06-25T10:26:33.000-04: 00" 在我在断言中使用它之前。

我试图不在 java 中使用 SimpleDate,而是使用内置的 java.time。但是,我认为我并没有真正理解其中的所有内容。这是我一直在玩的代码 sn-p。我已经尝试了很多方法,但解析发生时总是出错。

 public String test() throws ParseException {
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");
    LocalDateTime ldt = LocalDateTime.parse("06/25/2021 10:26:33.0", dtf);
    //After the above line I have a date like: 2021-06-25T10:26:33.0
    ZoneId zone = ZoneId.of("UTC-04:00");
    ZonedDateTime zdt = ldt.atZone(zone);
    Instant instant = zdt.toInstant();
    return instant.toString();
}

在我看来,我认为我必须首先将日期转换为“可接受”的格式,因为我觉得这种格式的字符串 - “yyyy-MM-dd HH:mm:ss.S”不是那种java.time 可以处理。它给了我一个错误,例如“无法在索引 19 处解析文本”,然后可能在第二遍中将其转换为“2021-06-25T10:26:33.000-04:00” ”。

我已经在 SO 上查阅了几篇关于此的文章,但未能找到有助于转换自定义格式的内容。我知道“解析”和“格式”是必须在此处使用的 2 个 API 方法,但不知道如何去做。有人可以将我推向正确的方向吗?

【问题讨论】:

  • 困惑...您使用与输入字符串完全不同的格式
  • 不要从数据库中获取您的日期和时间作为字符串。检索LocalDateTime(如果您无法检索OffsetDateTime)。见the good answer by Arvind Kumar Avinash here

标签: java datetime iso8601 java.time.instant


【解决方案1】:

您可以使用LocalDateTime#atOffset 来满足此要求。

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String input = "06/25/2021 10:26:33.0";
        DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("M/d/u H:m:s.S", Locale.ENGLISH);
        LocalDateTime ldt = LocalDateTime.parse(input, dtfInput);
        OffsetDateTime odt = ldt.atOffset(ZoneOffset.of("-04:00"));
        System.out.println(odt);

        // Formatted output
        DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
        String formatted = dtfOutput.format(odt);
        System.out.println(formatted);
    }
}

输出:

2021-06-25T10:26:33-04:00
2021-06-25T10:26:33.000-04:00

ONLINE DEMO

注意事项:

  1. 如果输入中的秒小数可以是 0 到 9 位数字,请使用模式 M/d/u H:m:s[.[SSSSSSSSS][SSSSSSSS][SSSSSSS][SSSSSS][SSSSS][SSSS][SSS][SS][S]],其中已使用方括号指定可选模式。
  2. OffsetDateTime#toString 如果第二部分和小数部分为零,则省略它们。使用DateTimeFormatter 将它们放入格式化字符串中。

通过 Trail: Date Time 了解有关 modern Date-Time API* 的更多信息。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7 . 如果您正在为一个Android项目工作并且您的Android API级别仍然不符合Java-8,请检查Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

【讨论】:

  • 感谢您的信息。这就像一个魅力。当我尝试时,我无法弄清楚文档中提到的所有方法的含义。也谢谢你的解释
【解决方案2】:

将其转换为“2021-06-25T10:26:33.000-04:00”。

我认为您需要一个自定义格式化程序。也许如下:

    public String test() {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM/dd/uuuu HH:mm:ss.S");
        LocalDateTime ldt = LocalDateTime.parse("06/25/2021 10:26:33.0", dtf);
        ZoneOffset zoff = ZoneOffset.ofHours(-4);
        OffsetDateTime ldt2 = ldt.atOffset(zoff);
        DateTimeFormatter tsf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSxxx");
        return tsf.format(ldt2);
    }

【讨论】:

  • ZonedDateTime 在这里是错误的类型。如果是时区偏移值,您应该使用OffsetDateTime。但是,我想知道您在发布此答案前 20 分钟发布的现有答案中添加了什么价值。
  • 但是,我想知道您在发布此答案前 20 分钟发布的现有答案中添加了什么价值您需要阅读我的前言评论和然后再仔细看看需求
  • OP 可能已经考虑了时区,例如 America/St_Vincent。如果是这样,首先转换为ZonedDateTime 是正确的。然后可以使用DateTimeFormatter.ISO_OFFSET_DATE_TIME 对其进行格式化或进一步转换为OffsetDateTime 对象。还有@ArvindKumarAvinash
  • 对。但我注意到 ISO_OFFSET_DATE_TIME 不适合 OP 所需的格式。也许我错过了一些东西。
  • 你们说得对,“America/St_Vincent”时区更有意义,就我而言,如果我们碰巧实施它;它将是“America/New_York”,但目前我在服务中得到“-04:00”,我只是想匹配数据,以便我知道该服务正在从数据库中带来正确的值。为此,我正在编写此函数以将数据库中的值转换为正确的格式,以便格式与服务匹配。您的解决方案虽然也解决了我的问题。谢谢你的赞赏
猜你喜欢
  • 2021-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多