【JAVA入门】Day21 - 时间类

发布于:2024-08-18 ⋅ 阅读:(142) ⋅ 点赞:(0)

【JAVA入门】Day21 - 时间类



        Java 中的时间有一些相关类,它们都与时间的编程息息相关。

一、JDK7前的时间相关类

类名 作用
Date 时间类
SimpleDateFormat 格式化时间
Calender 日历类

        世界上的时间,是有一个统一的计算标准的。
        曾经的世界时间标准被称作 格林尼治时间 / 格林威治时间 (Greenwich Mean Time),简称GMT。GMT 的计算核心是:地球自转一天是24小时,太阳直射时为正午12点。但是由于误差太大,现在 GMT 已经被舍弃。
        现在的世界时间标准是利用原子钟规定的,利用铯原子的振动频率计算出来的时间,作为世界标准时间(UTC)。
        中国地处东八区,要在世界标准时间的基础上 + 8小时。

1.1 Date

        Date 类是 JDK 写好的一个 Javabean 类,用来描述时间,精确到毫秒。
        利用空参构造创建的对象,默认表示为系统当前时间
        利用有参构造创建的对象,表示为指定的时间

方法 作用
public Date() 创建Date对象,表示系统当前时间
public Date(long date) 创建Date对象,表示指定时间
public void setTime(long time) 设置/修改毫秒值
public long getTime() 获取时间对象的毫秒值

【练习】学习使用Date类。

package DateClass;

import java.util.Date;
import java.util.Random;

public class DateDemo2 {
    public static void main(String[] args) {
        //需求一:打印一年后的时间
        extracted();

        //需求二:比较两个Date对象哪个在前哪个在后
        extracted1();

    }

    private static void extracted() {
        //1.打印时间原点一年后的时间
        Date d1 = new Date(0L);

        //2.获取d1的毫秒值
        long time = d1.getTime();

        //3.加上一年后的毫秒值
        time = time + 1000L * 60 * 60 * 24 * 365;

        //4.把计算后的时间毫秒值,设置回d1中
        d1.setTime(time);

        //5.打印
        System.out.println(d1);
    	}

	    private static void extracted1() {
        Random r = new Random();

        //创建两个时间对象
        Date d1 = new Date(r.nextInt());
        Date d2 = new Date(r.nextInt());

        System.out.println(d1);
        System.out.println(d2);

        long time1 = d1.getTime();
        long time2 = d2.getTime();

        if(time1 > time2) {
            System.out.println("d2在前,d1在后");
        } else if(time2 > time1) {
            System.out.println("d1在前,d2在后");
        } else {
            System.out.println("两时间一样");
        }
   	  }
	}
}

1.2 SimpleDateFormat

         Date 类只能以默认的格式展示,不符合人们的阅读习惯。
        SimpleDateFormat 可以把日期格式化;也可以解析日期,即把字符串表示的时间编程 Date 对象。

构造方法 说明
public SimpleDateFormat() 构造一个SimpleDateFormat对象,使用默认格式
public SimpleDateFormat(String pattern) 构造一个SimpleDateFormat对象,使用指定的格式
常用方法 说明
public final String format(Date date) 格式化(日期对象 -> 字符串)
public Date parse(String source) 解析(字符串 -> 日期对象)

         格式化的时间形式的常用模式对应关系如下:
在这里插入图片描述
【练习1】练习使用SimpleDateFormat。

package DateClass;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateDemo3 {
    public static void main(String[] args) throws ParseException {
        //需求一:格式化时间
        method1();
        //需求二:解析字符串
        method2();
    }

    private static void method2() throws ParseException {
        //1.定义一个字符串用来表示时间
        String str = "2023-11-11 11:11:11";
        //2.利用空参构造创建SimpleDateFormat对象
        //其创建的格式参数要和字符串的格式完全一致
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //解析字符串,变为时间对象
        Date date = sdf.parse(str);
        //打印毫秒值
        System.out.println(date.getTime());
    }

    private static void method1() {
        //1.利用空参构造创建SimpleDateFormat对象,默认格式
        SimpleDateFormat sdf = new SimpleDateFormat();
        Date d1  = new Date(0L);
        String str = sdf.format(d1);
        System.out.println(str);       //1970/1/1 上午8:00

        //2.利用带参构造创建SimpleDateFormat对象,指定格式
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        String str2 = sdf2.format(d1);
        System.out.println(str2);       //1970年01月01日 08:00:00

        //3.格式2
        SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 EE");
        String str3 = sdf3.format(d1);
        System.out.println(str3);       //1970年01月01日 08时00分00秒 周四
    }
}

