java日期类

介绍

        随着Java版本的更新,处理日期和时间的API也经历了显著的变化。在Java 8之前,主要使用的是 java.util.Date、java.util.Calendar 和 java.text.SimpleDateFormat 等类来处理日期和时间,但这些类存在很多缺点,比如设计不合理、线程不安全、不可变性差等。该类已经有很多方法已被注销不再使用,所以我们不推荐使用此类
        从Java 8开始,引入了全新的日期时间API,位于java.time包下,这个新的API旨在解决旧有API的问题,并提供更加直观和强大的日期时间处理能力。

第一代日期类

Date类

        我们可以使用 Date 类的无参构造器,它的功能就是获取当前时间。
        但需注意,我们使用该方法需要引入的包为 java.util.Date ;而该方法在 java.sql.Date; 包中也存在,但并非我们所需的包,所以需要注意不要误引。
        该类常用的构造方法有两个,分为无参和有参构造,无参构造即获取当前时间,有参构造允许接收一个 long 型参数,该参数表示自1970年1月1日 00:00:00 GMT以来的过了毫秒数之后的时间。

        我们还可使用 getTime() 返回自1970年1月1日00:00:00 GMT以来的毫秒数(即时间戳),我们可以使用两个由该方法所得的参数来判断程序运行所需时长。我们可以先创建Date对象,再调用该对象的.getTime()就可获取时间戳。

        其次,该方法输出的日期格式并不便于理解,因此通常需要使用 SimpleDateFormat 类对其格式进行转换。

import java.util.Date;
//不要误导入 java.sql.Date 包
public class Go {
    public static void main(String[] args) {
        Date x = new Date();//调用无参构造器
        System.out.println(x);
        Date now = new Date(99999999);//调用有参构造器传入long型变量99999999
        System.out.println(now);
    }//输出结果:Thu Aug 08 23:47:22 CST 2024
     //         Fri Jan 02 11:46:39 CST 1970
}

SimpleDateFormat类

格式化日期

        SimpleDateFormat类是一个以与语言环境有关的方式来格式化和解析日期的具体类。它允许进行格式化(日期 -> 文本)、解析(文本 -> 日期)和规范化。然而,由于它依赖于 Date 类,因此也受到其设计缺陷的影响。

public class Go {
    public static void main(String[] args) {
        Date x = new Date();//调用无参构造器
        Date now = new Date(99999999);//调用有参构造器传入long型变量99999999
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(sdf.format(x));
        System.out.println(sdf.format(now));
    }//输出2024-08-11 04:14:12
}//       1970-01-02 11:46:39

        这个例子中,模式字符串 "yyyy-MM-dd HH:mm:ss" 表示日期时间将按照“年-月-日 时:分:秒”的格式进行格式化和解析。

字符串转换为日期

        此外,该类还可以将指定格式的字符串转换为对应的Date,但须注意此时的格式和使用 Date() 方法构造的格式一样不便理解,还需使用 sdf.format() 方法转换其格式再进行输出。
        注意所给的字符串格式必须与使用的 sdf 格式相同,否则会抛出异常,在此我们为避免抛出异常,可使用 throws 关键字事先声明该异常。

public class Go {
    public static void main(String[] args) throws ParseException {
        //事先使用throws关键字抛出异常
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //创建 SimpleDateFormat 类实例
        String str = "2222-22-22 22:22:22";
        //创建字符串,格式与定义的sdf相同
        System.out.println(sdf.format(sdf.parse(str)));
        //使用sdf.parse()方法转换为Date类再调用sdf.format()方法改变日期格式
    }
}

第二代日期类

        第二代日期类指的是 java.util.Calendar 类。它是一个抽象类,提供了方法和字段(如年、月、日、时、分、秒等)的方法。它允许进行日期和时间的计算,如添加或减去特定的时间单位。
        由于 Calendar 是抽象类,并且他的构造器也是私有化的,因此不能直接实例化,而需通过调用其静态方法 getInstance() 来获取一个 Calendar 对象,这个方法会根据默认时区和语言环境返回一个子类对象。

public class Go {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();
        System.out.println(calendar);
    }
}

输出结果:java.util.GregorianCalendar[time=1723405314881,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2024,MONTH=7,WEEK_OF_YEAR=33,WEEK_OF_MONTH=3,DAY_OF_MONTH=12,DAY_OF_YEAR=225,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=2,AM_PM=0,HOUR=3,HOUR_OF_DAY=3,MINUTE=41,SECOND=54,MILLISECOND=881,ZONE_OFFSET=28800000,DST_OFFSET=0]
        这种输出方法会输出大量字段信息,我们难以获取所需字段,所以我们一般会通过 get 方法获取指定字段:

public class Go {
    public static void main(String[] args) {
        Calendar c = Calendar.getInstance();
        System.out.print("今天是:\n"+c.get(Calendar.YEAR)+"年");
        System.out.print(c.get(Calendar.MONTH)+1+"月");//需+1
        System.out.println(c.get(Calendar.DAY_OF_MONTH)+"日");//为12小时制
        System.out.print(c.get(Calendar.HOUR)+"点");
        System.out.print(c.get(Calendar.MINUTE)+"分");
        System.out.print(c.get(Calendar.SECOND)+"秒");
    }
}

输出结果:

