前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >你还在用SimpleDateFormat格式化时间嘛?

你还在用SimpleDateFormat格式化时间嘛?

作者头像
石的三次方
发布2021-01-05 22:43:47
8150
发布2021-01-05 22:43:47
举报
文章被收录于专栏:石的三次方石的三次方

Jdk1.8之时间处理

该文章已经同步到Github:https://github.com/stackInk/makerstack 阅读原文直达

1. 传统时间处理的问题

1.1 多线程环境下的SimpleDateFormat

当多个线程使用同一个时间处理对象进行对日期的格式化的时候,会出现java.lang.NumberFormatException: multiple points。主要原因是由于SimpleDateFormat是线程不安全的,当线程共享的时候,会引发这个异常。

1.1.1 代码演示
代码语言:javascript
复制
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
//线程池中线程共享了SimpleDateFormat,引发线程不安全
Callable<String> callable = () -> simpleDateFormat.parse("20200402").toString();

ExecutorService executorService = Executors.newFixedThreadPool(10);
List<Future<String>> list = new LinkedList<>();

for (int i = 0; i < 10; i++) {
      Future<String> submit = executorService.submit(callable);
      list.add(submit);
}
for (Future<String> stringFuture : list) {
     String s = stringFuture.get();
     System.out.println(s);
}
executorService.shutdown();

解决方法:

  • 线程不共享变量SimpleDateFormat,每一个线程在进行日期格式化的时候都自己创建一个
代码语言:javascript
复制
ExecutorService executorService = Executors.newFixedThreadPool(10);
List<Future<String>> list = new LinkedList<>();
for (int i = 0; i < 10; i++) {
   Future<String> submit = executorService.submit(new MyCallable01("20200403"));
   list.add(submit);
}
for (Future<String> stringFuture : list) {
        String s = stringFuture.get();
        System.out.println(s);
 }
executorService.shutdown();

class MyCallable01 implements Callable<String>{

    private String date ;

    public MyCallable01(String date) {
        this.date = date;
    }

    @Override
        public String call() throws Exception {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
            return simpleDateFormat.parse(date).toString();
        }
}
  • 通过ThreadLocal为每一个线程绑定一个SimpleDateFormate
代码语言:javascript
复制
Future<String> submit = executorService.submit(() -> ResolveByThreadLocal.converDateStrToDate("20200405"));

public class ResolveByThreadLocal {
    //创建一个绑定每一个变量的ThreadLocal
    private static final ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<>();

    public static String converDateStrToDate(String date) throws ParseException {
        SimpleDateFormat simpleDateFormat = threadLocal.get(); ;
        if(simpleDateFormat == null){
            simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
            threadLocal.set(simpleDateFormat);
        }
        Date parse = simpleDateFormat.parse(date);
        return parse.toString() ;
    }
}

2. 1.8时间处理

对于时间的处理,均在java.time包及其子包中,且线程安全

  • java.time包下存放了进行时间处理的各种类
    • Instant获取本地时间的时间戳
    • LocalDate获取本地时间的日期
    • LocalTime获取本地时间的时间
    • LocalDateTime获取本地时间的日期和时间
    • Duration计算两个日期之间的间隔
    • Period计算两个时间的间隔
    • OffsetDateTime对日期和时间进行偏移量计算
    • offsetTime对时间进行偏移量计算
    • ZoneId各种时区代码
    • ZoneOffset市区偏移量计算
    • ZonedDateTime
  • java.time.chrono不同地区时间记时方式
  • java.time.temporal对时间进行一些调整的包
  • java.time.format对时间进行格式化

2.1 LocalDate、LocalTime、LocalDateTime

三者的使用方式完全相同,输出的结果不同

  • now获取本地时间
代码语言:javascript
复制
LocalDateTime now = LocalDateTime.now();
        System.out.println(now);
        System.out.println(now.getYear());
        System.out.println(now.getMonthValue());//直接获取月份的值
        System.out.println(now.getDayOfMonth());
        System.out.println(now.getHour());
        System.out.println(now.getMinute());
        System.out.println(now.getSecond());

输出:
2020-04-03T10:25:29.906
2020
4
3
10
25
29
  • of()传入指定的日期和时间
  • 对时间进行偏移量计算
  • 对事件进行偏移量运算
  • 当前时间与另一个时间的比较
  • 将月份天数,年份天数,月份等修改为指定的值,返回一个新的LocalDateTime对象
  • get方法
  • format(DateTimeFormatter formatter)对日期进行格式化
  • until返回两个日期之间的Period对象
  • isLeapYear判断是否为闰年

2.2 Instant时间戳

Unix元年(传统设定为UTC时区1970年1月1日)开始所经历的描述进行运算

  • 获取当前时间的时间戳toEpochMilli
  • 获取当前时间的秒getEpochSecond
  • 对时间进行偏移Instant.now().ofHours(ZoneOffset.ofHours(int hours))

2.3 TemporalAdjuster 时间校正器

主要通过TemporalAdjusters工具类获取到TemporalAdjuster实例对象

代码语言:javascript
复制
LocalDateTime now = LocalDateTime.now();
        //直接调用JDK提供的时间校正器
        LocalDateTime with = now.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
        System.out.println(with);
        //自定义一个时间校正器,计算下一个工作日
        LocalDateTime with2 = now.with(e -> {
            LocalDateTime e1 = (LocalDateTime) e;
            DayOfWeek dayOfWeek = e1.getDayOfWeek();
            if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {
                return e1.plusDays(3);
            } else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
                return e1.plusDays(2);
            } else {
                return e1.plusDays(1);
            }
        });
        System.out.println(with2);

2.4 DateTimeFormatter日期格式化

三种格式化方法:

  • 预定义的标准格式
  • 语言环境相关的格式
  • 自定义的格式
2.4.1 预定义的标准格式

JDK提供的格式化格式

代码语言:javascript
复制
LocalDate localDate = LocalDate.now();
String format = localDate.format(DateTimeFormatter.ISO_DATE);
输出:
 2020-04-03
2.4.1 自定义的时间格式
代码语言:javascript
复制
//自定义日期格式化方式,可以通过format和parse对日期进行格式化
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
String format1 = localDate.format(dateTimeFormatter);
System.out.println(format1);
localDate.parse(format1,dateTimeFormatter);

输出:
    2020年04月03日
    2020-04-03

2.5 时区处理

2.5.1 ZoneId
  • 获取所有的时区信息
代码语言:javascript
复制
 Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
  • 获取指定时区信息的ZoneId对象
代码语言:javascript
复制
ZoneId of = ZoneId.of("Asia/Chungking");
2.5.2 ZonedDateTime

获取一个带时区的日期时间对象

代码语言:javascript
复制
ZonedDateTime now = ZonedDateTime.now();
        System.out.println(now);
//输出
2020-04-03T14:22:54.250+08:00[Asia/Shanghai]

其他用法和LocalDateTime类相同

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 石的三次方 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Jdk1.8之时间处理
    • 1. 传统时间处理的问题
      • 1.1 多线程环境下的SimpleDateFormat
    • 2. 1.8时间处理
      • 2.1 LocalDate、LocalTime、LocalDateTime
      • 2.2 Instant时间戳
      • 2.3 TemporalAdjuster 时间校正器
      • 2.4 DateTimeFormatter日期格式化
      • 2.5 时区处理
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档