【练习2】把一个日期转换为另一种格式。

package DateClass;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateDemo4 {
    public static void main(String[] args) throws ParseException {
        /*2000-11-11*/

        String str = "2000-11-11";

        //1.解析字符串为日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = sdf.parse(str);

        //2.格式化日期为年月日
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日");
        String result = sdf1.format(date);

        //3.打印
        System.out.println(result);

    }
}

【练习3】判断两个同学是否秒杀成功。

package DateClass;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateDemo5 {
    public static void main(String[] args) throws ParseException {
        /*需求:
        秒杀活动:2023年11月11日 0:0:0
        开始时间:2023年11月11日 0:10:0

        小贾下单付款时间:2023年11月11日 0:01:00
        小皮下单付款时间:2023年11月11日 0:11:00

        计算两个人有没有参加成功
         */

        //1.比较两个时间
        String startStr = "2023年11月11日 0:0:0";
        String endStr = "2023年11月11日 0:10:0";
        String orderStr1 = "2023年11月11日 0:01:0";
        String orderStr2 = "2023年11月11日 0:11:00";

        //2.解析上面的时间,得到Date对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        Date startDate = sdf.parse(startStr);
        Date endDate = sdf.parse(endStr);
        Date orderDate1 = sdf.parse(orderStr1);
        Date orderDate2 = sdf.parse(orderStr2);

        //3.得到所有时间的毫秒值
        long startTime = startDate.getTime();
        long endTime = endDate.getTime();
        long orderTime1 = orderDate1.getTime();
        long orderTime2 = orderDate2.getTime();

        //4.判断
        if((startTime <= orderTime1)&&(orderTime1 <= endTime)) {
            System.out.println("小贾同学秒杀成功了!");
        }else{
            System.out.println("小贾同学秒杀失败了...");
        }

        if((startTime <= orderTime2)&&(orderTime2 <= endTime)) {
            System.out.println("小皮同学秒杀成功了!");
        }else{
            System.out.println("小皮同学秒杀失败了...");
        }
    }
}

1.3 Calendar

         Calendar 就是日历类,它是时间类的补充,可以单独修改、获取事件中的年,月,日。
         值得注意的是,Calendar 是一个抽象类,它不能直接创建对象。
         我们需要通过一个静态方法来获取当前时间的日历对象。

public static Calendar getInstance()

         Calendar 中常用的方法有这些:

方法名 说明
public final Date getTime() 获取日期对象
public final setTime(Date date) 给日历设置日期对象
public long getTimeInMillis() 拿到时间的毫秒值
public void setTimeInMillis(long millis) 给日历设置时间毫秒值
public int get(int field) 取得日历中某个字段的信息
public void set(int field,int value) 修改日历中的某个字段信息
public void add(int field,int amount) 为某个字段增加/减少指定的值

         下面通过一个练习,熟悉一下这些方法。

package DateClass;

import java.util.Calendar;
import java.util.Date;

public class CalenderDemo1 {
    public static void main(String[] args) {
        //1.获取日历对象
        //Calender是一个抽象类,不能直接new,而是通过一个静态方法获取子类对象
        Calendar c = Calendar.getInstance();
        //底层原理:
        //会根据系统的不同时区来获取不同的日历对象
        //把时间中的纪元,年,月,日,时,分,秒,星期,等等放到一个数组当中

        //2.修改一下日历代表的时间为时间原点
        //获取的时间信息有细节
        // 月份范围:0~11,0代表一月,11代表十二月
        // 星期:星期日是第一天,值为1;星期六的值为7
        Date d = new Date(0L);
        c.setTime(d);

        //3.获取日期中某个字段信息
        //参数为int类型
        //0:纪元 1:年 2:月 3:一年中的第几周 ...
        //Java当中,把索引数字都定义为了常量
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH) + 1;
        int date = c.get(Calendar.DAY_OF_MONTH);
        int week = c.get(Calendar.DAY_OF_WEEK);

        System.out.println(year + ", " + month + ", "+ date+ ", " + getWeek(week));


        //4.修改日历中某个字段
        c.set(Calendar.YEAR, 2000);
        c.set(Calendar.MONTH,12);
        //月份12是指13月,这是不存在的
        //系统会自动把年份调成次年

