将Java(或任何编程语言)中的字符串转换为日期是一项基本技能,对于在项目上进行工作很有用。有时,使用字符串表示日期,然后将其转换为Date对象以供进一步使用是更容易的。
在本文中,我们将介绍许多可用于将Java字符串转换为日期对象的方法和库。
日期/时间API
Java中的日期/时间API默认情况下使用ISO 8601格式(yyyy-MM-dd)。
默认情况下,所有日期都遵循此格式,如果您使用默认格式器,则所有转换后的字符串都必须遵循该格式。
parse()
该API定义了一种parse()方法,该方法接受字符序列并使用ISO_LOCAL_DATE格式来解析输入:
parse(CharSequence);
另外,您可以使用此方法的两个参数的变体,定义一个不同的格式化程序:
parse(CharSequence, DateTimeFormatter);
DateTimeFormatter用于在新的日期/时间API中格式化和解析日期时间对象。此API中的所有日期时间类都包含一种用于解析和格式化的方法,其中每个方法都接受DateTimeFormatter来定义模式。
将字符串转换为LocalDate
LocalDate表示日期,没有ISO-8601格式的时间。
它与Date以下事实的不同之处在于,它不将时间存储为自纪元以来的毫秒偏移量,而只是存储当前日期。它也是Date / Time API的较新实现,并提供了自己的格式/解析方法,以及日,周和年的加减法,这在Date变体中不存在。
要将字符串转换为LocalDate对象,只需编写以下代码:
LocalDate date = LocalDate.parse("2018-09-16");
这等效于编写处理代码以实例化LocalDate对象:
LocalDate date = LocalDate.of(2018, 09, 16);
将字符串转换为LocalTime
LocalTime代表时间,不带ISO-8601格式的时区。它不存储自历元以来的偏移时间,而是提供纳秒级精度。
与LocalDate一样,它提供了许多内置的非常有用的解析和格式化方法,以及从中添加或减去时间的方法。
要将字符串转换为LocalTime对象,只需编写以下代码:
LocalTime localTime = LocalTime.parse("8:00");
这等效于编写处理代码以实例化LocalTime对象:
LocalTime localTime = LocalTime.of(8, 00);
将字符串转换为LocalDateTime
这LocalDateTime是Java中有关日期/时间的最常用的类。它代表日期和时间的组合,可以用于许多目的:
LocalDateTime localDateTime = LocalDateTime.parse("2018-09-16T08:00:00");
乍一看,这种格式可能令人困惑,但实际上非常简单:
“时间”标记仅表示格式的LocalDate和之间的一条线LocalTime。
您还可以轻松地将其格式化LocalDateTime为更具可读性的格式:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatDateTime = localDateTime.format(formatter);
运行这段代码并打印formatDateTime将产生:
2018-09-16 08:00:00
您通常会这样做,以便在LocalDateTime事先对对象执行操作的同时以字符串格式向最终用户显示结果。
将字符串转换为ZonedDateTime
根据要处理的项目,在处理日期和时间时,可能需要处理不同的时区。
将字符串转换为ZonedDateTime对象很简单:
ZonedDateTime zonedDateTime = ZonedDateTime.parse("2018-09-16T08:00:00+00:00[Europe/London]");
上面的示例显示了如何初始化ZonedDateTime伦敦的。
使用自定义格式化程序转换字符串
有时,我们可能希望使用我们自己的自定义格式化程序,该格式化程序以多种方式接受字符串,但仍然不会抛出DateTimeParseException。
这是您将使用的一些最常见的模式:
窗体底端
- y:年(2018,18)
- M:一年中的一个月(08年8月,8月)
- d:一个月中的某天(1、5、25)
- E:一周中一天的名称(周一,周六)
- a:前子午/后子午标记(AM,PM)
- H:24小时制的小时(1、7、14、21)
- h:12小时风格的小时(1、5、12)
- m:一小时内的分钟数(1、25、54)
- s:一分钟内的秒数(1、25、54)
还有一些您可能不会经常使用:
- G:时代代号(AD,CE)
- Y:周年(2018,18)
- w:一年中的一周(25,53)
- W:一个月中的一周(2)
- D:一年中的一天(254)
- F:一个月中的星期几(3)
- E:一周中的日期名称(星期一,星期一)
- u:一周的天数(1、4)
- k:一天中的小时(17)
- K:一天中的AM / PM小时(5)
- S:毫秒(1245)
- z:一般时区(太平洋标准时间;太平洋标准时间; GMT-8:00)
- Z:RFC 822时区(-0800)
- X:ISO 8601时区(-08,-0800,-8:00)
注意:周年与年份不同-周年与WEEK_OF_YEAR周期同步。第一周到最后一周(包括最后一周)之间的所有星期都具有相同的周年值。因此,一周的第一天和最后一天可能具有不同的日历年值。
注意: K和H相同的方式k和h不同。H和h分别指的是0-23和1-12的模式,而K与k分别指的是0-11和1-24。
如果仍然不能满足您对自定义格式器的需求,则可以使用DateTimeFormatterBuilder来构建非常具体且复杂的格式器。除其他外,DateTimeFormatter是使用此类构建的。
java.util.Date
这是一种较旧的方法,如今已不常用,但仍然值得一提,因为有时我们仍使用这些API中的类:
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
Date date = formatter.parse("22-Sep-2018");
我们可以将许多模式传递给的构造函数SimpleDateFormat。您可以使用可用的模式来组合几乎任何数量的格式。
无法为日期设置时区,因为它根本不包含此类信息。但是,很容易格式化日期并将时区信息添加到字符串中:
SimpleDateFormat formatter = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = formatter.parse("22-09-2018 08:23:43 PM");
String formattedDate = formatter.format(date);
System.out.println(date);
System.out.println(formattedDate);
运行这段代码将产生:
Sat Sep 22 22:23:43 CEST 2018
22-9-2018 08:23:43 PM
“ 22:23:43 CEST”对应于“ 10:23:43 PM”时间,而格式化日期则代表“ 8:23:43 PM”,因为它处于不同的时区。
SimpleDateFormat与DateTimeFormatter
阅读本文,很容易提出一个问题-“有什么区别,我应该使用哪个? ”
DateTimeFormatter已在Java 8中用新的Date / Time API添加,并替换了较旧的,现在已不常用的SimpleDateFormat。与旧版本不同,它是线程安全的,并提供新功能:
// SimpleDateFormat
SimpleDateFormat formatter = new SimpleDateFormat("dd-M-yyyy");
Date date = new Date();
String formattedDate = formatter.format(date);
Date parsedDate = formatter.parse(formattedDate);
// DateTimeFormatter
LocalDate date = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-M-yyyy");
String formattedDate = date.format(formatter);
LocalDate parsedDate = LocalDate.parse(formattedDate, formatter);
很明显看到这两者之间的区别。在较旧的方式中,格式化程序用于格式化然后解析日期。以更新的方式,日期具有其自己的格式和解析方法,并且DateTimeFormatter仅将模式用作模式。
如果您正在使用Java 8和新API,请使用DateTimeFormatter,而如果您仍在使用Java的旧版本,请使用SimpleDateFormat。
乔达时代
开发Joda-Time是为了解决旧的Java时间和日期类的问题。
从Java 8开始,这些问题已得到纠正,并且Joda-Time已达到其目的。甚至它的作者都建议迁移到官方,java.time以便确定日期和时间。
如果这是不可能的,并且对于仍然使用Java 8之前的Java版本的用户,Joda-Time仍然是一个不错的库。
该库的依赖项可以通过Maven依赖项轻松添加:
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>{version}</version>
</dependency>
使用Joda-Time与使用Java的Date / Time API非常相似:
DateTimeFormatter formatter = DateTimeFormatter.forPattern("dd-MM-yyyy HH:mm:ss");
DateTime dateTime = DateTime.parse("22-Sep-2018 8:15:43", formatter);
Joda-Time的DateTime课程也支持时区:
DateTimeFormatter formatter = DateTimeFormatter.forPattern("dd-MM-yyyy HH:mm:ss");
DateTime dateTime = DateTime.parse("22-Sep-2018 8:15:43", formatter);
DateTime dateTimeZoned = dateTime.withZone(DateTimeZone.forID("Europe/London));
有关可用的时区ID的完整列表,请访问官方文档。
Apache Commons
Apache Commons是许多项目中使用的有用库。
要将这个库添加到您的项目中,可以使用Maven依赖项:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>{version}</version>
</dependency>
以下两种实现都接受一系列模式。这些方法将依次解析每个模式。如果没有模式与输入字符串匹配,ParseException则抛出a。
使用DateTimeConverter
DateTimeConverter dtc = new DateConverter();
dtc.setPatterns(new String[] { "yyyy-MM-dd", "yyyy-MM-dd hh:mm:ss" });
ConvertUtils.register(dtc, Date.class);
使用DateUtils
Date date = DateUtils.parseDate("22-Sep-2018", String[] {"dd-MM-yyyy HH:mm:ss", "dd-MM-yyyy"});
结论
我们已经介绍了将Java中的简单String转换为Date和Date-Time类的多种方法。其中一些方法利用了您的项目中可能已经拥有的第三方库,而另一些方法则利用了Java提供的API来完成。