如何用LocalDateTime解析/格式化日期?(Java 8)

450 人关注

Java 8增加了一个新的 java.time 用于处理日期和时间的API ( JSR 310 ).

我有日期和时间的字符串(例如: "2014-04-08 12:30" )。我怎样才能获得一个 LocalDateTime 从给定的字符串中选择一个实例?

在我完成对 LocalDateTime 对象的处理后。然后,我如何将 LocalDateTime 实例转换回与上述格式相同的字符串?

3 个评论
顺便说一下,大多数人在大多数时候都会希望有一个 ZonedDateTime 而不是一个 LocalDateTime .这个名字是反直觉的; Local 是指 任何 locality in general而不是一个specific time zone. As such, a LocalDateTime object is not tied to the time line. To have meaning, to get a specify moment on the time line, you must apply a time zone.
关于 LocalDateTime ZonedDateTime OffsetDateTime Instant LocalDate LocalTime 的解释,请看我的回答,如何保持冷静,为什么这么复杂,如何在第一枪就做对。
如果不是因为它长得不实用, LocalDateTime 可能会被命名为 ZonelessOffsetlessDateTime
java
datetime
java-8
timestamp
java-time
micha
micha
发布于 2014-03-18
11 个回答
micha
micha
发布于 2023-01-10
已采纳
0 人赞同

解析日期和时间

要从一个字符串创建一个 LocalDateTime 对象,你可以使用静态的 LocalDateTime.parse() 方法。它接受一个字符串和一个 DateTimeFormatter 作为参数。替换代码2】用于指定日期/时间模式。

String str = "1986-04-08 12:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTime = LocalDateTime.parse(str, formatter);

格式化日期和时间

要在一个LocalDateTime对象中创建一个格式化的字符串,你可以使用format()方法。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTime = LocalDateTime.of(1986, Month.APRIL, 8, 12, 30);
String formattedDateTime = dateTime.format(formatter); // "1986-04-08 12:30"

注意,在DateTimeFormatter中,有一些常用的日期/时间格式被预定为常量。比如说。使用DateTimeFormatter.ISO_DATE_TIME来格式化上面的LocalDateTime实例,将导致字符串"1986-04-08T12:30:00"

parse()format()方法可用于所有与日期/时间相关的对象(例如:LocalDateZonedDateTime)。

需要注意的是,DateTimeFormatter是不可变的,并且是线程安全的,因此推荐的方法是尽可能将其存储在静态常量中。
@DawoodAbbasi try DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX")
@Loenix 也许这是因为你试图在LocalDateTime类上而不是在实例上调用 format() ?至少,我就是这么做的。我在上面的例子中混淆了 DateTime dateTime
别忘了MM上的大写字母
@AJW 我咬了咬牙,把那些位子从 Date 改写成 LocalDate 和各自的类。
Sufiyan Ghori
Sufiyan Ghori
发布于 2023-01-10
0 人赞同

你也可以在 LocalDate.parse() LocalDateTime.parse() 上使用 String ,而不给它提供模式,如果 String 是在 ISO 8601格式 .

String strDate = "2015-08-04";
LocalDate aLD = LocalDate.parse(strDate);
System.out.println("Date: " + aLD);
String strDatewithTime = "2015-08-04T10:11:30";
LocalDateTime aLDT = LocalDateTime.parse(strDatewithTime);
System.out.println("Date with Time: " + aLDT);

Output,

Date: 2015-08-04
Date with Time: 2015-08-04T10:11:30

而只有在你必须处理其他日期模式时才使用DateTimeFormatter

例如,在下面的例子中。dd MMM uuuu代表月份的一天(两位数),月份名称的三个字母(Jan, Feb, Mar, ...),以及四位数的年份。

DateTimeFormatter dTF = DateTimeFormatter.ofPattern("dd MMM uuuu");
String anotherDate = "04 Aug 2015";
LocalDate lds = LocalDate.parse(anotherDate, dTF);
System.out.println(anotherDate + " parses to " + lds);

Output

04 Aug 2015 parses to 2015-08-04

还要记住,DateTimeFormatter对象是双向的;它既可以解析输入,也可以格式化输出。