        //5.为某个字段增加/减少值
        c.add(Calendar.MONTH, -1);

    }

    //传入对应的数字:1~7
    //返回对应的星期
    //查表法:在方法中让数据跟索引产生对应关系
    public static String getWeek(int index) {
        String[] arr = {"","星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
        return arr[index];
    }
}

二、JDK8新增的时间相关类

         JDK8 新增的时间相关类,解决了 JDK7 代码麻烦的问题,而且在安全层面下有了突破。
         JDK7 在多线程环境下会导致数据安全问题产生,而 JDK8 的时间日期对象都是不可变的,解决了这个问题。
         JDK8 主要新增了以下四种类:
在这里插入图片描述

2.1 Date 相关类

2.1.1 ZoneId 时区

         时区类常用方法如下。
在这里插入图片描述

package DateClass;

import java.time.ZoneId;
import java.util.Set;

public class CalenderDemo2 {
    public static void main(String[] args) {
        /*
        时区
         */

        //1.获取所有的时区名称
        Set<String> zoneIds = ZoneId.getAvailableZoneIds();
        System.out.println(zoneIds);
        System.out.println(zoneIds.size());

        //2.获取当前系统的默认时区
        ZoneId zoneId = ZoneId.systemDefault();
        System.out.println(zoneId);

        //3.获取指定的时区
        ZoneId zoneId1 = ZoneId.of("Asia/Aqtau");
        System.out.println(zoneId1);
        
    }
2.1.2 Instant 时间戳

        时间戳是一种新的计算时间方法,它可以精确到时间的纳秒值(标准时间)。
在这里插入图片描述

package DateClass;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class DateDemo6 {
    public static void main(String[] args) {
        //1.获取当前时间的Instant对象(标准时间)
        Instant now = Instant.now();
        System.out.println(now);            //2024-08-16T10:35:23.164490400Z

        //2.根据(秒/毫秒/纳秒)获取Instant对象
        //获取原初时间戳
        Instant instant1 = Instant.ofEpochMilli(0L);
        System.out.println(instant1);       //1970-01-01T00:00:00Z

        //获取相较于原初时间一秒后的时间戳
        Instant instant2 = Instant.ofEpochSecond(1L);
        System.out.println(instant2);       //1970-01-01T00:00:01Z

        //获取1秒+1000000000纳秒后的时间
        Instant instant3 = Instant.ofEpochSecond(1L, 1000000000L);
        System.out.println(instant3);       //1970-01-01T00:00:02Z

        //3.指定时区
        //指定时区后再获得当前系统时间,中国在东八区,会自动加上8个小时
        ZonedDateTime zonedDateTime = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
        System.out.println(zonedDateTime);    //2024-08-16T18:45:01.710355900+08:00[Asia/Shanghai]

        //4.isXxx 判断
        Instant instant4 = Instant.ofEpochMilli(0L);
        Instant instant5 = Instant.ofEpochMilli(1000L);

        boolean result1 = instant4.isBefore(instant5);
        System.out.println(result1);            //true

        boolean result2 = instant4.isAfter(instant5);
        System.out.println(result2);            //false

        //5.增减时间
        Instant instant6 = Instant.ofEpochMilli(3000L);
        System.out.println(instant6);           //1970-01-01T00:00:03Z

        Instant instant7 = instant6.minusSeconds(1L);
        System.out.println(instant7);           //1970-01-01T00:00:02Z

        Instant instant8 = instant6.plusMillis(5000L);
        System.out.println(instant8);           //1970-01-01T00:00:08Z

    }
}
2.1.3 ZoneDateTime 带时区的时间

        带时区的时间就是带上时区的时间。
在这里插入图片描述

package DateClass;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class DateDemo7 {
    public static void main(String[] args) {
        //1.获取当前带时区的时间对象
        ZonedDateTime now = ZonedDateTime.now();
        System.out.println(now);

        //2.获取指定的带时区时间对象
        //年月日时分秒纳秒方式指定
        ZonedDateTime time1 = ZonedDateTime.of(2023,10,1,11,12,12,0, ZoneId.of("Asia/Shanghai"));
        System.out.println(time1);

        //通过Instant + 时区的方式获取指定时间对象
        Instant instant = Instant.ofEpochMilli(0L);
        ZoneId zoneId = ZoneId.of("Asia/Shanghai");
        ZonedDateTime time2 = ZonedDateTime.ofInstant(instant, zoneId);
        System.out.println(time2);      //1970-01-01T08:00+08:00[Asia/Shanghai]

        //3.withXxx 修改时间系列的方法,可以单独修改年月日等
        ZonedDateTime time3 = time2.withYear(2000);
        System.out.println(time3);      //2000-01-01T08:00+08:00[Asia/Shanghai]

        //4.减少时间
        ZonedDateTime time4 = time3.minusYears(1);
        System.out.println(time4);

        //5.增加时间
        ZonedDateTime time5 = time3.plusYears(1);
        System.out.println(time5);

        //细节:
        //JDK8新增的时间对象都是不可变的
        //如果我们进行任何形式的修改,调用者本身都不会改变,而是会产生一个新的时间
    }
}

2.2 DateTimeFormat 相关类

2.2.1 DateTimeFormatter 时间的格式化和解析类

