在本文中,我们将带你了解Java8Date是否等效于具有多种解析器格式的Joda的DateTimeFormatterBuilder?在这篇文章中,我们将为您详细介绍Java8Date是否等效于具有多种
在本文中,我们将带你了解Java 8 Date是否等效于具有多种解析器格式的Joda的DateTimeFormatterBuilder?在这篇文章中,我们将为您详细介绍Java 8 Date是否等效于具有多种解析器格式的Joda的DateTimeFormatterBuilder?的方方面面,并解答java中的date类型常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的DateTimeFormatter LocalDateTime 工具类、DateTimeFormatter 格式化时间工具类 主要是与Date之间的转化、DateTimeFormatter与SimpleDateFormat、DateTimeFormatter和SimpleDateFormat有什么区别?。
本文目录一览:- Java 8 Date是否等效于具有多种解析器格式的Joda的DateTimeFormatterBuilder?(java中的date类型)
- DateTimeFormatter LocalDateTime 工具类
- DateTimeFormatter 格式化时间工具类 主要是与Date之间的转化
- DateTimeFormatter与SimpleDateFormat
- DateTimeFormatter和SimpleDateFormat有什么区别?
Java 8 Date是否等效于具有多种解析器格式的Joda的DateTimeFormatterBuilder?(java中的date类型)
我目前有一个Joda日期解析器,该解析器使用DateTimeFormatterBuilder和可能会收到的六种不同日期格式。
我正在迁移到Java 8的Date例程,但没有看到等效的例程。
我如何使用Java 8 Dates做类似的事情?
DateTimeParser[] parsers = { DateTimeFormat.forPattern( "yyyy/MM/dd HH:mm:ss.SSSSSS" ).getParser() , DateTimeFormat.forPattern( "yyyy-MM-dd HH:mm:ss" ).getParser() , DateTimeFormat.forPattern( "ddMMMyyyy:HH:mm:ss.SSS Z" ).getParser() , DateTimeFormat.forPattern( "ddMMMyyyy:HH:mm:ss.SSS" ).getParser() , DateTimeFormat.forPattern( "ddMMMyyyy:HH:mm:ss.SSSSSS" ).getParser() , DateTimeFormat.forPattern( "yyyy-MM-dd HH:mm:ss.SSS" ).getParser() };DateTimeFormatter dateTimeFormatterInput = new DateTimeFormatterBuilder() .append( null, parsers ).toFormatter();
答案1
小编典典没有直接的工具可以执行此操作,但是您可以使用可选部分。可选部分放在方括号内[]
。这允许整个字符串的分析部分丢失。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("" + "[yyyy/MM/dd HH:mm:ss.SSSSSS]" + "[yyyy-MM-dd HH:mm:ss[.SSS]]" + "[ddMMMyyyy:HH:mm:ss.SSS[ Z]]");
该格式化程序为您拥有的三个主要模式定义了3个主要的可选部分。它们每个都在其自己的可选部分中。
工作演示代码:
public static void main(String[] args) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("" + "[yyyy/MM/dd HH:mm:ss.SSSSSS]" + "[yyyy-MM-dd HH:mm:ss[.SSS]]" + "[ddMMMyyyy:HH:mm:ss.SSS[ Z]]" , Locale.ENGLISH); System.out.println(LocalDateTime.parse("2016/03/23 22:00:00.256145", formatter)); System.out.println(LocalDateTime.parse("2016-03-23 22:00:00", formatter)); System.out.println(LocalDateTime.parse("2016-03-23 22:00:00.123", formatter)); System.out.println(LocalDateTime.parse("23Mar2016:22:00:00.123", formatter)); System.out.println(LocalDateTime.parse("23Mar2016:22:00:00.123 -0800", formatter));}
DateTimeFormatter LocalDateTime 工具类
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalUnit;
import java.util.Calendar;
import java.util.Date;
public class DateTimeUtil {
public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HHmmss");
public static final DateTimeFormatter YEAR_MONTH_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM");
public static final DateTimeFormatter SHORT_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyMMdd");
public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
public static final DateTimeFormatter SHORT_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static final DateTimeFormatter LONG_DATETIME_FORMATTER = DateTimeFormatter
.ofPattern("yyyy-MM-dd HH:mm:ss SSS");
/**
* 获得当前日期
*
* @return
*/
public static Date getNow() {
Calendar cal = Calendar.getInstance();
return cal.getTime();
}
/**
* 获取一天的开始时间,2017,7,22 00:00
*
* @param time
* @return
*/
public static LocalDateTime getDayStart(LocalDateTime time) {
return time.withHour(0).withMinute(0).withSecond(0).withNano(0);
}
/**
* 获取一天的结束时间,2017,7,22 23:59:59.999999999
*
* @param time
* @return
*/
public static LocalDateTime getDayEnd(LocalDateTime time) {
return time.withHour(23).withMinute(59).withSecond(59).withNano(999999999);
}
/**
* 日期加上一个数,根据field不同加不同值,field为ChronoUnit.*
*
* @param time
* @param number
* @param field
* @return
*/
public static LocalDateTime plus(LocalDateTime time, long number, TemporalUnit field) {
return time.plus(number, field);
}
/**
* 日期减去一个数,根据field不同减不同值,field参数为ChronoUnit.*
*
* @param time
* @param number
* @param field
* @return
*/
public static LocalDateTime minu(LocalDateTime time, long number, TemporalUnit field) {
return time.minus(number, field);
}
/**
* 获取两个日期的差 field参数为ChronoUnit.*
*
* @param startTime
* @param endTime
* @param field 单位(年月日时分秒)
* @return
*/
public static long betweenTwoTime(LocalDateTime startTime, LocalDateTime endTime, ChronoUnit field) {
Period period = Period.between(LocalDate.from(startTime), LocalDate.from(endTime));
if (field == ChronoUnit.YEARS)
return period.getYears();
if (field == ChronoUnit.MONTHS)
return period.getYears() * 12 + period.getMonths();
return field.between(startTime, endTime);
}
/**
* 返回当前的日期
*/
public static LocalDate getCurrentLocalDate() {
return LocalDate.now(ZoneOffset.of("+8"));
}
/**
* 返回当前时间
*/
public static LocalTime getCurrentLocalTime() {
return LocalTime.now(ZoneOffset.of("+8"));
}
/**
* 返回当前日期时间
*/
public static LocalDateTime getCurrentLocalDateTime() {
return LocalDateTime.now(ZoneOffset.of("+8"));
}
/**
* yyyy-MM-dd
*/
public static String getCurrentDateStr() {
return LocalDate.now(ZoneOffset.of("+8")).format(DATE_FORMATTER);
}
/**
* yyMMdd
*/
public static String getCurrentShortDateStr() {
return LocalDate.now(ZoneOffset.of("+8")).format(SHORT_DATE_FORMATTER);
}
public static String getCurrentMonthStr() {
return LocalDate.now(ZoneOffset.of("+8")).format(YEAR_MONTH_FORMATTER);
}
/**
* yyyy-MM-dd HH:mm:ss
*/
public static String getCurrentDateTimeStr() {
return LocalDateTime.now(ZoneOffset.of("+8")).format(DATETIME_FORMATTER);
}
public static String getCurrentLongDateTimeStr() {
return LocalDateTime.now(ZoneOffset.of("+8")).format(LONG_DATETIME_FORMATTER);
}
/**
* yyMMddHHmmss
*/
public static String getCurrentShortDateTimeStr() {
return LocalDateTime.now(ZoneOffset.of("+8")).format(SHORT_DATETIME_FORMATTER);
}
/**
* HHmmss
*/
public static String getCurrentTimeStr() {
return LocalTime.now(ZoneOffset.of("+8")).format(TIME_FORMATTER);
}
public static String getCurrentDateStr(String pattern) {
return LocalDate.now(ZoneOffset.of("+8")).format(DateTimeFormatter.ofPattern(pattern));
}
public static String getCurrentDateTimeStr(String pattern) {
return LocalDateTime.now(ZoneOffset.of("+8")).format(DateTimeFormatter.ofPattern(pattern));
}
public static String getCurrentTimeStr(String pattern) {
return LocalTime.now(ZoneOffset.of("+8")).format(DateTimeFormatter.ofPattern(pattern));
}
public static LocalDate parseLocalDate(String dateStr, String pattern) {
return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(pattern));
}
public static LocalDateTime parseLocalDateTime(String dateTimeStr, String pattern) {
return LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ofPattern(pattern));
}
public static LocalTime parseLocalTime(String timeStr, String pattern) {
return LocalTime.parse(timeStr, DateTimeFormatter.ofPattern(pattern));
}
public static String formatLocalDate(LocalDate date, String pattern) {
return date.format(DateTimeFormatter.ofPattern(pattern));
}
public static String formatLocalDateTime(LocalDateTime datetime, String pattern) {
return datetime.format(DateTimeFormatter.ofPattern(pattern));
}
public static String formatLocalTime(LocalTime time, String pattern) {
return time.format(DateTimeFormatter.ofPattern(pattern));
}
public static LocalDate parseLocalDate(String dateStr) {
return LocalDate.parse(dateStr, DATE_FORMATTER);
}
public static LocalDateTime parseLocalDateTime(String dateTimeStr) {
return LocalDateTime.parse(dateTimeStr, DATETIME_FORMATTER);
}
public static LocalDateTime parseLongLocalDateTime(String longDateTimeStr) {
return LocalDateTime.parse(longDateTimeStr, LONG_DATETIME_FORMATTER);
}
public static LocalTime parseLocalTime(String timeStr) {
return LocalTime.parse(timeStr, TIME_FORMATTER);
}
public static String formatLocalDate(LocalDate date) {
return date.format(DATE_FORMATTER);
}
public static String formatLocalDateTime(LocalDateTime datetime) {
return datetime.format(DATETIME_FORMATTER);
}
public static String formatLocalTime(LocalTime time) {
return time.format(TIME_FORMATTER);
}
/**
* 日期相隔秒
*/
public static long periodHours(LocalDateTime startDateTime, LocalDateTime endDateTime) {
return Duration.between(startDateTime, endDateTime).get(ChronoUnit.SECONDS);
}
/**
* 日期相隔天数
*/
public static long periodDays(LocalDate startDate, LocalDate endDate) {
return startDate.until(endDate, ChronoUnit.DAYS);
}
/**
* 日期相隔周数
*/
public static long periodWeeks(LocalDate startDate, LocalDate endDate) {
return startDate.until(endDate, ChronoUnit.WEEKS);
}
/**
* 日期相隔月数
*/
public static long periodMonths(LocalDate startDate, LocalDate endDate) {
return startDate.until(endDate, ChronoUnit.MONTHS);
}
/**
* 日期相隔年数
*/
public static long periodYears(LocalDate startDate, LocalDate endDate) {
return startDate.until(endDate, ChronoUnit.YEARS);
}
/**
* 是否当天
*/
public static boolean isToday(LocalDate date) {
return getCurrentLocalDate().equals(date);
}
/**
* 获取当前毫秒数
*/
public static Long toEpochMilli(LocalDateTime dateTime) {
return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
/**
* 判断是否为闰年
*/
public static boolean isLeapYear(LocalDate localDate) {
return localDate.isLeapYear();
}
/**
* 将java.util.Date 转换为java8 的java.time.LocalDateTime,默认时区为东8区
*
* @param date
* @return
*/
public static LocalDateTime dateConvertToLocalDateTime(Date date) {
return date.toInstant().atOffset(ZoneOffset.of("+8")).toLocalDateTime();
}
/**
* 将java8 的 java.time.LocalDateTime 转换为 java.util.Date,默认时区为东8区
*
* @param localDateTime
* @return
*/
public static Date localDateTimeConvertToDate(LocalDateTime localDateTime) {
return Date.from(localDateTime.toInstant(ZoneOffset.of("+8")));
}
/**
* 毫秒转LocalDateTime
*
* @param milliseconds
* @return
*/
public static LocalDateTime millisecToDatetime(long milliseconds) {
Instant instant = Instant.ofEpochMilli(milliseconds);
return LocalDateTime.ofInstant(instant, ZoneOffset.of("+8"));
}
/**
* 将LocalDataTime转为毫秒数
*
* @param ldt
* @return
*/
public static long datatimeToTimestamp(LocalDateTime ldt) {
return ldt.toInstant(ZoneOffset.of("+8")).toEpochMilli();
}
/**
* 把long 转换成 日期 再转换成Date类型
*/
public static Date transferLongToDate(Long millSec) {
return new Date(millSec);
}
public static Date getDateBefore(int day) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, -day);
return calendar.getTime();
}
public static String getDateBeforeByLocalDateTime(int day) {
return dateConvertToLocalDateTime(getDateBefore(day)).format(DATETIME_FORMATTER);
}
public static String getDateBeforeBySimpleDateFormat(int day, String format) {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat(format);
calendar.add(Calendar.DATE, -day);
return sdf.format(calendar.getTime());
}
public static String getDateAfterBySimpleDateFormat(int day, String format) {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat(format);
calendar.add(Calendar.DATE, day);
return sdf.format(calendar.getTime());
}
public static void main(String[] args) {
System.out.println(getDateBeforeByLocalDateTime(23));
System.out.println(millisecToDatetime(1563867467000L).format(DATETIME_FORMATTER));
System.out.println(datatimeToTimestamp(getCurrentLocalDateTime()));
System.out.println(DateTimeUtil.getCurrentDateTimeStr("yyyy年MM月dd日 HH:mm:ss"));
System.out.println(DateTimeUtil.getCurrentDateTimeStr());
Date date = getNow();
LocalDateTime localDateTime = DateTimeUtil.dateConvertToLocalDateTime(date);
Long localDateTimeSecond = localDateTime.toEpochSecond(ZoneOffset.of("+8"));
Long dateSecond = date.toInstant().atOffset(ZoneOffset.of("+8")).toEpochSecond();
System.out.println("dateSecond:" + dateSecond);
System.out.println("localDateTimeSecond:" + localDateTimeSecond);
// 增加二十分钟
System.out.println(DateTimeUtil.formatLocalDateTime(
DateTimeUtil.plus(LocalDateTime.now(), 20, ChronoUnit.MINUTES), "yyyy年MM月dd日 HH:mm"));
// 增加两年
System.out.println(DateTimeUtil.formatLocalDateTime(DateTimeUtil.plus(LocalDateTime.now(), 2, ChronoUnit.YEARS),
"yyyy年MM月dd日 HH:mm"));
LocalDateTime start = LocalDateTime.of(1993, 10, 13, 11, 11);
LocalDateTime end = LocalDateTime.of(1994, 11, 13, 13, 13);
System.out.println("年:" + DateTimeUtil.betweenTwoTime(start, end, ChronoUnit.YEARS));
System.out.println("月:" + DateTimeUtil.betweenTwoTime(start, end, ChronoUnit.MONTHS));
System.out.println("日:" + DateTimeUtil.betweenTwoTime(start, end, ChronoUnit.DAYS));
System.out.println("半日:" + DateTimeUtil.betweenTwoTime(start, end, ChronoUnit.HALF_DAYS));
System.out.println("小时:" + DateTimeUtil.betweenTwoTime(start, end, ChronoUnit.HOURS));
System.out.println("分钟:" + DateTimeUtil.betweenTwoTime(start, end, ChronoUnit.MINUTES));
System.out.println("秒:" + DateTimeUtil.betweenTwoTime(start, end, ChronoUnit.SECONDS));
System.out.println("毫秒:" + DateTimeUtil.betweenTwoTime(start, end, ChronoUnit.MILLIS));
// =============================================================================================
/*
* 年:1 月:13 日:396 半日:792 小时:9506 分钟:570362 秒:34221720 毫秒:34221720000
*/
}
}
DateTimeFormatter 格式化时间工具类 主要是与Date之间的转化
// 01. java.util.Date --> java.time.LocalDateTime
public void DateToLocalDateTime() {
java.util.Date date = new java.util.Date();
Instant instant = date.toInstant();
ZoneId zone = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
}
// 02. java.util.Date --> java.time.LocalDate
public void DateToLocalDate() {
java.util.Date date = new java.util.Date();
Instant instant = date.toInstant();
ZoneId zone = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
LocalDate localDate = localDateTime.toLocalDate();
}
// 03. java.util.Date --> java.time.LocalTime
public void DateToLocalTime() {
java.util.Date date = new java.util.Date();
Instant instant = date.toInstant();
ZoneId zone = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
LocalTime localTime = localDateTime.toLocalTime();
}
// 04. java.time.LocalDateTime --> java.util.Date
public void LocalDateTimeToDate() {
LocalDateTime localDateTime = LocalDateTime.now();
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDateTime.atZone(zone).toInstant();
java.util.Date date = Date.from(instant);
}
// 05. java.time.LocalDate --> java.util.Date
public void LocalDateToDate() {
LocalDate localDate = LocalDate.now();
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
java.util.Date date = Date.from(instant);
}
// 06. java.time.LocalTime --> java.util.Date
public void LocalTimeToDate() {
LocalTime localTime = LocalTime.now();
LocalDate localDate = LocalDate.now();
LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDateTime.atZone(zone).toInstant();
java.util.Date date = Date.from(instant);
}
DateTimeFormatter与SimpleDateFormat
日期格式化类:DateTimeFormatter与SimpleDateFormat
一、SimpleDateFormat类
- SimpleDateFormat是用于以对语言环境敏感的方式格式化和解析日期的具体类。
- SimpleDateFormat类的构造方法
NO | 构造器 | 描述 |
---|---|---|
1 | SimpleDateFormat() | SimpleDateFormat使用默认FORMAT语言环境的默认模式和日期格式符号 构造一个。 |
2 | SimpleDateFormat(Stringpattern) | SimpleDateFormat使用给定的模式和默认FORMAT语言环境的默认日期格式符号 构造一个。 |
3 | SimpleDateFormat(Stringpattern,DateFormatSymbolsformatSymbols) | SimpleDateFormat使用给定的模式和日期格式符号构造一个。 |
4 | SimpleDateFormat(Stringpattern,Localelocale) | SimpleDateFormat使用给定语言环境和给定语言环境的默认日期格式符号构造一个。 |
SimpleDateFormat为什么不是线程安全的?
- SimpleDateFormat类的方法没有使用synchronized来给共享变量加锁。
- SimpleDateFormat继承于DateFormat,下面我们看看我们用来格式化的format()方法的部分源码
- DateFormat.java
public final String format(Date date)
{
return format(date, new StringBuffer(),
DontCareFieldPosition.INSTANCE).toString();
}
public abstract StringBuffer format(Date date, StringBuffer toAppendTo,
FieldPosition fieldPosition);
- SimpleDateFormat.java
@Override
public StringBuffer format(Date date, StringBuffer toAppendTo,
FieldPosition pos)
{
// 如此轻易地使用内部变量,肯定不能线程安全
// 线程都对pos进行写操作,必然会影响其他线程的读操作
pos.beginIndex = pos.endIndex = 0;
return format(date, toAppendTo, pos.getFieldDelegate());
}
private StringBuffer format(Date date, StringBuffer toAppendTo,
FieldDelegate delegate) {
// Convert input date to time field list
// 这里已经彻底毁坏线程的安全性
calendar.setTime(date);
boolean useDateFormatSymbols = useDateFormatSymbols();
for (int i = 0; i < compiledPattern.length; ) {
int tag = compiledPattern[i] >>> 8;
int count = compiledPattern[i++] & 0xff;
if (count == 255) {
count = compiledPattern[i++] << 16;
count |= compiledPattern[i++];
}
switch (tag) {
case TAG_QUOTE_ASCII_CHAR:
toAppendTo.append((char)count);
break;
case TAG_QUOTE_CHARS:
toAppendTo.append(compiledPattern, i, count);
i += count;
break;
default:
subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
break;
}
}
return toAppendTo;
}
看源码不用全部看,只需要看重点,不然你会很难受,很耗费时间。SimpleDateFormat类中的format方法的一段代码calendar.setTime(date);
,从这我们可以看出来,如果我们把SimpleDateFormat定义成static成员变量,那么多个thread之间会共享这个SimpleDateFormat对象, 所以Calendar对象也会被共享。那么当有线程A,B操作该方法时,A线程已经给Calendar对象setTime了,但是这时A线程让出了cpu被B线程抢占了,这时B线程在给Calendar对象setTime一个值,然后A线程获得cpu处理,这时A线程以为使用的是它给setTime的值,其实这里的值已经被B线程更改了。这里就会出现线程不安全,因为这里的处理对象都被两个或者更多的线程公用,就会出现线程不安全,所以我们在开发时,尽量使用内部变量,不共享的变量。 3. 实例
package www.com.lining.dateformate;
import java.text.SimpleDateFormat;
import java.util.Locale;
public class DateTimeFormateTest1 {
private static SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
private static String date[] = { "01-Jan-1999", "09-Jan-2000", "08-Jan-2001", "07-Jan-2002", "06-Jan-2003",
"05-Jan-2004", "04-Jan-2005", "03-Jan-2006", "02-Jan-2007" };
public static void main(String[] args) {
for (int i = 0; i < date.length; i++) {
final int temp = i;
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
String str1 = date[temp];
String str2 = sdf.format(sdf.parse(str1));
System.out.println(Thread.currentThread().getName() + ", " + str1 + "," + str2);
if (!str1.equals(str2)) {
throw new RuntimeException(
Thread.currentThread().getName() + ", Expected " + str1 + " but got " + str2);
}
}
} catch (Exception e) {
throw new RuntimeException("parse failed", e);
}
}
}).start();
}
}
}
- 输出
- 一定要注意cpu的使用权都是需要去抢占的,所以就会出现多线程情况下,出现线程安全问题。
SimpleDateFormat线程不安全的解决方法
- 将SimpleDateFormat定义成局部变量,每次使用时在new 对象。但是每调用一次方法就会创建一个SimpleDateFormat对象,方法结束又要作为垃圾回收,很浪费资源。
- 加一把线程同步锁:synchronized(lock)
public class SyncDateFormatTest {
private static SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
private static String date[] = { "01-Jan-1999", "01-Jan-2000", "01-Jan-2001" };
public static void main(String[] args) {
for (int i = 0; i < date.length; i++) {
final int temp = i;
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
synchronized (sdf) {
String str1 = date[temp];
Date date = sdf.parse(str1);
String str2 = sdf.format(date);
System.out.println(Thread.currentThread().getName() + ", " + str1 + "," + str2);
if(!str1.equals(str2)){
throw new RuntimeException(Thread.currentThread().getName()
+ ", Expected " + str1 + " but got " + str2);
}
}
}
} catch (Exception e) {
throw new RuntimeException("parse failed", e);
}
}
}).start();
}
}
}
缺点是:每次都要等该锁释放其他的线程才能使用,性能差。 3. 使用ThreadLocal类
- 直接继承与Object类,该类提供了线程局部变量,这些变量不同于他们的普通对应物,因为访问某个变量的每个线程都有自己的局部变量,它独立于变量的初始化副本。
- 每个线程都将拥有自己的SimpleDateFormat对象副本。
public class DateUtil {
private static ThreadLocal<SimpleDateFormat> local = new ThreadLocal<SimpleDateFormat>();
public static Date parse(String str) throws Exception {
SimpleDateFormat sdf = local.get();
if (sdf == null) {
sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
local.set(sdf);
}
return sdf.parse(str);
}
public static String format(Date date) throws Exception {
SimpleDateFormat sdf = local.get();
if (sdf == null) {
sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
local.set(sdf);
}
return sdf.format(date);
}
}
public class ThreadLocalDateFormatTest {
private static String date[] = { "01-Jan-1999", "01-Jan-2000", "01-Jan-2001" };
public static void main(String[] args) {
for (int i = 0; i < date.length; i++) {
final int temp = i;
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
String str1 = date[temp];
Date date = DateUtil.parse(str1);
String str2 = DateUtil.format(date);
System.out.println(str1 + "," + str2);
if(!str1.equals(str2)){
throw new RuntimeException(Thread.currentThread().getName()
+ ", Expected " + str1 + " but got " + str2);
}
}
} catch (Exception e) {
throw new RuntimeException("parse failed", e);
}
}
}).start();
}
}
}
这样每个线程都有自己的副本对象SimpleDateFormat,所以每次不同的线程调用的都是自己的副本对象,不会改变其他线程的对象的。
二、DateTimeFormatter类
- jdk1.8中新增了 LocalDate 与 LocalDateTime等类来解决日期处理方法,同时引入了一个新的类DateTimeFormatter来解决日期格式化问题。
- LocalDateTime,DateTimeFormatter两个类都没有线程问题,只要你自己不把它们创建为共享变量就没有线程问题。
- 可以使用Instant代替 Date,LocalDateTime代替 Calendar,DateTimeFormatter 代替 SimpleDateFormat。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd");
LocalDate date = LocalDate.parse("2017 06 17", formatter);
System.out.println(formatter.format(date));
- DateTimeFormatter.ofPattern(pattern)的实现
public static DateTimeFormatter ofPattern(String pattern) {
return new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
}
public final class DateTimeFormatterBuilder extends Object
- TimeFormatterBuilder():用于创建日期时间格式化程序的生成器。
- TimeFormatterBuilder().appendPattern(pattern):将指定模式定义的元素追加到构建器,返回TimeFormatterBuilder对象。
- toFormatter():通过DateTimeFormatter使用默认语言环境创建来完成此构建器,获取DateTimeFormatter对象。
- 模式基于字母和符号的简单序列。模式用于使用ofPattern(String)和ofPattern(String, Locale)方法创建格式化程序 。例如, "d MMM uuuu"将2011-12-03的格式设置为“ 2011年12月3日”。从模式创建的格式化程序可以根据需要多次使用,它是不可变的并且是线程安全的。 例如:
LocalDate日期= LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(“ yyyy MM dd”);
字符串文本= date.format(formatter);
LocalDate parsedDate = LocalDate.parse(text,formatter);
- 其中的LocalDate和LocalDateTime都可以去查看jdk1.8往上的版本api去学习。
DateTimeFormatter和SimpleDateFormat有什么区别?
DateTimeFormatter和SimpleDateFormat都是用于日期时间格式化和解析的类,但它们有以下几个区别:
1.线程安全性:
- DateTimeFormatter 是线程安全的,可以在多线程环境下共享和重用。
- SimpleDateFormat 不是线程安全的,不建议在多线程环境中共享和重用,除非使用适当的同步措施。
2.API 设计:
- DateTimeFormatter 是 Java 8 中引入的,并遵循了新的日期时间 API 的设计原则,提供了一致且易于使用的方法,支持更多的日期时间模式符号和灵活的格式化选项。
- SimpleDateFormat 是早期的 Java 日期时间 API(java.util.Date) 中的类,使用较老的设计风格,并且其 API 比较有限。
3.底层实现:
- DateTimeFormatter 使用基于解析器和格式化器的模型,底层使用 java.time.format.DateTimeFormatterBuilder 类来构建格式化模式。
- SimpleDateFormat 使用基于模式字符串的方式进行格式化和解析,底层使用 java.text.SimpleDateFormat 类。
以下是使用DateTimeFormatter和SimpleDateFormat的代码示例:
使用DateTimeFormatter示例代码:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class DateTimeFormatterExample {
public static void main(String[] args) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 格式化日期时间
LocalDateTime now = LocalDateTime.now();
String formattedDateTime = formatter.format(now);
System.out.println("格式化后的日期时间:" + formattedDateTime);
// 解析日期时间
String dateTimeString = "2023-07-03 12:30:45";
LocalDateTime parsedDateTime = LocalDateTime.parse(dateTimeString, formatter);
System.out.println("解析后的日期时间:" + parsedDateTime);
}
}
打印结果:
格式化后的日期时间:2023-07-03 15:34:58
解析后的日期时间:2023-07-03T12:30:45
使用SimpleDateFormat示例代码:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatExample {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 格式化日期时间
Date now = new Date();
String formattedDateTime = sdf.format(now);
System.out.println("格式化后的日期时间:" + formattedDateTime);
// 解析日期时间
String dateTimeString = "2023-07-03 12:30:45";
try {
Date parsedDateTime = sdf.parse(dateTimeString);
System.out.println("解析后的日期时间:" + parsedDateTime);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
打印结果:
格式化后的日期时间:2023-07-03 15:38:33
解析后的日期时间:Mon Jul 03 12:30:45 CST 2023
在这个示例中,我们分别使用了DateTimeFormatter和SimpleDateFormat来格式化和解析日期时间。它们的用法非常相似,但是需要注意的是,DateTimeFormatter是线程安全的,可以在多线程环境下共享和重用;而SimpleDateFormat不是线程安全的,不建议在多线程环境中共享和重用。
今天关于Java 8 Date是否等效于具有多种解析器格式的Joda的DateTimeFormatterBuilder?和java中的date类型的分享就到这里,希望大家有所收获,若想了解更多关于DateTimeFormatter LocalDateTime 工具类、DateTimeFormatter 格式化时间工具类 主要是与Date之间的转化、DateTimeFormatter与SimpleDateFormat、DateTimeFormatter和SimpleDateFormat有什么区别?等相关知识,可以在本站进行查询。
本文标签: