java 日期相关类的学习和多线程下的日期格式化使用

Date类

Date类 实现Serializable Cloneable Comparable 接口

他的子类有:Date(sql包下的) Time Timestamp  这三个子类其实都是sql包下的

Date的构造方法:

Date()获取当前的时间对象 
Date(long date)将时间戳数字转化为Date类对象 

Date常用方法:

long getTime()将时间以long类型返回

boolean after(Date when)

是否在指定时间之后
boolean before(Date when)是否在指定时间之前

Calendar日历类 实现Serializable Cloneable Comparable 接口 ,是一个抽象类,构造方法都被protected修饰

用法比Date复杂,但是功能是日历,而不再需要我们进行long类型的加减操

常用方法:

Calendar getInstance()获取calendar的示例对象
int get(int field)获取calendar的成员日期或其他时间数据
set(int field, int value)设置指定成员的数据内容
abstract void add(int field, int amount)在指定的成员数据上进行加法运算
  
public static void main(String[] args) {
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.MONTH, 6); //计算半年后的日期
        instance.set(instance.get(Calendar.DAY_OF_MONTH), 3); // 设置这个月的第三天,即半年后的那个月的第三天
        System.out.println(String.format("日历为,%s,%s,%s %s:%s:%s", instance.get(Calendar.YEAR)
                , instance.get(Calendar.MONDAY)
                , instance.get(Calendar.DAY_OF_MONTH)
                , instance.get(Calendar.HOUR_OF_DAY)
                , instance.get(Calendar.MINUTE)
                , instance.get(Calendar.SECOND)
                ));
    }

SimpleDateFormat:格式化日期类,在java.text 包下面,这个包是国际化都放在这个里面

这个类继承了DateFormat 

format(Date date)将日期格式化转化为字符串
parse(String source)将字符串转化为日期
SimpleDateFormat(String pattern)创建对象,设置匹配模式

如果想成功的对日期进行格式化或者将字符串转化为日早起,那么 就必须存在有一个日期的匹配表达式,而这组表达式里面最重要的几个日期单位年(yyyy) 月(MM)日(dd)时(HH)分(mm)秒(ss)毫秒(SSS)

public static void main(String[] args) throws Exception{
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        System.out.println(dateFormat.format(date));
        String str = "2020-04-01 22:23:11.606";
        Date parse = dateFormat.parse(str);
        System.out.println(parse);
    }

java中常用的 数据类型和字符串相互转换的常用方法

LocalDate类

在jdk1.8 之后的版本里,java追加了一个新的日期时间的处理包,java.time ,在这个包有三个类比较重要LocalDate

LocalTime ,LocalDateTime ,通用Calendar类相比更加简单

 

public static void main(String[] args) throws Exception {
        LocalDate localDate = LocalDate.now();
        LocalTime localTime = LocalTime.now();
        LocalDateTime localDateTime = LocalDateTime.now();

        System.out.println("LocalDate 实例化输出" + localDate);
        System.out.println("LocalTime 实例化输出" + localTime);
        System.out.println("LocalDateTime 实例化输出" + localDateTime);

        System.out.println(String.format("当前日期%s-%s-%s", localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth()));
        System.out.println("获取一周的时间数" + localDate.getDayOfWeek().getValue());
        System.out.println("今天所处的一月的周数" + localDate.get(ChronoField.ALIGNED_WEEK_OF_MONTH));
        System.out.println("今天所处的一年的周数" + localDate.get(ChronoField.ALIGNED_WEEK_OF_YEAR));
        System.out.println("今天所处的一年的第几天" + localDate.getDayOfYear());

        LocalDate localDate2 = LocalDate.parse("2020-04-02");
        System.out.println("是否是闰年" + localDate2.isLeapYear());
        System.out.println("所在月的第一天" + localDate.with(TemporalAdjusters.firstDayOfMonth()));
        System.out.println("所在月的第一天" + localDate.withDayOfMonth(1));
        System.out.println("所在月的最后一天" + localDate.with(TemporalAdjusters.lastDayOfMonth()));
        System.out.println("三百年后的日期" + localDate.plusYears(300));
        System.out.println("日期所处月的第一个周一" + localDate.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)));

    }