        两个方法用来时间格式化和解析。被解析的时间对象可以是ZonedDateTime (带时区的时间类对象)。
在这里插入图片描述

package DateClass;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class DateDemo8 {
    public static void main(String[] args) {
        //获取时间对象
        ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));

        //生成对象
        DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EE a");

        //格式化时间对象
        System.out.println(dtf1.format(time));
    }
}

2.3 Calendar 相关类

2.3.1 LocalDate、LocalTime、LocalDateTime

在这里插入图片描述
        这三个类是这种关系,LocalDateTime 能表示的最全,年月日时分秒都可以,LocalDate 只能表示年月日,LocalTime 只能表示时分秒。LocalDate 和 LocalTime 之间可以互转。
在这里插入图片描述
        LocalDate 类用法如下。

package DateClass;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.MonthDay;

public class LocalDateDemo {
    public static void main(String[] args) {
        //1.获取当前时间的日历对象(包含年月日)
        LocalDate nowDate = LocalDate.now();

        //2.获取指定的时间的日历对象
        LocalDate ldDate = LocalDate.of(2023, 1, 1);
        System.out.println("指定日期:" + ldDate);

        System.out.println("===============================");

        //3.get系列方法获取日历中的每一个属性值
        //获取年
        int year = ldDate.getYear();
        System.out.println("year:" + year);

        //获取月
        //方式一:通过Month对象获取
        Month m = ldDate.getMonth();
        System.out.println(m);
        System.out.println(m.getValue());

        //方式二:用int变量接收
        int month = ldDate.getMonthValue();
        System.out.println(month);

        //获取日
        int day = ldDate.getDayOfMonth();
        System.out.println("day:" + day);

        //获取一年的第几天
        int dayOfYear = ldDate.getDayOfYear();
        System.out.println("dayOfYear:" + dayOfYear);

        //获取星期
        DayOfWeek dayOfWeek = ldDate.getDayOfWeek();
        System.out.println(dayOfWeek);
        System.out.println(dayOfWeek.getValue());

        //is方法表判断
        System.out.println(ldDate.isBefore(ldDate));
        System.out.println(ldDate.isAfter(ldDate));

        //with开头方法表示修改,只能修改年月日
        //修改传回的是一个新的对象
        LocalDate withLocalDate = ldDate.withYear(2000);
        System.out.println(withLocalDate);
        System.out.println(withLocalDate == ldDate); //false

        //minus减少年月日
        LocalDate minusLocalDate = ldDate.minusYears(1);
        System.out.println(minusLocalDate);

        //plus增加年月日
        LocalDate plusLocalDate = ldDate.plusDays(1);
        System.out.println(plusLocalDate);

        //------------------------------
        //判断今天是否是你的生日
        LocalDate birDate = LocalDate.of(2000, 1, 1);
        LocalDate nowDate1 = LocalDate.now();

        //月日对象
        MonthDay birMd = MonthDay.of(birDate.getMonthValue(), birDate.getDayOfMonth());
        MonthDay nowMd = MonthDay.of(nowDate1.getMonthValue(), nowDate1.getDayOfMonth());

        System.out.println("今天是你的生日吗?" + birMd.equals(nowMd));
    }
}

        LocalTime 类用法如下。

package DateClass;

import java.time.LocalTime;