今天是:
2024年8月12日
3点50分44秒 

注意:因为这里的月份是从零开始算的,所以需要+1才是正确的月份

这里输出的小时为12小时制,如需使用24小时制只需将 Calendar.HOUR 替换为 Calendar.HOUR_OF_DAY 即可

        因为 Calendar 并未提供指定的格式化输出方法,所以具体需要截取哪一字段的信息需要自行编写组合。

        相对于 Date 类 来说 Calendar 类已经完善了很多,但仍存在一定问题:
可变性:像日期和时间这样的类应该是不可变的。

偏移性:月份并不是从 1 开始,而是从 0 开始计算。

格式化:不包含格式化输出方法。

线程安全:它不是线程安全的,例如不能处理闰秒(每隔两天,多出一秒)

第三代日期类

        第三代日期类主要指的是Java 8及以后版本中引入的 java.time 包下的一系列日期和时间API。这些新的日期和时间类旨在解决早前两代日期类存在的问题,如设计缺陷、易用性差、线程安全性问题等。

        java.time包提供了一套全新的日期和时间API,包括日期(LocalDate)、时间(LocalTime)、日期时间(LocalDateTime)、时区日期时间(ZonedDateTime)等类,以及用于日期时间运算的DurationPeriod类。这些类基于ISO-8601日历系统,提供了更好的设计、更清晰的API和更好的时区支持。

主要方法

  1. LocalDate:表示一个具体的日期,不包含时间信息(只有年月日,不包含时分秒)。可以通过年、月、日创建实例,支持日期的加减、比较等操作。

  2. LocalTime:表示一个具体的时间,不包含日期信息(只有时分秒,不包含年月日))。可以通过时、分、秒(以及纳秒)创建实例,支持时间的加减、比较等操作。

  3. LocalDateTime:表示一个具体的日期和时间(既包含年月日,也包含时分秒),不包含时区信息。可以看作LocalDateLocalTime的组合,支持日期和时间的加减、比较等操作。

  4. ZonedDateTime:表示一个具体的时区日期时间。在LocalDateTime的基础上增加了时区信息,可以精确表示世界上任何时区的日期和时间。

  5. Duration:用于表示两个时间点之间的时间间隔,以秒和纳秒为基准。可以用于计算两个LocalTimeLocalDateTime之间的时间差。

  6. Period:用于表示两个日期之间的时间间隔,以年、月、日为基准。可以用于计算两个LocalDate之间的日期差。

  7. now:通过该方法返回当前日期类的对象。
public class Go {
    public static void main(String[] args) {
        LocalDateTime x=LocalDateTime.now();//获取年月日时分秒
//也可替换为LocalDate now= LocalDate.now();或LocalTime now= LocalTime.now();
        System.out.println(x);
    }
}

输出结果:2024-08-12T04:21:02.450

        如需获取单独的字段,也可使用实例所包含的方法,其中x.getYear()表获取年、x.getMonth()表获取英文月份、x.getMonthValue()表获取中文月份、x.getDayOfMonth()表获取日、x.getHour()表获取时、x.getMinute()表获取分、x.getSecond()表获取秒。

DateTimeFormatter类

        同时第三代日期类也包含一个类似于第一代日期类中 SimpleDateFormat 功能(即格式化日期格式)的类:DateTimeFormatter类,功能也类似

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Go {
    public static void main(String[] args) {
        // 创建DateTimeFormatter对象,指定自定义格式
        DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        // 格式化LocalDateTime对象
        LocalDateTime x = LocalDateTime.now();
        String aim = DTF.format(x);
        System.out.println("格式化后的日期: " + aim);

        // 解析字符串为LocalDateTime对象
        LocalDateTime DTF1 = LocalDateTime.parse("2023-10-01 12:00:00", DTF);
        System.out.println("解析后的日期: " + DTF1);
    }
}

输出结果

格式化后的日期: 2024-08-12 04:47:26
解析后的日期: 2023-10-01T12:00

Instant类

        该类类似于 Date,并提供了一系列和 Date 类转换的方式:

public class Go {
    public static void main(String[] args) {
        //通过静态方法now获取当前时间戳的对象
        Instant ins =Instant.now();
        System.out.println(ins);
        //通过from()方法将Instant类转换为Date类
        Date d=Date.from(ins);
        System.out.println(d);
        //通过toInstant()方法将Date类转换成Instant类
        ins=d.toInstant();
    }
}

输出结果:

2024-08-11T21:00:15.085Z
Mon Aug 12 05:00:15 CST 2024

        还可以进行时间计算:可以使用plusminus系列的方法来计算时间偏移,如plusSeconds(long seconds)minusMillis(long millis)等。

public class Go {
    public static void main(String[] args) {
        // 创建DateTimeFormatter对象,指定自定义格式
        DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime ldt=LocalDateTime.now();
        System.out.println("当前日期:"+DTF.format(ldt));
        ldt=ldt.plusDays(8);
        System.out.println("8天后的日期:"+DTF.format(ldt));
        ldt=ldt.minusDays(16);
        System.out.println("8天前的日期:"+DTF.format(ldt));
    }
}

执行结果:

当前日期:2024-08-12 05:12:44
8天后的日期:2024-08-20 05:12:44
8天前的日期:2024-08-04 05:12:44

  • 10
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值