Java 项目中的一项常见任务是将日期格式化或解析为字符串,反之亦然。解析日期意味着你有一个代表日期的字符串,例如“2017-08-3”,你想把它转换成一个代表 Java 中日期的对象,例如Java 8 之前的世界中的 java.util.Date 和 Java 8 世界中的 LocalDate 或 LocalDatetime。同样,格式化日期意味着将日期实例转换为字符串,例如,您有一个 Date 对象或 LocalDatetime 对象,并且您想要一个 dd-MM-yyyy 格式的字符串。
Java 8 API 为格式化和解析日期提供了良好的支持。例如,如果您有一个日期作为字符串,例如“2017-08-3 12:30”,你想将它转换为 LocalDateTime 实例,这是 JDK 8 日期和时间 API 中的一个新类,包含日期和时间部分,你该怎么做?好吧,您可以使用 LocalDateTime 类中的 format() 和 parse() 方法来实现这一点,但您还需要一件事,即日期格式。
在 Java 8 之前,您可能知道我们使用 SimpleDateFormat 和 DateFormat 类来表示格式,这有很多问题,例如它们很重、可变且不是线程安全的,这意味着您不能共享它们,并且每次需要将 String 转换为 Date 时,您都必须创建一个新的 DateFormat 对象。尽管将 SimpleDateFormat 封装到线程局部变量中确实提供了一些喘息机会,但这还不够。
JDK 8 在新的 DateTimeFormatter 类中解决了这个问题,该类可用于定义日期和时间格式,例如“yyyy-MM-dd HH: mm”,指定格式的语法与我们之前在 SimpleDateFormat 类中使用的语法相同,但该类是线程安全且不可变的,这意味着您可以在线程之间共享其实例。理想情况下,您可以将 DateTimeFormatter 的引用存储到静态变量中以使其成为全局变量。
使用 DateTimeFormatter 的另一个优点是它提供了几个内置的格式化程序,例如java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME,可以将日期表示为“2017-08-03T10:15:30”。您可以在 Javadoc 中查看内置格式化程序的完整列表,或者您可以阅读 Java SE 8 for Really Impatient 以了解更多相关信息。
获得格式化程序后,解析或格式化日期就像调用方法一样简单。您只需要调用 LocalDateTime.parse() 方法将 String 转换为 Java 8 中的 LocalDateTime。parse() 获取一个 String 并根据 DateTimeFormatter 指定的格式解析为 LocalDateTime 实例。 parse() 方法也被重载,默认情况下它使用 ISO_LOCAL_DATE_TIME 格式,即“yyyy-MM-dd HH:mm”,即“2017-08-03T10:15:30”,但如果您的字符串采用不同的格式,则您可以指定一个单独的格式化程序。
所以,足够的理论,让我们开始真正的工作......
假设您从数据库或 ISO 格式的文件中将日期作为字符串加载,例如“yyyy-MM-dd HH:mm” 并且您想将它们转换为 java.time.LocalDateTime。以下是在 Java 8 中将日期字符串解析为 LocalDateTime 的具体步骤:
1) 创建一个 DateTimeFormatter 对象
2) 使用 LocalDateTime.parse(string, formatter) 方法将 String 转换为 LocalDatetime 对象
顺便说一句,在我们的例子中日期是 ISO 格式,你不需要创建一个单独的格式化程序,你可以直接调用 parse 方法,如下例所示:
String date = "2017-03-08T12:30:54"; LocalDateTime localdatetime = LocalDateTime.parse(date); System.out.println("origional date as string: " + date); System.out.println("generated LocalDateTime: " + localdatetime); Output origional date as string: 2017-03-08T12:30:54 generated LocalDateTime: 2017-03-08T12:30:54
顺便说一句,如果您的日期字符串不是解析方法所期望的 ISO 格式,例如第二部分没有 T 或缺少分钟,然后它将抛出 DateTimeParseException。例如,如果要解析“2017-08-3 12:30”或“2017-03-08 12:30:54”,则会抛出以下异常:
线程“主”java.time.format.DateTimeParseException 中的异常:无法在 java.time.format.DateTimeFormatter.parseResolved0 的索引 10 处解析文本“2017-03-08T12:30:54” (DateTimeFormatter.java:1949) 在 java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851) 在 java.time.LocalDateTime.parse(LocalDateTime.java:492) 在 Demo.main(Demo.java:22)
为避免此错误,您可以创建一个与日期字符串匹配的 DateTimeFormatter 实例。例如,如果您的日期类似于“2017-08-3 12:30”,那么您可以创建一个 DateTimeFormatter,如下所示:
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
在此之后,您可以使用此格式化程序实例将 String 解析为 LocalDateTime,如以下示例所示:
String date = "2017-03-08 12:30:54"; DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); LocalDateTime dateTime = LocalDateTime.parse(date, format); System.out.println("origional date as string: " + date); System.out.println("generated LocalDateTime: " + dateTime); Output: origional date as string: 2017-03-08 12:30 generated LocalDateTime: 2017-03-08T12:30
您可以看到没有更多异常,但您必须确保 date as String 必须与您在 DateTimeFormatter 实例中定义的模式匹配。由于它也是线程安全和不可变的,您甚至可以将其存储在静态变量中并在程序的另一部分之间共享。您可以在 Java SE 8 for the Really Impatient 一书中阅读有关线程安全和不变性的更多信息。
在上一节中,您学习了如何解析日期,例如将日期的字符串表示形式转换为相应的对象,即 Java 8 中的 LocalDateTime。现在,让我们做相反的事情,从现有的 LocalDateTime 对象创建一个格式化的字符串,例如“dd-MM-yyyy”格式的日期。
同样,我们需要一个 DateTimeFormatter 实例来保存我们的日期模式,然后我们可以使用 LocalDateTime 类的 format() 方法来实现这一点。但是,您应该记住 format() 是一个非静态方法,您需要一个 LocalDateTime 类的实例来调用此方法。以下是在 Java 8 中使用 LocalDatetime 格式化日期的示例:
DateTimeFormatter aFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm"); LocalDateTime localDateTime = LocalDateTime.of(2017, Month.AUGUST, 3, 12, 30); String foramttedString = localDateTime.format(aFormatter); // "2017-03-08 12:30" System.out.println("origional LocalDatetime object: " + localDateTime); System.out.println("generated string : " + foramttedString); Output: origional LocalDatetime object: 2017-08-03T12:30 generated string : 03-08-2017 12:30
你应该注意到我们是在对象上调用格式化方法而不是类,因为它是一个非静态方法,与静态方法 parse() 相反。您还可以看到生成的字符串确认了您的模式,即“03-08-2017 12:30”采用“dd-MM-yyyy HH:mm”格式。
这是我们的示例 Java 程序,它封装了在 Java 8 中使用 LocalDateTime 解析和格式化日期的示例。
import java.time.LocalDateTime; import java.time.Month; import java.time.format.DateTimeFormatter; /* * Java Program to parse to LocalDateTime in JDK 8. * We'll convert a String "2017-03-08 12:30" into LocalDateTime. * we'll also see how to format a LocalDateTime instance to String format. */ public class Demo { public static void main(String[] args) throws Exception { // parsing a string date to LocalDateTime String date = "2017-03-08 12:30"; DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); LocalDateTime dateTime = LocalDateTime.parse(date, format); System.out.println("origional date as string: " + date); System.out.println("generated LocalDateTime: " + dateTime); //formatting a LocalDateTime to string instance DateTimeFormatter aFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); LocalDateTime localDateTime = LocalDateTime.of(2017, Month.AUGUST, 3, 12, 30); String foramttedString = localDateTime.format(aFormatter); // "2017-03-08 12:30" System.out.println("origional LocalDatetime object: " + localDateTime); System.out.println("generated string : " + foramttedString); // be careful, string must contain date and time portion // if you are converting to LocalDateTime, or else, your // code will break LocalDateTime dateWithoutTime = LocalDateTime.parse("2017-08-03", format); } } Output origional date as string: 2017-03-08 12:30 generated LocalDateTime: 2017-03-08T12:30 origional LocalDatetime object: 2017-08-03T12:30 generated string : 2017-08-03 12:30 Exception in thread "main" java.time.format.DateTimeParseException: Text '2017-08-03' could not be parsed at index 10 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851) at java.time.LocalDateTime.parse(LocalDateTime.java:492) at Demo.main(Demo.java:35)
1) LocalDateTime.parse() 方法用于解析,它是一个静态方法,但 format() 方法不是静态的,它需要一个 LocalDateTime 实例来调用。这是 parse() 和 format() 方法之间需要注意的重要区别。例如 LocalDateTime.format(DateTimeFromatter) 在 Java 中是非法的,并给出编译时错误。
2) 您必须确保您的 String 确认您用于解析和格式化的格式,否则 parse() 和 format() 方法都会抛出 DateTimeParseException,例如“线程“main”java.time.format.DateTimeParseException 中的异常:文本‘2017-08-03’ 无法在索引 10 处解析”。
3) Java 8 中有几种内置格式可用,如果它破坏了目的,我们也应该利用它而不是创建一个新格式。
4) 由于 DateTimeFormatter 既是不可变的又是线程安全的,因此建议将其存储在静态变量中并在任何想要使用的人之间共享,但要确保该变量既是静态变量又是最终变量,以便线程可以读取它但不能分配新的对它的引用或 null,这可能会导致微妙的问题。有关更多详细信息,请参阅我关于在多线程环境中使用静态变量的危险的帖子。
以下是在 Java 8 中将日期格式化或解析为 LocalDateTime 的代码摘要:
这就是关于如何在 Java 8 中使用 LocalDateTime 格式化和解析日期。正如我所说,每个新课程,例如LocalDate、LocalTime 和 LocalDateTime 具有解析和格式化方法,可用于将字符串转换为日期,反之亦然。请记住,您需要一个 DateTimeFormatter,其模式必须与您的日期字符串匹配,否则两个 parse() 方法都会抛出 java.time.format.DateTimeParseException 错误。
您还应该记住 parse() 和 format() 方法之间的区别,前者是静态的,而后者是非静态的。您可以记住的另一件事是以静态变量的形式重用 DateTimeFormatter 实例,或者利用 JDK 中可用的几个内置格式化程序。您可以进一步阅读 Java SE 8 for Really Impatient 以了解有关 Java 8 新功能的更多信息,包括新的日期和时间 API。
您可能想探索的其他Java 8 日期和时间教程:
如何比较Java中的两个日期? (教程) 如何在 Java 中获取当前时间戳值? (教程) 如何在 Java 8 中将 String 转换为 LocalDateTime? (example) 如何在JDBC中将java.util.Date转换为java.sql.Timestamp? (教程) 如何在 Java 8 中将 Date 转换为 LocalDateTime? (教程) 如何在 Java 6 中获取当前日期和时间? (教程) 如何使用 JodaTime 库将字符串解析为日期? (example) 如何在JDBC中将java.util.Date转换为java.sql.Date? (教程) 如何在 Java 8 中将字符串转换为 LocalDateTime (教程)
感谢您到目前为止阅读本文。如果您喜欢这个 Java 8 日期和时间教程以及我的技巧,请与您的朋友和同事分享。如果您有任何问题或反馈,请发表评论。
标签2: Java教程地址:https://www.cundage.com/article/jcg-formatparse-dates-localdatetime-java-8-example-tutorial.html