public class LocalTimeDemo {
    public static void main(String[] args) {
        //获取本地时间的日历对象(时分秒)
        LocalTime nowTime = LocalTime.now();
        System.out.println("今天的时间:" + nowTime);

        int hour = nowTime.getHour(); //时
        System.out.println("hour:" + hour);

        int minute = nowTime.getMinute();   //分
        System.out.println("minute:" + minute);

        int second = nowTime.getSecond();   //秒
        System.out.println("second:" + second);

        int nano = nowTime.getNano();       //纳秒
        System.out.println("nano:" + nano);

        System.out.println("------------------------");
        System.out.println(LocalTime.of(8, 20, 30)); //时分秒
        LocalTime mTime = LocalTime.of(8, 20, 30, 150);

        //is系列方法
        System.out.println(nowTime.isBefore(mTime));
        System.out.println(nowTime.isAfter(mTime));

        //with系列方法,只能修改时分秒
        System.out.println(nowTime.withHour(10));

        //minus系列
        System.out.println(nowTime.minusHours(10));

        //plus系列
        System.out.println(nowTime.plusHours(10));
    }
}

2.4 JDK8 新增的三个工具类

        它们是:

  • Duration:时间间隔(秒,纳秒)
  • Period:时间间隔(年,月,日)
  • ChronoUnit:时间间隔(所有单位)

        Period - 计算年月日之间的时间间隔。

package DateClass;

import java.time.LocalDate;
import java.time.Period;

public class TimeUtils {
    public static void main(String[] args) {
        //当前本地年月日
        LocalDate today = LocalDate.now();
        System.out.println(today);

        //生日的年月日
        LocalDate birthDate = LocalDate.of(2000, 1, 1);
        System.out.println(birthDate);

        //时间间隔是多少:第二个参数减去第一个参数
        Period period = Period.between(birthDate, today);

        System.out.println("相差的时间间隔对象:" + period);
        System.out.println(period.getYears());
        System.out.println(period.getMonths());
        System.out.println(period.getDays());

        //转化为总共差几个月
        System.out.println(period.toTotalMonths());
    }
}

        Duration - 计算时分秒之间的时间间隔

package DateClass;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;

public class TimeUtils {
    public static void main(String[] args) {
        //当前本地年月日
        LocalDateTime today = LocalDateTime.now();
        System.out.println(today);

        //出生日期的时间对象
        LocalDateTime birthDate = LocalDateTime.of(2000,1,1,0,00,00);
        System.out.println(birthDate);

        Duration duration = Duration.between(birthDate,today);
        System.out.println("相差的时间间隔对象:" + duration);

        System.out.println("========================");
        System.out.println(duration.toDays());
        System.out.println(duration.toHours());
        System.out.println(duration.toMinutes());
        System.out.println(duration.toMillis());
        System.out.println(duration.toNanos());
    }
}

        ChronoUnit - 计算年月日时分秒的时间间隔。

package DateClass;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class ChronoUnitDemo {
    public static void main(String[] args) {
        //当前时间
        LocalDateTime today = LocalDateTime.now();
        System.out.println(today);

        //生日时间
        LocalDateTime birthDate = LocalDateTime.of(2000,1,1,0,0,0);
        System.out.println(birthDate);

        System.out.println("相差的年数:" + ChronoUnit.YEARS.between(birthDate, today));
        System.out.println("相差的月数:" + ChronoUnit.MONTHS.between(birthDate, today));
        System.out.println("相差的周数:"+ ChronoUnit.WEEKS.between(birthDate, today));
        System.out.println("相差的天数:"+ ChronoUnit.DAYS.between(birthDate, today));
        System.out.println("相差的时数:"+ ChronoUnit.HOURS.between(birthDate, today));
        System.out.println("相差的分数:"+ ChronoUnit.MINUTES.between(birthDate, today));
        System.out.println("相差的秒数:"+ ChronoUnit.SECONDS.between(birthDate, today));
        System.out.println("相差的毫秒数:"+ ChronoUnit.MILLIS.between(birthDate, today));
        System.out.println("相差的微秒数:"+ ChronoUnit.MICROS.between(birthDate, today));
        System.out.println("相差的纳秒数:"+ ChronoUnit.NANOS.between(birthDate, today));
        System.out.println("相差的半天数:"+ ChronoUnit.HALF_DAYS.between(birthDate, today));
        System.out.println("相差的十年数:"+ ChronoUnit.DECADES.between(birthDate, today));
        System.out.println("相差的世纪(百年)数:"+ ChronoUnit.CENTURIES.between(birthDate, today));
        System.out.println("相差的千年数:"+ ChronoUnit.MILLENNIA.between(birthDate, today));
        System.out.println("相差的纪元数:"+ ChronoUnit.ERAS.between(birthDate, today));
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到