概述
传统时间格式化的线程安全问题
public class TestSimpleDateFormat {
@Test
public void test01(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Callable<Date> task = new Callable<Date>() {
@Override
public Date call() throws Exception {
return sdf.parse("20161218");
}
};
ExecutorService pool = Executors.newFixedThreadPool(10);
List<Future<Date>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(pool.submit(task));
}
for (Future<Date> future : results) {
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
pool.shutdown();
}
}
加锁:
public class DateFormatThreadLocal {
private static final ThreadLocal<DateFormat> df = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd"));
public static Date convert(String source) throws ParseException {
return df.get().parse(source);
}
}
@Test
public void test02(){
Callable<Date> task = () -> DateFormatThreadLocal.convert("20161218");
ExecutorService pool = Executors.newFixedThreadPool(10);
ArrayList<Future<Date>> result = new ArrayList<>();
for (int i = 0; i < 10; i++) {
result.add(pool.submit(task));
}
for (Future<Date> future : result) {
try {
System.out.println(future.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
pool.shutdown();
}
java8:localDate DateTimeFormatter----线程安全
@Test
public void test03(){
DateTimeFormatter dtf =DateTimeFormatter.ofPattern("yyyyMMdd");
Callable<LocalDate> task = new Callable<LocalDate>() {
@Override
public LocalDate call() throws Exception {
return LocalDate.parse("20161218",dtf);
}
};
ExecutorService pool = Executors.newFixedThreadPool(10);
List<Future<LocalDate>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(pool.submit(task));
}
for (Future<LocalDate> future : results) {
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
pool.shutdown();
}
一、本地时间
使用LocalDate(表示日期) LocalTime(表示时间) LocalDateTime(时间日期)
- 这三个类的实例是不可变的对象,分别表示使用ISO-8601日历系统的日期时间日期和时间.他们提供了简单的日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息
- ISO-8601日历系统是国际标准化组织指定的现代公民的日期和时间的表示法
常用方法:
方法名 | 返回值类型 | 解释 |
---|---|---|
now( ) | LocalDateTime | 从默认时区的系统时钟获取当前日期 |
of(int year, int month, int dayOfMonth, int hour, int minute, int second) | LocalDateTime | 从年,月,日,小时,分钟和秒获得 LocalDateTime的实例,将纳秒设置为零 |
plus(long amountToAdd, TemporalUnit unit) | LocalDateTime | 返回此日期时间的副本,并添加指定的数量 |
get(TemporalField field) | int | 从此日期时间获取指定字段的值为 int |
public class TestLocalDateTime {
// 1:LocalDate LocalTime LocalDateTime
@Test
public void test1(){
// 获取当前系统时间 now
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);// 2022-06-15T16:02:03.464
// 指定时间 of
LocalDateTime of = LocalDateTime.of(2015, 10, 10, 13, 22, 33);
System.out.println(of);// 2015-10-10T13:22:33
// 加时间 plus
LocalDateTime time = localDateTime.plusYears(2);
System.out.println(time);// 2024-06-15T16:02:03.464
// 减时间 minus
LocalDateTime time1 = localDateTime.minusMonths(2);
// 获取指定的你年月日时分秒... get
System.out.println(localDateTime.getYear());//2022
System.out.println(localDateTime.getMonthValue());// 6
System.out.println(localDateTime.getDayOfMonth());// 15
System.out.println(localDateTime.getHour());// 16
System.out.println(localDateTime.getMinute()); // 2
System.out.println(localDateTime.getSecond());// 3
}
}
二、Instant 时间戳
Instant:以 Unix 元年 1970-01-01 00:00:00 到某个时间之间的毫秒值
// 2:Instant 时间戳 (以Unix元年 1970/1/1 00:00:00 到某个时间之间的毫秒值)
@Test
public void test2(){
// 获取当前时间戳 默认获取 UTC 时区 (UTC:世界协调时间)
Instant now = Instant.now();
System.out.println(now);// 2022-06-15T08:04:42.444Z(默认获取的UTC时区)
// 带偏移量的时间日期 (如:UTC + 8)
OffsetDateTime odt = now.atOffset(ZoneOffset.ofHours(8));
System.out.println(odt);// 2022-06-15T16:04:42.444+08:00
//转换成对应的毫秒值
long epochMilli = now.toEpochMilli();
System.out.println(epochMilli);// 1655280282444
//构建时间戳(相较于元年进行的运算)
Instant instant = Instant.ofEpochSecond(60);
System.out.println(instant);// 1970-01-01T00:01:00Z
}
三、计算时间之间的间隔
Duration:计算两个时间之间的间隔
Period:计算两个日期之间的间隔
@Test
public void test3(){
Instant ins1= Instant.now();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Instant ins2= Instant.now();
Duration duration = Duration.between(ins1, ins2);
System.out.println(duration);//PT1.012S
System.out.println(duration.getSeconds());// 秒 1
System.out.println(duration.toMillis());// 毫秒 1001
}
@Test
public void test4() {
LocalTime localTime = LocalTime.now();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LocalTime localTime2 = LocalTime.now();
System.out.println(Duration.between(localTime,localTime2).toMillis());//1006
}
@Test
public void test5(){
LocalDate ld1 = LocalDate.of(2020,1,1);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LocalDate ld2 = LocalDate.now();
Period period = Period.between(ld1, ld2);
System.out.println(period);//P1Y3M9D
System.out.println(period.getYears());//1
System.out.println(period.getMonths());//3
System.out.println(period.getDays());//9
}
四、时间校正器
日期的操纵:
- TemporalAdjuster:时间校正器(例如:将日期调整到下个周日等操作)
- TemporalAdjusters:该类通过静态方法提供了大量用TemporalAdjuster的实现
// TemporalAdjuster 时间校正器
@Test
public void test6(){
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);//2022-06-15T16:12:20.108
// //指定日期时间中的 年 月 日 ... .withXXX
LocalDateTime ldt2 = ldt.withDayOfMonth(5);
System.out.println(ldt2);//2022-06-05T16:12:20.108
//指定时间校正器 (指定为下一个周日)
LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(ldt3);// 2022-06-19T16:12:20.108
//自定义时间校正器 (指定下一个工作日)
LocalDateTime time = ldt.with((l) -> {
LocalDateTime ldt4 = (LocalDateTime) l;
DayOfWeek dow = ldt4.getDayOfWeek();//获取周几
if (dow.equals(DayOfWeek.FRIDAY)) {
return ldt4.plusDays(3);
} else if (dow.equals(DayOfWeek.SATURDAY)) {
return ldt4.plusDays(2);
} else {
return ldt4.plusDays(1);
}
});
System.out.println(time);//2022-06-16T16:12:20.108
}
五、时间格式化和时区的处理
DateTimeFormatter:格式化时间 / 日期
@Test
public void test7(){
//默认格式化
DateTimeFormatter dtf =DateTimeFormatter.ISO_DATE;
LocalDateTime ldt = LocalDateTime.now();
String strDate = ldt.format(dtf);
System.out.println(strDate);//2022-06-15
// 自定义格式化
DateTimeFormatter dtf2= DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
String strDate2 = dtf2.format(ldt);
System.out.println(strDate2);//2022年06月15日 16:19:02
//解析
LocalDateTime newDate = ldt.parse(strDate2,dtf2);
System.out.println(newDate);// 2022-06-15T16:19:02
}
时区的处理
ZonedDate、ZonedTime、ZonedDateTime
其中每个时区都对应着ID,地区ID都为"{区域}/{城市}"的格式 [ 例如:Asia/Shanghai ]
- ZoneId:该类包含了所有的时区信息
- getAvailableZoneIds:可以获取所有时区的信息
- of(id):用指定的时区信息获取ZoneId对象
// 时区的处理
@Test
public void test8(){
// 获取所有的时区
Set<String> ids = ZoneId.getAvailableZoneIds();
ids.forEach(System.out::println);
// 指定时区
LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Europe/Tallinn"));
System.out.println(ldt);//2022-06-15T11:22:49.753
// 在已构建好的日期时间上指定时区
LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
ZonedDateTime zdt = now.atZone(ZoneId.of("Asia/Shanghai"));
System.out.println(zdt);// 2022-06-15T16:22:49.757+08:00[Asia/Shanghai]
}
JAVA 8 时间工具类
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
/**
* JAVA 8 时间工具类
*
* @author bood
* @since 2020/9/25
*/
public class DateTimeUtils {
/**
* 格式:yyyy-MM-dd HH:mm:ss
*/
public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
/**
* 格式:yyyy-MM-dd
*/
public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
/**
* 格式:HH:mm:ss
*/
public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
private DateTimeUtils() {
}
// ------------------------------------------- 获取时间 -------------------------------------------
/**
* 返回 当前时间的(yyyy-MM-dd HH:mm:ss)
*
* @return yyyy-MM-dd HH:mm:ss
*/
public static LocalDateTime get() {
return LocalDateTime.now();
}
/**
* 返回 当前时间的(yyyy-MM-dd)
*
* @return yyyy-MM-dd
*/
public static LocalDate getCurrentLocalDate() {
return LocalDate.now();
}
/**
* 返回 当前时间的(HH:mm:ss)
*
* @return HH:mm:ss
*/
public static LocalTime getCurrentLocalTime() {
return LocalTime.now();
}
// ------------------------------------------- 时间格式化 -------------------------------------------
/**
* <p>
* yyyy-MM-dd HH:mm:ss 转 LocalDateTime 类型
* </p>
*
* @param dateTimeStr: yyyy-MM-dd HH:mm:ss
* @return:java.time.LocalDateTime
* @author:bood
* @date:2020/9/25
*/
public static LocalDateTime parseLocalDateTime(String dateTimeStr) {
return LocalDateTime.parse(dateTimeStr, DATETIME_FORMATTER);
}
/**
* <p>
* yyyy-MM-dd 转 LocalDate 类型
* </p>
*
* @param dateStr: yyyy-MM-dd
* @return:java.time.LocalDate
* @author:bood
* @date:2020/9/25
*/
public static LocalDate parseLocalDate(String dateStr) {
return LocalDate.parse(dateStr, DATE_FORMATTER);
}
/**
* <p>
* HH:mm:ss 转 LocalTime 类型
* </p>
*
* @param timeStr: HH:mm:ss
* @return:java.time.LocalTime
* @author:bood
* @date:2020/9/25
*/
public static LocalTime parseLocalTime(String timeStr) {
return LocalTime.parse(timeStr, TIME_FORMATTER);
}
/**
* <p>
* LocalDateTime 转 yyyy-MM-dd HH:mm:ss
* </p>
*
* @param datetime: LocalDateTime
* @return:java.lang.String
* @author:bood
* @date:2020/9/25
*/
public static String formatLocalDateTime(LocalDateTime datetime) {
return datetime.format(DATETIME_FORMATTER);
}
/**
* <p>
* LocalDate 转 yyyy-MM-dd
* </p>
*
* @param date: LocalDate
* @return:java.lang.String
* @author:bood
* @date:2020/9/25
*/
public static String formatLocalDate(LocalDate date) {
return date.format(DATE_FORMATTER);
}
/**
* <p>
* LocalTime 转 HH:mm:ss
* </p>
*
* @param time: LocalTime
* @return:java.lang.String
* @author:bood
* @date:2020/9/25
*/
public static String formatLocalTime(LocalTime time) {
return time.format(TIME_FORMATTER);
}
// ------------------------------------------- 时间计算 -------------------------------------------
/**
* <p>
* 当前时间延期几天
* </p>
*
* @param days: 天数
* @return:java.time.LocalDateTime
* @author:bood
* @date:2020/9/25
*/
public static LocalDateTime plusDays(int days) {
return get().plusDays(days);
}
/**
* <p>
* 日期相隔天数
* </p>
*
* @param startDateInclusive: 开始时间
* @param endDateExclusive: 结束时间
* @return:int
* @author:bood
* @date:2020/9/25
*/
public static int periodDays(LocalDate startDateInclusive, LocalDate endDateExclusive) {
return Period.between(startDateInclusive, endDateExclusive).getDays();
}
/**
* <p>
* 日期相隔小时
* </p>
*
* @param startInclusive: 开始时间
* @param endExclusive: 结束时间
* @return:long
* @author:bood
* @date:2020/9/25
*/
public static long durationHours(Temporal startInclusive, Temporal endExclusive) {
return Duration.between(startInclusive, endExclusive).toHours();
}
/**
* <p>
* 日期相隔分钟
* </p>
*
* @param startInclusive: 开始时间
* @param endExclusive: 结束时间
* @return:long
* @author:bood
* @date:2020/9/25
*/
public static long durationMinutes(Temporal startInclusive, Temporal endExclusive) {
return Duration.between(startInclusive, endExclusive).toMinutes();
}
/**
* <p>
* 日期相隔毫秒数
* </p>
*
* @param startInclusive: 开始时间
* @param endExclusive: 结束时间
* @return:long
* @author:bood
* @date:2020/9/25
*/
public static long durationMillis(Temporal startInclusive, Temporal endExclusive) {
return Duration.between(startInclusive, endExclusive).toMillis();
}
/**
* <p>
* 返回 指定年份的(yyyy-MM-dd HH:mm:ss)
* </p>
*
* @param year: 年份
* @return:java.time.LocalDateTime
* @author:bood
* @date:2020/9/25
*/
public static LocalDateTime withYear(int year) {
return get().withYear(year);
}
/**
* <p>
* 返回 指定年份的 第一天时间
* </p>
*
* @param year: 年份
* @return:java.time.LocalDateTime
* @author:bood
* @date:2020/9/25
*/
public static LocalDateTime firstDayOfThisYear(int year) {
return withYear(year).with(TemporalAdjusters.firstDayOfYear()).with(LocalTime.MIN);
}
/**
* <p>
* 返回 指定年份的 最末天时间
* </p>
*
* @param year: 年份
* @return:java.time.LocalDateTime
* @author:bood
* @date:2020/9/25
*/
public static LocalDateTime lastDayOfThisYear(int year) {
return withYear(year).with(TemporalAdjusters.lastDayOfYear()).with(LocalTime.MAX);
}
/**
* <p>
* 返回 指定年份的 第一天时间
* </p>
*
* @param year: 年份
* @return:java.lang.String
* @author:bood
* @date:2020/9/25
*/
public static String getFirstDayOfThisDate(int year) {
LocalDateTime firstDayOfThisYear = firstDayOfThisYear(year);
return DATETIME_FORMATTER.format(firstDayOfThisYear);
}
/**
* <p>
* 返回 指定年份的 最末天时间
* </p>
*
* @param year: 年份
* @return:java.lang.String
* @author:bood
* @date:2020/9/25
*/
public static String getLastDayOfThisDate(int year) {
LocalDateTime lastDayOfThisYear = lastDayOfThisYear(year);
return DATETIME_FORMATTER.format(lastDayOfThisYear);
}
/**
* <p>
* 获取本月的第一天(当前时间)
* </p>
*
* @return:java.lang.String
* @author:bood
* @date:2020/9/25
*/
public static String getFirstDayOfThisMonth() {
LocalDateTime firstDayOfThisYear = get().with(TemporalAdjusters.firstDayOfMonth());
return DATETIME_FORMATTER.format(firstDayOfThisYear);
}
/**
* <p>
* 获取本月的最末天(当前时间)
* </p>
*
* @return:java.lang.String
* @author:bood
* @date:2020/9/25
*/
public static String getLastDayOfThisMonth() {
LocalDateTime firstDayOfThisYear = get().with(TemporalAdjusters.lastDayOfMonth());
return DATETIME_FORMATTER.format(firstDayOfThisYear);
}
/**
* <p>
* 当天开始时间
* </p>
*
* @return:java.time.LocalDateTime
* @author:bood
* @date:2020/9/25
*/
public static LocalDateTime todayStart() {
return LocalDateTime.of(getCurrentLocalDate(), LocalTime.MIN);
}
/**
* <p>
* 当天结束时间
* </p>
*
* @return:java.time.LocalDateTime
* @author:bood
* @date:2020/9/25
*/
public static LocalDateTime todayEnd() {
return LocalDateTime.of(getCurrentLocalDate(), LocalTime.MAX);
}
/**
* <p>
* 获取 指定年月的 第一个周一
* </p>
*
* @param year: 年份
* @param month: 月份
* @return:java.time.LocalDateTime
* @author:bood
* @date:2020/9/25
*/
public static LocalDateTime firstDayOfWeekInYearMonth(int year, int month) {
return get().withYear(year).withMonth(month).with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
}
/**
* <p>
* 获取 本周 第一天
* </p>
*
* @return:java.lang.String
* @author:bood
* @date:2020/9/25
*/
public static String getStartDayOfWeekToString() {
return formatLocalDate(getStartDayOfWeek());
}
/**
* <p>
* 获取 本周 第一天
* </p>
*
* @return:java.time.LocalDate
* @author:bood
* @date:2020/9/25
*/
public static LocalDate getStartDayOfWeek() {
TemporalAdjuster first_of_week = TemporalAdjusters.ofDateAdjuster(localDate -> localDate.minusDays(localDate
.getDayOfWeek().getValue() - DayOfWeek.MONDAY.getValue()));
return getCurrentLocalDate().with(first_of_week);
}
/**
* <p>
* 获取 本周 第末天
* </p>
*
* @return:java.lang.String
* @author:bood
* @date:2020/9/25
*/
public static String getEndDayOfWeekToString() {
return formatLocalDate(getEndDayOfWeek());
}
/**
* <p>
* 获取 本周 第末天
* </p>
*
* @return:java.time.LocalDate
* @author:bood
* @date:2020/9/25
*/
public static LocalDate getEndDayOfWeek() {
TemporalAdjuster last_of_week = TemporalAdjusters.ofDateAdjuster(localDate -> localDate.plusDays(
DayOfWeek.SUNDAY.getValue() - localDate.getDayOfWeek().getValue()));
return getCurrentLocalDate().with(last_of_week);
}
/**
* <p>
* LocalDateTime 转 Date
* </p>
*
* @param localDateTime: LocalDate 类型
* @return:java.util.Date
* @author:bood
* @date:2020/9/25
*/
public static Date asDate(LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
/**
* <p>
* Date 转 LocalDateTime
* </p>
*
* @param date: Date 类型
* @return:java.time.LocalDateTime
* @author:bood
* @date:2020/9/25
*/
public static LocalDateTime asLocalDateTime(Date date) {
return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
}
/**
* <p>
* LocalDate 转 Date
* </p>
*
* @param localDate: LocalDate 类型
* @return:java.util.Date
* @author:bood
* @date:2020/9/25
*/
public static Date asDate(LocalDate localDate) {
return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
}
/**
* <p>
* Date 转 LocalDate
* </p>
*
* @param date: Date 类型
* @return:java.time.LocalDate
* @author:bood
* @date:2020/9/25
*/
public static LocalDate asLocalDate(Date date) {
return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
}
}
最后
以上就是糊涂蛋挞为你收集整理的java8 新时间日期API的全部内容,希望文章能够帮你解决java8 新时间日期API所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复