Java8之前的版本,格式化日期常使用SimpleDateFormat,但这个类并不是线程安全的,通常要用作局部变量或者使用ThreadLocal包装。或者使用额外的joda time 依赖来对日期进行操作。
但是到了Java8,这类烦恼都没有了,全新的日期api可以快速实现日期格式化。
1.日期格式化-字符串转换成日期
/**
* 将不带时间的日期字符串转为日期
*
* @param dateStr 字符串
* @param format 该字符串对应的日期格式,必须一一对应,否则返回null
* @return 日期对象,当格式不匹配会返回null
*/
public static Date toDate(String dateStr, String format) {
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(format);
try {
LocalDate localDate = LocalDate.parse(dateStr, inputFormatter);
ZoneId defaultZoneId = ZoneId.systemDefault();
return Date.from(localDate.atStartOfDay(defaultZoneId).toInstant());
} catch (Exception e) {
return null;
}
}
/**
* 将带时间的格式转换为日期
* @param dateStr 字符串
* @param format 该字符串对应的日期时间格式,必须一一对应,否则返回null
* @return 日期对象,当格式不匹配会返回null
*/
public static Date toDateTime(String dateStr, String format) {
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(format);
try {
LocalDateTime localDateTime = LocalDateTime.parse(dateStr, inputFormatter);
ZoneId defaultZoneId = ZoneId.systemDefault();
ZonedDateTime zdt = localDateTime.atZone(defaultZoneId);
return Date.from(zdt.toInstant());
} catch (Exception e) {
return null;
}
}
测试代码及输出:
String str4 = "2022-08-16";
System.out.println(toDate(str4, "yyyy-MM-dd"));
String str5 = "2022-08-16 12:05:24";
System.out.println(toDateTime(str5, "yyyy-MM-dd HH:mm:ss"));
Tue Aug 16 00:00:00 CST 2022
Tue Aug 16 12:05:24 CST 2022
2.日期字符串转换
/**
* 不带时分秒的日期字符串转化
*
* @param input 输入的日期
* @param inputFormat 输入日期的格式
* @param outputFormat 输出日期的格式
* @return 输出的日期,不带时分秒
*/
public static String formattedDate(String input, String inputFormat, String outputFormat) {
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(inputFormat);
LocalDate localDate = LocalDate.parse(input, inputFormatter);
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern(outputFormat);
return localDate.format(outputFormatter);
}
测试代码及输出:
String output1 = formattedDate("2019年07月15日", "yyyy年MM月dd日", "yyyy-MM-dd");
String output2 = formattedDate("2019/07/16", "yyyy/MM/dd", "yyyy-MM-dd");
String output3 = formattedDate("2019-07-16", "yyyy-MM-dd", "yyyy/MM/dd");
System.out.println(output1);
System.out.println(output2);
System.out.println(output3);
2019-07-15
2019-07-16
2019/07/16
注意,使用LocalDate + DateTimeFormatter仅仅能够转换不带时分秒的日期格式!
3.带时间日期字符串转换
/**
* 带时分秒的日期字符串转换
*
* @param input 输入的日期
* @param inputFormat 输入日期的格式
* @param outputFormat 输出日期的格式
* @return 输出指定格式的日期,可以带时分秒,也可以不带
*/
public static String formattedDateTime(String input, String inputFormat, String outputFormat) {
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(inputFormat);
LocalDateTime localDateTime = LocalDateTime.parse(input, inputFormatter);
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern(outputFormat);
return localDateTime.format(outputFormatter);
}
测试代码及输出:
String output1 = formattedDateTime("20190713000000", "yyyyMMddHHmmss", "yyyy-MM-dd");
String output2 = formattedDateTime("20190713000000", "yyyyMMddHHmmss", "yyyy-MM-dd HH:mm:ss");
String output3 = formattedDateTime("2019年07月14日00时00分00秒", "yyyy年MM月dd日HH时mm分ss秒",
"yyyy/MM/dd");
String output4 = formattedDateTime("2019年07月14日00时00分00秒", "yyyy年MM月dd日HH时mm分ss秒",
"yyyyMMddHHmmss");
String output5 = formattedDateTime("2019-07-15 00:00:00", "yyyy-MM-dd HH:mm:ss", "yyyyMMdd");
String output6 = formattedDateTime("2019-07-15 00:00:00", "yyyy-MM-dd HH:mm:ss",
"yyyy年MM月dd日HH时mm分ss");
System.out.println(output1);
System.out.println(output2);
System.out.println(output3);
System.out.println(output4);
System.out.println(output5);
System.out.println(output6);
2019-07-13
2019-07-13 00:00:00
2019/07/14
20190714000000
20190715
2019年07月15日00时00分00
注意:使用LocalDateTime + DateTimeFormatter 可以将指定日期类型转换成任意形式的日期类型。
4.Date和LocalDateTime互转
/**
* LocalDateTime -> Date
*/
public static Date toDate(LocalDateTime localDateTime) {
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = localDateTime.atZone(zoneId);
return Date.from(zdt.toInstant());
}
/**
* Date -> LocalDateTime
*/
public static LocalDateTime toLocalDateTime(Date date) {
Instant instant = date.toInstant();
ZoneId zoneId = ZoneId.systemDefault();
return instant.atZone(zoneId).toLocalDateTime();
}
5.Date和LocalDate互转
/**
* Date -> LocalDateTime
*/
public static LocalDateTime toLocalDateTime(Date date) {
Instant instant = date.toInstant();
ZoneId zoneId = ZoneId.systemDefault();
return instant.atZone(zoneId).toLocalDateTime();
}
/**
* LocalDate -> Date
*/
public static Date toDate(LocalDate localDate) {
ZoneId defaultZoneId = ZoneId.systemDefault();
return Date.from(localDate.atStartOfDay(defaultZoneId).toInstant());
}
6.为什么推荐使用DateTimeFormatter而不是SimpleDateFormat
不仅仅安全,而且更加严格。
举例:当日期格式为 yyyy-MM-dd,输入日期为2022-8-16,对于SimpleDateFormat即使设置强校验模式,依然能够转换成功,但是对于DateTimeFormatter则会转换失败
String str = "2022-8-16";
System.out.println(toDate(str, "yyyy-MM-dd"));
String str2 = "2022-8-16";
System.out.println(toDateUseSdf(str2, "yyyy-MM-dd"));
public static Date toDateUseSdf(String dateStr, String format) {
SimpleDateFormat sdf = new SimpleDateFormat(format);
sdf.setLenient(true);
try {
return sdf.parse(dateStr);
} catch (Exception e) {
return null;
}
}
分别输出null和 Tue Aug 16 00:00:00 CST 2022