在Java中格式化日期时遇到问题

在Java中格式化日期时遇到问题,java,date,datetime,Java,Date,Datetime,我尝试了几种使用Java Joda Time、使用locale和commons lang的日期时间的方法,但无法格式化此日期 输入 Mon-Dec 28 15:18:16 UTC 2020 输出 所需输出格式yyyy-MM-dd HH:MM:ss.SSS 当我使用像EEE MMM dd HH:mm:ss Z YYYY这样的格式模式时,日期有几天不在我的范围内,时区似乎完全错误 格式化程序: private static final DateTimeFormatter DATE_TIME_FO

我尝试了几种使用Java Joda Time、使用locale和commons lang的日期时间的方法,但无法格式化此日期

输入
Mon-Dec 28 15:18:16 UTC 2020

输出 所需输出格式
yyyy-MM-dd HH:MM:ss.SSS

当我使用像
EEE MMM dd HH:mm:ss Z YYYY这样的格式模式时,日期有几天不在我的范围内,时区似乎完全错误

格式化程序:

  private static final DateTimeFormatter DATE_TIME_FORMATTER =
    DateTimeFormatter
      .ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
      .withLocale(Locale.US)
      .withZone(ZoneId.systemDefault());
对我来说很好

String s=“周一至十二月28日15:18:16 UTC 2020”;
DateTimeFormatter formatter=DateTimeFormatter.of模式(“EEE MMM dd HH:mm:ss VV yyyy”,
语言环境(英语);
ZonedDateTime zdt=ZonedDateTime.parse(s,格式化程序);
格式化程序=模式的DateTimeFormatter.(“yyyy-MM-dd-HH:MM:ss.SSS”,Locale.ENGLISH);
System.out.println(zdt.format(格式化程序));
输出为

2020-12-28 15:18:16.000

我是否遗漏了什么?

在调试解析问题时,如果可能,请反转操作并生成您应该解析的文本,以验证解析规则,即日期格式字符串。这适用于日期解析、JAXB解析和任何其他双向(反)序列化操作。它使查找转换规则问题变得更加容易

那么,让我们用显示的日期值检查问题中的格式字符串:

ZoneDateTime dateTime=ZoneDateTime.of(2020,12,28,15,18,16,0,ZoneOffset.UTC);
DateTimeFormatter fmt=模式的DateTimeFormatter.(“EEE-MMM-dd-HH:mm:ss-Z-YYYY”,Locale.US);
System.out.println(dateTime.format(fmt));
输出

Mon Dec 28 15:18:16+0000 2021
哎呀!这不符合预期的输出,即我们希望解析的输入:

Mon-Dec 28 15:18:16 UTC 2020
那么出了什么问题

  • 年份是错误的,因为它应该是
    uuuu
    (年份),而不是
    YYYY
    (基于周的年份)

  • 时区错误,因为
    Z
    不支持文本表示。改用
    VV
    z

  • DateTimeFormatter fmt=DateTimeFormatter.of模式(“EEE-MMM-dd-HH:mm:ss-z-uuuu”,Locale.US);
    ZonedDateTime日期时间=ZonedDateTime.parse(“周一至十二月28日15:18:16 UTC 2020”,fmt);
    System.out.println(日期时间);
    System.out.println(dateTime.format(模式的DateTimeFormatter.of(“uuu-MM-dd-HH:MM:ss.SSS”));
    
    输出

    2020-12-28T15:18:16Z[UTC]
    2020-12-28 15:18:16.000
    

    如您所见,它现在已正确解析。

    您是否尝试过使用SimpleDataFormat

    String dateString = "Mon Dec 28 15:18:16 UTC 2020";
    
    SimpleDateFormat input = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
    SimpleDateFormat output = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
    
    System.out.println(output.format(input.parse(dateString)));
    
    时区:

    String dateString = "Mon Dec 28 15:18:16 UTC 2020";
    
    SimpleDateFormat input = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
    SimpleDateFormat output = new SimpleDateFormat("yyyy-MM-dd z HH:mm:ss.SSS");
    input.setTimeZone(TimeZone.getTimeZone("UTC"));
    output.setTimeZone(TimeZone.getTimeZone("UTC"));
    
    System.out.println(output.format(input.parse(dateString)));
    

    问题中的代码没有什么意义:

    • 它正在使用
      toString()
      Date
      值格式化为文本,只是尝试将其解析回来

    • 它使用
      Optional
      进行简单的空处理(不鼓励这样做),但随后无条件地调用
      get()
      ,这意味着
      null
      值无论如何都会引发异常

    代码应为:

    record.getCustomerAudit().getCreated().getDate().toInstant()文件
    

    这当然使整个问题变得毫无意义。

    什么是输入,什么是代码,什么是输出?@luk2302用给定的输入更新了desire输出。您可以添加您用于输入的类的类型吗?(String,LocalDate,LocalDateTime)@OneCricketeer又添加了一些代码您需要commons lang吗?java.time类应该可以很好地工作。这也适用于类似2020-12-28T15:18:17.461525Z[Etc/UTC]的情况吗?我对这些UTC类型值感到困惑。@Ryan文本是a的自然格式,所以只需调用该方法,例如
    ZonedDateTime.parse(“2020-12-28T15:18:17.461525Z[Etc/UTC]”
    这是否也适用于类似2020-12-28T15:18:17.461525Z[Etc/UTC]的东西?我对这些UTC类型的值感到困惑。@Ryan你这是什么意思?这个答案中的
    zdt
    2020-12-28815:18:16Z[UTC]
    ,它有点接近,显然它没有微秒。我们想解释一下,如果你能更准确地告诉我们什么让你感到困惑。请不要教年轻人使用早已过时且臭名昭著的
    SimpleDateFormat
    类。至少不是第一个选择。而且不是毫无保留的。今天,我们在及其
    DateTimeFormatter
    中有了更好的功能。OP已经在使用java.time。黑暗者,你在向我们展示一条倒退的道路,我们永远不想再去的地方。智慧的话语?老实说,我不知道。。事实上,我鄙视日期/时间转换,并像躲避瘟疫一样避免它。也许在这一点上,时间已经过去了(这算双关语吗?),而我被留在了过去。但是,SimpleDateFormat一直对我很有用。不过,如果你愿意,请随意编辑我的答案,并为后代添加警告。(在我的辩护中,我想补充一点,我的答案并不是第一个。)Well meter@OleV.V.甚至对同一个问题有两个好的答案。@OleV.V。是的,它们也是完全不同的答案,这就是为什么我创建了两个不同的答案。
    String dateString = "Mon Dec 28 15:18:16 UTC 2020";
    
    SimpleDateFormat input = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
    SimpleDateFormat output = new SimpleDateFormat("yyyy-MM-dd z HH:mm:ss.SSS");
    input.setTimeZone(TimeZone.getTimeZone("UTC"));
    output.setTimeZone(TimeZone.getTimeZone("UTC"));
    
    System.out.println(output.format(input.parse(dateString)));