Java LocalDateTime 格式问题

Java LocalDateTime formatting issue

我制作了一个名为 Observation 的 class,其构造函数将 CSV 文件的单行作为输入。我已经提取了 LocalDateTime,但是,它没有按照我的预期进行格式化。

public class Observation {

    private String date, time, datetimeStr;
    private LocalDateTime dateTime;

    private static DateTimeFormatter FORMAT = DateTimeFormatter.ofPattern("dd-MMM-yy HH:mm"); 

    public Observation(String line) {
        String[] parts = line.trim().split(",");
        if (parts.length != 14) {
            throw new InputMismatchException("Error: Invalid data!");
        }

        date = String.valueOf(parts[6]);
        time = String.valueOf(parts[7]);
        dateTimeStr = date + " " + time;
        dateTime = LocalDateTime.parse(dateTimeStr, FORMAT);
    }

    // DateTime Getter
    public LocalDateTime getDateTime() {
      return dateTime;
    }

    public static void main(String[] args) {
        String input= "Leeds,Albion Street North,2017,March,13,Saturday,01-Apr-17,00:00,197,0,197,197,0,197";

        Observation test = new Observation(input);

        // Print out DateTime
        System.out.println("Date-Time: " + test.getDateTime());

    }
}

所以我想要的格式是 "01-Apr-17 00:00" 并且我正在使用上面指定的格式化程序 "dd-MMM-yy HH:mm"

使用 dateTime getter 时,我从终端获得的结果是:

Ashs-MacBook-Pro:resit asheastham$ Java ObservationTest
Date-Time: 2017-04-01T00:00

与您的假设相反,LocalDateTime.parse(dateTimeStr, FORMAT) does not parse _and format_ the contents ofdateTimeStr` 但仅解析日期时间值,期望它具有您在 FORMAT 中指定的格式。

输出时需要格式化日期时间值:

public static void main(String[] args) {
  String input= "Leeds,Albion Street North,2017,March,13,Saturday,01-Apr-17,00:00,197,0,197,197,0,197";

  Observation test = new Observation(input);

  // Print out DateTime
  System.out.println("Date-Time: " + FORMAT.format(test.getDateTime()));

}

这会生成所需的输出:

Date-Time: 01-Apr-17 00:00

我认为您在日期方面混淆了 2 个不同的 "concepts":日期对象的 value此值以某种特定格式表示

一个LocalDateTime对象代表一个date/time:它保存着日、月、年、时、分、秒和纳秒的。但是日期本身 has no format at all - 这个 link 是关于 java.util.Date,但是日期没有格式的一般概念也适用于 LocalDateTime

LocalDateTime 对象只有与日期和时间相对应的值,但是这些值可以以多种不同的方式显示。而那些不同的方式与价值观本身无关。因此,date/time April 1st 2017 at midnight 可以是 represented/displayed 许多不同的 格式:

  • 4 月 1 日st 2017 00:00:00
  • 2017 年 1 月 4 日 0:00
  • 2017 年 4 月 1 日 00:00
  • 2017-04-01T00:00
  • 还有许多其他人...

虽然以上所有格式都不同,它们代表相同的日期和时间。各个字段(日、月、年、时、秒等)的相同,因此都表示相同的date/time值(在本例中,相同 LocalDateTime).


当您执行 LocalDateTime.parse(dateTimeStr, FORMAT) 时,您正在将特定的 格式 转换为日期值(在本例中为 LocalDateTime)。这个操作叫做parsing:得到一个String(一个文本)在一个特定的格式并且把它转换成date/time .

创建的DateTimeFormatter指定格式是什么:

FORMAT = DateTimeFormatter.ofPattern("dd-MMM-yy HH:mm")

这意味着要解析的 String 将采用指定的格式 - 在这种情况下,dd(2 位数字的日期),然后是 -,然后是MMM(月份简称)等。 javadoc 包含有关所有可用模式的详细信息。


当你这样做时:

System.out.println("Date-Time: " + test.getDateTime());

此代码隐式调用 LocalDateTimetoString() 方法,此方法 returns the date/time in a specific format:

Outputs this date-time as a String, such as 2007-12-03T10:15:30. The output will be one of the following ISO-8601 formats:

uuuu-MM-dd'T'HH:mm
uuuu-MM-dd'T'HH:mm:ss
uuuu-MM-dd'T'HH:mm:ss.SSS
uuuu-MM-dd'T'HH:mm:ss.SSSSSS
uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS

The format used will be the shortest that outputs the full value of the time where the omitted parts are implied to be zero

这就是为什么您的程序将日期输出为 2017-04-01T00:00 的原因:这是 LocalDateTime::toString() 方法的结果。


如果您想以 01-Apr-17 00:00 格式打印 LocalDateTime,您应该调用 FORMAT.format(test.getDateTime())(已在 中解释)。

如果您同时需要 LocalDateTime(存储它,)和指定格式的日期,并且在构造函数中执行所有操作,则必须保留 2 个不同的字段(一个 LocalDateTime 和一个 String).

实际上,您已经在这样做了。您的 dateTimeStr 字段已包含所需格式的日期,因此只需为其创建一个 getter。或者创建另一个方法(如 getFormattedDateTime()),即 returns FORMAT.format(this.dateTime)。然后你将有 2 种方法:一种是 returns LocalDateTime(当你需要日期对象时,比如存储它时),另一种是 returns 格式化的 String (当你需要打印它时)。


还有一件事:月份名称 ("Apr") 是英文的。您的代码可以正常工作,因为 JVM 的默认语言环境也是英语,但不能保证它总是那样。并且默认区域设置可以在不通知的情况下更改,即使在运行时也是如此(同一 JVM 中的其他一些应用程序可以调用 Locale.setDefault(),或者有人可能错误配置 JVM,您的代码将突然中断)。

为避免这种情况,您可以使用 java.util.Locale 设置格式化程序并明确表示您使用的是英语:

// formatter always uses English for month names
DateTimeFormatter FORMAT = DateTimeFormatter.ofPattern("dd-MMM-yy HH:mm", Locale.ENGLISH);