在多线程下的SimpleDateFormat类的操作:

首先说一下出现的原因:将字符串转化为日期,一定要使用SimpleDateFormat类,于是这个类成了所有项目开发中必然要采用的工具类,于是下面来针对这个工具类使用进行多线程环境下的分析:

单线程:

public static void main(String[] args) throws Exception{

        for (int i = 0; i < 10; i++)
        {
            new Thread(() -> {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                try {
                    System.out.println("当前线程的名称是:" + Thread.currentThread().getName()+ " 线程id是:" + Thread.currentThread().getId() + sdf.parse("1998-02-17 22:31:32"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }

            }, "SDF转换线程" + i).start();
        }
    }

上述代代码,虽然也是多线程,但是每一个线程都保留了一个各自的SimpleDateFormat 类的对象,所以整个的转换是可以正常完成的,但是上述多个线程要将字符串转化为相同的类型的日期,所以没有必要每个线程都定义一个单独的SimpleDateFormat 类对象实例(这样可以减少内存垃圾内存开销)

所以我们可以修改代码(注意下面这代码是错误的,给大家演示现象,危险代码请勿模仿,这个错误时:将字符串转化为日期会报错,但是当日期转化为字符串时不会报错

public static void main(String[] args) throws Exception{
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        for (int i = 0; i < 10; i++)
        {
            new Thread(() -> {

                try {
                    System.out.println("当前线程的名称是:" + Thread.currentThread().getName()+ " 线程id是:" + Thread.currentThread().getId() + sdf.parse("1998-02-17 22:31:32"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }

            }, "SDF转换线程" + i).start();
        }
    }

发现代码不仅报错,而且有的时间不对

为什么会报错:

出现的异常中有 NumberFormatException这个异常,是因为在设计SimpleDateFormat类的时候,它的转化处理操作机制并没有同步的处理,即线程A的日期时间传递过来之后,可能刚配置了一半数据之后,线程B又传过来的数据,也进行了匹配内容的变更,这样就会出现线程不同步的问题。

即多个线程不能并发的访问

如何解决这个问题的方法

1:传统方法,每个线程都有一个SimpleDateFormat 对象,就是我们最开始的那种方法,但是缺点就是造垃圾

2:我们利用jdk1.8 的LocalDate ,LocalDateTime LocalDateTime 类来完成

public static void main(String[] args) throws Exception{

        // 创建日期的格式化类对象,定义SimpleDateFormat 类中的匹配日期时间字符串
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        ZoneId zoneId = ZoneId.systemDefault();

        for (int i = 0; i < 10; i++)
        {
            new Thread(() -> {
                try {
                    LocalDateTime localDateTime = LocalDateTime.parse("1998-02-17 22:31:32", formatter);
                    Instant instant = localDateTime.atZone(zoneId).toInstant();// 获得一个当前时区的一个实例
                    Date date = Date.from(instant);
                    System.out.println("当前线程的名称是:" + Thread.currentThread().getName()+ " 线程id是:" + Thread.currentThread().getId()+ date);
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }, "SDF转换线程" + i).start();
        }

下面给出LocalDate 类

public static void main(String[] args) throws Exception{

        // 创建日期的格式化类对象,定义SimpleDateFormat 类中的匹配日期时间字符串
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        ZoneId zoneId = ZoneId.systemDefault();

        for (int i = 0; i < 10; i++)
        {
            new Thread(() -> {
                try {
                    LocalDate localDate = LocalDate.parse("1998-02-17", formatter);
                    Instant instant = localDate.atStartOfDay().atZone(zoneId).toInstant();// 获得一个当前时区的一个实例
                    Date date = Date.from(instant);
                    System.out.println("当前线程的名称是:" + Thread.currentThread().getName()+ " 线程id是:" + Thread.currentThread().getId()+ date);
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }, "SDF转换线程" + i).start();
        }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值