String strDate = "2015-08-04";
LocalDate aLD = LocalDate.parse(strDate);
DateTimeFormatter dTF = DateTimeFormatter.ofPattern("dd MMM uuuu");
System.out.println(aLD + " formats as " + dTF.format(aLD));

Output

2015-08-04 formats as 04 Aug 2015

(See complete 格式化和解析DateFormatter的模式列表.)

  Symbol  Meaning                     Presentation      Examples
  ------  -------                     ------------      -------
   G       era                         text              AD; Anno Domini; A
   u       year                        year              2004; 04
   y       year-of-era                 year              2004; 04
   D       day-of-year                 number            189
   M/L     month-of-year               number/text       7; 07; Jul; July; J
   d       day-of-month                number            10
   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
   Y       week-based-year             year              1996; 96
   w       week-of-week-based-year     number            27
   W       week-of-month               number            4
   E       day-of-week                 text              Tue; Tuesday; T
   e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
   F       week-of-month               number            3
   a       am-pm-of-day                text              PM
   h       clock-hour-of-am-pm (1-12)  number            12
   K       hour-of-am-pm (0-11)        number            0
   k       clock-hour-of-am-pm (1-24)  number            0
   H       hour-of-day (0-23)          number            0
   m       minute-of-hour              number            30
   s       second-of-minute            number            55
   S       fraction-of-second          fraction          978
   A       milli-of-day                number            1234
   n       nano-of-second              number            987654321
   N       nano-of-day                 number            1234000000
   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
   z       time-zone name              zone-name         Pacific Standard Time; PST
   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;
   p       pad next                    pad modifier      1
   '       escape for text             delimiter
   ''      single quote                literal           '
   [       optional section start
   ]       optional section end
   #       reserved for future use
   {       reserved for future use
   }       reserved for future use
    
这个回答涉及到一个重要的问题:尽可能使用预定义的格式,例如,不要在 "yyyy-MM-dd "的基础上创建格式,而是使用DateTimeFormatter.ISO_LOCAL_DATE。这将使你的代码看起来更干净。此外,尝试最大限度地使用ISO8061格式,从长远来看,这将带来好处。
我想解析一个日期进行验证,如 2018-08-09 12:00:08 ,但当我解析时,我看到添加了一个 T ,我不需要。有什么方法可以做到这一点吗?
@Raghuveer T只是日期和时间之间的ISO-8061分隔符。如果你的格式中有空格,你可以简单地使用 yyyy-MM-dd hh:mm:ss 的模式进行解析和格式化。T将总是以默认(ISO-8061)格式显示,但你可以使用你自己的模式。
Marcio Jasinski
Marcio Jasinski
发布于 2023-01-10
0 人赞同

Both 苏菲安-古里的和 micha的回答 这篇文章很好地解释了关于字符串模式的问题。然而,为了防止你在工作中使用 ISO 8601 ,没有必要应用 DateTimeFormatter ,因为LocalDateTime已经为它准备好了。

将LocalDateTime转换为ISO8601的时区字符串

LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ldt.atZone(ZoneOffset.UTC); // You might use a different zone
String iso8601 = zdt.toString();

从ISO8601字符串转换回本地日期时间

String iso8601 = "2016-02-14T18:32:04.150Z";
ZonedDateTime zdt = ZonedDateTime.parse(iso8601);
LocalDateTime ldt = zdt.toLocalDateTime();
    
Ondra Žižka
Ondra Žižka
发布于 2023-01-10
0 人赞同

将一个带有日期和时间的字符串解析为一个特定的时间点(Java称其为" Instant ")是相当复杂的。Java已经在几个迭代中解决了这个问题。最新的 java.time java.time.chrono ,几乎涵盖了所有的需求(除了 时间扩张 :) ).

然而,这种复杂性带来了很多困惑。

理解日期解析的关键是。

Why does Java have so many ways to parse a date?

  • 有several systems to measure a time. For instance, the historical Japanese calendars were derived from the time ranges of the reign of the respective emperor or dynasty. Then there is, e.g., the Unix 时间戳 . Fortunately, the whole (business) world managed to use the same.
  • Historically, the systems were being switched from/to, for various reasons . E.g., from the Julian calendar to the Gregorian calendar in 1582; so, the 'western' dates before that need to be treated differently.
  • And, of course, the change did not happen at once. Because the calendar came from the headquarters of some religion and other parts of Europe believed in other deities, for instance Germany did not switch until the year 1700.
  • ...and why is the LocalDateTime , ZonedDateTime et al. so complicated

  • 时区 . 一个时区基本上是一个 "条纹 "*。 [3] 地球表面的当局遵循相同的规则,即什么时候有哪个时间偏移。这包括夏季时间规则。

    The 时区 随时间变化 for various areas, mostly based on who conquers whom. And one time zone's rules 随时间变化 也是如此。

  • 有time offsets. That is not the same as 时区, because a time zone may be, e.g., "Prague", but that has summer time offset and winter time offset.

    如果你得到一个带有时区的时间戳,其偏移量可能会有所不同,这取决于它在一年中的哪个部分。在闰时期间,时间戳可能意味着两个不同的时间,所以如果没有额外的信息,就不能可靠地转换。

    Note: By 时间戳 我的意思是 "一个包含日期和/或时间的字符串,可以选择带有时区和/或时间偏移"。

  • Several 时区 may share the same time offset for certain periods. For instance, the GMT/UTC time zone is the same as the "London" time zone when the summer time offset is not in effect.

    让它变得更复杂一些(但这对你的用例不是太重要)。

  • 科学家们观察地球的动态,它随着时间的推移而变化;在此基础上,他们在个别年份的末尾增加秒。(所以 2040-12-31 24:00:00 可能是一个有效的日期-时间)。这需要定期更新系统使用的元数据,以使日期转换正确。例如,在Linux上,你会得到包括这些新数据的Java包的定期更新。

  • The updates do not always keep the previous behavior for both historical and future 时间戳s. So it may happen that parsing of the two 时间戳s around some time zone's change comparing them 可能会产生不同的结果 当在不同版本的软件上运行时。这也适用于在受影响的时区和其他时区之间进行比较。

    Should this cause a bug in your software, consider using some 时间戳 that does not have such complicated rules, like Unix 时间戳 .

  • 因为7,对于未来的日期,我们不能确切地转换日期,有把握。因此,举例来说,当前解析的 8524-02-17 12:00:00 可能会与未来的解析结果相差几秒。

    JDK's APIs for this evolved with the contemporary needs

  • The early Java releases had just java.util.Date which had a bit naive approach, assuming that there's just the year, month, day, and time. This quickly did not suffice.
  • Also, the needs of the databases were different, so quite early, java.sql.Date was introduced, with its own limitations.
  • Because neither covered different calendars and 时区 well, the Calendar API was introduced.
  • This still did not cover the complexity of the 时区. And yet, the mix of the above APIs was really a pain to work with. So as Java developers started working on global web applications, libraries that targeted most use cases, like JodaTime, got quickly popular. JodaTime was the de facto standard for about a decade.
  • But the JDK did not integrate with JodaTime, so working with it was a bit cumbersome. So, after a very long discussion on how to approach the matter, JSR-310 was created mainly based on JodaTime .
  • How to deal with it in Java's java.time

    Determine what type to parse a 时间戳 to

    When you are consuming a 时间戳 string, you need to know what information it contains. 这是关键的一点。 如果你没有弄清楚这一点,你就会出现 "无法创建即时"、"区域偏移丢失"、"未知区域ID "等令人费解的异常。

  • Unable to obtain OffsetDateTime from TemporalAccessor
  • Unable to obtain ZonedDateTime from TemporalAccessor
  • Unable to obtain LocalDateTime from TemporalAccessor
  • Unable to obtain Instant from TemporalAccessor
  • 它是否包含日期和时间?

  • 它是否有一个时间偏移? 时间偏移是指 +hh:mm 部分。有时。 +00:00 可以用 Z 称为 "祖鲁时间", UTC 称为世界时间协调,或 GMT as Greenwich Mean Time. These also set the time zone. For these 时间戳s, you use OffsetDateTime .

  • 它有一个时区吗? For these 时间戳s, you use ZonedDateTime . 区是由以下两种方式指定的

  • name ("Prague", "Pacific Standard Time", "PST"), or
  • "zone ID" ("America/Los_Angeles", "Europe/London"), represented by java.time.ZoneId .
  • The list of 时区 is compiled by a "TZ数据库" 撑腰的是 ICAAN .

    根据 ZoneId 的javadoc,区域ID也可以以某种方式被指定为 Z 和偏移。我不确定这如何映射到实际区域。

    If the 时间戳, which only has a TZ, falls into a leap hour of time offset change, then it is ambiguous, and the interpretation is subject of ResolverStyle , see below.

  • 如果它既没有 那么,缺失的背景就会被假定或忽略掉。而消费者必须决定。因此,它需要被解析为 LocalDateTime 并通过添加缺失的信息转换为 OffsetDateTime

  • You can assume that it is a UTC time. Add the UTC offset of 0 hours.
  • You can assume that it is a time of the place where the conversion is happening. Convert it by adding the system's time zone.
  • You can neglect and just use it as is. That is useful e.g. to compare or subtract two times (see Duration ), or when you don't know and it doesn't really matter (e.g., local bus schedule).
  • 部分时间信息

  • Based on what the 时间戳 contains, you can take LocalDate , LocalTime , OffsetTime , MonthDay , Year , or YearMonth out of it.
  • 如果你有完整的信息,你可以得到一个 java.time.Instant .这也是内部用来在 OffsetDateTime ZonedDateTime 之间的转换。

    Figure out how to parse it

    有大量关于 DateTimeFormatter which can both parse a 时间戳 string and format to string.

    The pre-created DateTimeFormatter s should cover more or less all standard 时间戳 formats. For instance, ISO_INSTANT can parse 2011-12-03T10:15:30.123457Z .

    如果你有一些特殊的格式,那么你可以 创建你自己的DateTimeFormatter (这也是一个分析器)。

    private static final DateTimeFormatter TIMESTAMP_PARSER = new DateTimeFormatterBuilder()
       .parseCaseInsensitive()
       .append(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SX"))
       .toFormatter();
    

    我建议你看一下DateTimeFormatter的源代码,并在如何使用DateTimeFormatterBuilder建立一个替换代码方面得到启发。当你在那里的时候,也可以看看ResolverStyle,它可以控制解析器对格式和模糊的信息是LENIENT、SMART还是STRICT。

    TemporalAccessor

    现在,经常出现的错误是进入TemporalAccessor的复杂性。这来自于开发人员习惯于使用SimpleDateFormatter.parse(String)的工作方式。没错,DateTimeFormatter.parse("...")给了你TemporalAccessor

    // No need for this!
    TemporalAccessor ta = TIMESTAMP_PARSER.parse("2011-... etc");
    

    但是,配备了上一节的知识,你可以方便地解析到你需要的类型。

    OffsetDateTime myTimestamp = OffsetDateTime.parse("2011-12-03T10:15:30.123457Z", TIMESTAMP_PARSER);
    

    你实际上也不需要DateTimeFormatter。你想解析的类型有parse(String)的方法。

    OffsetDateTime myTimestamp = OffsetDateTime.parse("2011-12-03T10:15:30.123457Z");
    

    关于TemporalAccessor,如果你对字符串中的信息有一个模糊的概念,并且想在运行时决定,你可以使用它。

    我希望我给你的灵魂带来一些理解之光 :)

    注意:java.time有一个回传到Java 6和7。三联书店-Backport.对于安卓系统,它有三田ABP.

    [3]不仅仅是它们没有条纹,而且还有一些奇怪的极端情况。例如,有些邻近的太平洋岛屿 have +14:00 and -11:00 时区. That means, that while on one island, there is 1st May 3 PM, on another island not so far, it is still 30 April 12 PM (if I counted correctly :) )

    Yu Cheng
    Yu Cheng
    发布于 2023-01-10
    0 人赞同

    对于 LocalDateTime.parse ,需要注意的另一点是,你不能将其用于只有日期格式化字符的自定义格式化,如 uuuuMMdd 。在这种情况下,你应该使用 LocalDate.parse 来代替。比如说。

    String s = "20210223";
    // ok
    LocalDate.parse(s, DateTimeFormatter.ofPattern("uuuuMMdd"));
    // java.time.format.DateTimeParseException
    LocalDateTime.parse(s, DateTimeFormatter.ofPattern("uuuuMMdd")); 
        
    Santhosh Hirekerur
    Santhosh Hirekerur
    发布于 2023-01-10
    0 人赞同

    以规定的格式获取当前的UTC时间

    // Current the UTC time
    OffsetDateTime utc = OffsetDateTime.now(ZoneOffset.UTC);
    // Get LocalDateTime
    LocalDateTime localDateTime = utc.toLocalDateTime();
    System.out.println("*************" + localDateTime);
    // Formatted UTC time
    DateTimeFormatter dTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    System.out.println(" formats as " + dTF.format(localDateTime));
    // Get the UTC time for the current date
    Date now = new Date();
    LocalDateTime utcDateTimeForCurrentDateTime = Instant.ofEpochMilli(now.getTime()).atZone(ZoneId.of("UTC")).toLocalDateTime();
    DateTimeFormatter dTF2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    System.out.println(" formats as " + dTF2.format(utcDateTimeForCurrentDateTime));
        
    msangel
    msangel
    发布于 2023-01-10
    0 人赞同

    所有的答案都是好的。Java 8以上版本有这些模式用于解析和格式化时区。 V z O X x Z

    这里是他们,为 解析 ,根据文件中的规则。

       Symbol  Meaning                     Presentation      Examples
       ------  -------                     ------------      -------
       V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
       z       time-zone name              zone-name         Pacific Standard Time; PST
       O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
       X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
       x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
       Z       zone-offset                 offset-Z          +0000; -0800; -08:00;
    

    但如何格式化?

    Here's a sample for a date (assuming ZonedDateTime) that show these patters behavior for different 格式化 patters:

    // The helper function:
    static void printInPattern(ZonedDateTime dt, String pattern) {
        System.out.println(pattern + ": " + dt.format(DateTimeFormatter.ofPattern(pattern)));
    // The date:
    String strDate = "2020-11-03 16:40:44 America/Los_Angeles";
    DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss zzzz");
    ZonedDateTime dt = ZonedDateTime.parse(strDate, format);
    // 2020-11-03T16:40:44-08:00[America/Los_Angeles]
    // Rules:
    // printInPattern(dt, "V");     // exception!
    printInPattern(dt, "VV");       // America/Los_Angeles
    // printInPattern(dt, "VVV");   // exception!
    // printInPattern(dt, "VVVV");  // exception!
    printInPattern(dt, "z");        // PST
    printInPattern(dt, "zz");       // PST
    printInPattern(dt, "zzz");      // PST
    printInPattern(dt, "zzzz");     // Pacific Standard Time
    printInPattern(dt, "O");        // GMT-8
    // printInPattern(dt, "OO");    // exception!
    // printInPattern(dt, "OO0");   // exception!
    printInPattern(dt, "OOOO");     // GMT-08:00
    printInPattern(dt, "X");        // -08
    printInPattern(dt, "XX");       // -0800
    printInPattern(dt, "XXX");      // -08:00
    printInPattern(dt, "XXXX");     // -0800
    printInPattern(dt, "XXXXX");    // -08:00
    printInPattern(dt, "x");        // -08
    printInPattern(dt, "xx");       // -0800
    printInPattern(dt, "xxx");      // -08:00
    printInPattern(dt, "xxxx");     // -0800
    printInPattern(dt, "xxxxx");    // -08:00
    printInPattern(dt, "Z");        // -0800
    printInPattern(dt, "ZZ");       // -0800
    printInPattern(dt, "ZZZ");      // -0800
    printInPattern(dt, "ZZZZ");     // GMT-08:00
    printInPattern(dt, "ZZZZZ");    // -08:00
    

    在正偏移的情况下,+符号字符到处使用(现在有-的地方),绝不省略。

    这很适用于新的java.time类型。如果你准备将这些用于java.util.Datejava.util.Calendar的话- 不是所有的工作,因为这些类型已经坏了(所以被标记为废弃的,请不要使用它们)。

    mrsrinivas
    mrsrinivas
    发布于 2023-01-10
    0 人赞同

    让我们来看看两个问题,示例字符串 "2014-04-08 12:30"

    我如何从给定的字符串中获得一个LocalDateTime实例?

    import java.time.format.DateTimeFormatter
    import java.time.LocalDateTime
    final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
    // Parsing or conversion
    final LocalDateTime dt = LocalDateTime.parse("2014-04-08 12:30", formatter)
    

    替换代码2】应该允许你进行所有与日期时间有关的操作

    然后我如何将LocalDateTime实例转换回具有相同格式的字符串?

    final String date = dt.format(formatter) 
        
    Tomasz
    Tomasz
    发布于 2023-01-10
    0 人赞同

    The 通用方法 看起来如下所示。它适用于

  • yyyy-MM-dd HH:mm:ss.SSS

  • yyyy-MM-dd HH:mm:ss.S

  • yyyy-MM-dd HH:mm:ss

  • yyyy-MM-dd HH:mm

  • yyyy-MM-dd HH

  • yyyy-MM-dd

    public static final String DATE_FORMAT_YYYY_MM_DD_HH_MM_SS_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
    public LocalDateTime stringToLocalDateTime(String s){
        return LocalDateTime.parse(s, DateTimeFormatter.ofPattern(DATE_FORMAT_YYYY_MM_DD_HH_MM_SS_SSS.substring(0, s.length())));
        
  • flowgrad
    flowgrad
    发布于 2023-01-10
    0 人赞同

    我发现像这样涵盖多种日期时间格式的变体是很美妙的。

    final DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
    dtfb.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS"))
        .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSS"))
        .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS"))
        .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS"))
        .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSS"))
        .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSS"))
        .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
        .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS"))
        .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"))
        .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
        .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
        .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0);
        
    `` public final static DateTimeFormatter TIMESTAMP_XX = new DateTimeFormatterBuilder().appendPattern ("[[uuuu][-MM][-dd]] [[HH][:mm][:ss][.SSS]]" .parseDefaulting (ChronoField.YEAR , 2020) .parseDefaulting (ChronoField.MONTH_OF_YEAR , 1) 。.parseDefaulting (ChronoField.Day_OF_MONTH , 1) .parseDefaulting (ChronoField.HOUR_OF_DAY , 0) .parseDefaulting (ChronoField.MINUTE_OF_HOUR , 0) .parseDefaulting (ChronoField.SECOND_OF_MINUTE, 0) .toFormatter() ; ````
    Arvind Kumar Avinash
    Arvind Kumar Avinash
    发布于 2023-01-10
    0 人赞同

    对于这个问题,已经有很多好的答案了。这个答案展示了如何使用预定义的 DateTimeFormatter 来构建一个 DateTimeFormatter ,它可以解析给定的日期时间字符串。

    然而,使用这个 DateTimeFormatter 对得到的 LocalDateTime 进行格式化,将返回一个 HH:mm:ss 格式的时间字符串。为了将时间字符串限制为 HH:mm 的格式,我们还是要像其他答案那样使用 uuuu-MM-dd HH:mm 的模式。

    Demo :

    class Main {
        public static void main(String[] args) {
            DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                    .append(DateTimeFormatter.ISO_LOCAL_DATE)
                    .appendLiteral(' ')
                    .append(DateTimeFormatter.ISO_LOCAL_TIME)
                    .toFormatter(Locale.ENGLISH);
            String strDateTime = "2014-04-08 12:30";
            LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
            System.out.println(ldt);
            // However, formatting the obtained LocalDateTime using this DateTimeFormatter
            // will return a string with time in HH:mm:ss format. To restrict the time
            // string to HH:mm format, we still have to use the pattern, uuuu-MM-dd HH:mm as
            // other answers have done.
            String strDateTimeFormatted = ldt.format(dtf);
            System.out.println(strDateTimeFormatted);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm", Locale.ENGLISH);
            strDateTimeFormatted = ldt.format(formatter);
            System.out.println(strDateTimeFormatted);
    

    Output:

    2014-04-08T12:30
    2014-04-08 12:30:00