时间

JDK7 以前的时间相关类

关于时间的相关知识

全世界的时间, 有一个统一的计算标准.


图1

地球围绕太阳转一圈是一年, 自转一圈是一天.

同一条经线上的时间是一样的.

零度经线也叫做本初子午线.

在 1884 年的时候, 将格林威治的时间认为是世界标准时间.

全世界分为 24 个时区, 分为东 12 个区和西 12 个区. 每一个时区的时间都是在标准时间的基础上进行加或减.

本初子午线的右侧, 是东 12 个区, 称为东部地区, 是在标准时间的基础上增加时间. 中国位于东八区, 要在世界标准时间的基础上加 8 小时.

本初子午线的左侧, 是西 12 个区, 称为西部地区, 是在标准时间的基础上减时间.


图2

红色部分就是正午十二点.

格林尼治时间/格林威治时间 (Greenwich Mean Time) 简称 GMT.

格林威治时间的计算核心: 地球自转一天是 24 小时, 将 24 小时进行 24 等分, 太阳直射时为正午 12 点.

这个计算方法对于人们的日常生活是够用的, 但是后来人们发现地球的自转速度是不均匀的, 导致这种计算方式存在误差, 根据历史记录, 最大误差曾经达到了 16 分钟.

现在格林威治时间已经不再作为标准时间来使用了.

到了 2012 年 1 月, 取消了用了将近 130 年的回归制标准时间. 现在, 标准时间是由原子钟来提供的.

原子钟: 利用铯原子的震动的频率计算出来的时间, 作为世界标准时间 (UTC)

铯原子每震动 9,192,631,770 次等于 1 秒钟. 这种计算方式是非常精准的, 2000 万年的误差为 1 秒钟.


图4

Date 类

Date 类是一个 JDK 写好的 Javabean 类, 用来描述时间, 精确到毫秒.

利用空参构造创建的对象, 默认表示操作系统当前时间.

利用有参构造创建的对象, 表示指定的时间.

查看 Date 类的源码:


图5

图6

图7

图8

程序示例:

import java.util.Date;

public class Demo {
    public static void main(String[] args) {

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


        // 1. 创建对象表示一个时间
        Date d1 = new Date();
        System.out.println(d1);  // Sun Nov 17 15:52:11 CST 2024

        // 2. 创建对象表示一个指定的时间
        Date d2 = new Date(0L);  // 从时间原点开始, 过了 0 毫秒的那个时间, 也就是时间原点
        System.out.println(d2);  // Thu Jan 01 08:00:00 CST 1970. 我们在中国, 在东八区, 要在标准时间的基础上加八个小时

        // 3. setTime 修改时间
        // 1000 毫秒 = 1 秒
        d2.setTime(1000L);
        System.out.println(d2);  // Thu Jan 01 08:00:01 CST 1970

        // 4. getTime 获取某个指定时间对象的毫秒值
        long time = d2.getTime();
        System.out.println(time);  // 1000
    }
}

程序示例:

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

public class Demo {
    public static void main(String[] args) {
        /*
        需求 1: 打印时间原点开始一年之后的时间
        需求 2: 定义任意两个 Date 对象, 比较一下哪个时间在前, 哪个时间在后
        */

        // 需求 2: 定义任意两个 Date 对象, 比较一下哪个时间在前, 哪个时间在后

        Random r = new Random();

        // 创建两个时间对象
        Date d1 = new Date(Math.abs(r.nextInt()));
        Date d2 = new Date(Math.abs(r.nextInt()));
        long time1 = d1.getTime();
        long time2 = d2.getTime();

        if (time1 > time2) {
            System.out.println("第一个时间在后面, 第二个时间在前面");
        } else if (time1 < time2) {
            System.out.println("第二个时间在后面, 第一个时间在前面");
        } else {
            System.out.println("表示两个时间一样");
        }
    }

    private static void method() {
        // 需求 1: 打印时间原点开始一年之后的时间
        // 1. 创建一个对象, 表示时间原点
        Date d1 = new Date(0L);

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

        // 3. 在这个基础上我们要加一年的毫秒值即可
        time = time + 1000L * 60 * 60 * 24 * 365;  // 加一个 L 防止计算结果超过 int 的范围
        // 4. 把计算之后的时间毫秒值, 再设置回 d1 当中
        d1.setTime(time);
        // 5. 打印 d1
        System.out.println(d1);
    }
}

SimpleDateFormat 类

Date 类只能按照固定的格式打印时间, 而这个格式不符合一般的阅读习惯.

SimpleDateFormat 类的作用:

  • 格式化: 把时间变成我们喜欢的格式.

  • 解析: 把字符串表示的时间变成 Date 对象.


图9 SimpleDateFormat 类的构造方法

图10 SimpleDateFormat 类的成员方法

图11

图12

程序示例:

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

public class Demo3 {
    public static void main(String[] args) throws ParseException {
        /*
            public simpleDateFormat() 默认格式
            public simpleDateFormat(String pattern) 指定格式
            public final string format(Date date) 格式化 (日期对象 -> 字符串)
            public Date parse(string source) 解析 (字符串 -> 日期对象)
        */

        // 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);
        // 3. 打印结果
        System.out.println(date);  // Sat Nov 11 11:11:11 CST 2023
        System.out.println(date.getTime());  // 1699672271000

        System.out.println("--------------------------------------------------------");
        method1();
        System.out.println("--------------------------------------------------------");
    }

    private static void method1() {
        // 1. 利用空参构造创建 SimpleDateFormat 对象, 默认格式
        SimpleDateFormat sdf1 = new SimpleDateFormat();
        Date d1 = new Date(0L);
        String str1 = sdf1.format(d1);
        System.out.println(str1);  // 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

        // 课堂练习: yyyy年MM月dd日 时:分:秒 星期
        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 周四
    }
}

程序示例:

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

public class demo4 {
    public static void main(String[] args) throws ParseException {
        /*
         * 假设, 你初恋的出生年月日为: 2000-11-11
         * 请用字符串表示这个数据, 并将其转换为: 2000年11月11日
         *
         * 创建一个 Date 对象表示 2000年11月11日
         * 创建一个 SimpleDateFormat 对象, 并定义格式为年月日把时间变成: 2000年11月11日
         */

        // 1. 可以通过 2000-11-11 进行解析, 解析成一个 Date 对象
        String str = "2000-11-11";
        // 2. 解析
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
        Date date = sdf1.parse(str);
        // 3. 格式化
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日");
        String result = sdf2.format(date);
        System.out.println(result);  // 2000年11月11日
    }
}

程序示例:

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

public class demo5 {
    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:0
         * 小皮下单并付款的时间为: 2023年11月11日 0:11:0
         * 用代码说明这两位同学有没有参加上秒杀活动?
         */

        // 1. 定义字符串表示三个时间
        String startstr = "2023年11月11日 0:0:0";
        String endstr = "2023年11月11日 0:10:0";
        String orderstr = "2023年11月11日 0:01:00";
        // 2. 解析上面的三个时间, 得到 Date 对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
        Date startDate = sdf.parse(startstr);
        Date endDate = sdf.parse(endstr);
        Date orderDate = sdf.parse(orderstr);

        // 3. 得到三个时间的毫秒值
        long startTime = startDate.getTime();
        long endTime = endDate.getTime();
        long orderTime = orderDate.getTime();

        // 4. 判断
        if (orderTime >= startTime && orderTime <= endTime) {
            System.out.println("参加秒杀活动成功");  // 参加秒杀活动成功
        } else {
            System.out.println("参加秒杀活动失败");
        }
    }
}

Calendar 类


图1

可以做, 但是比较麻烦.

Calendar 代表了系统当前时间的日历对象, 可以单独修改, 获取时间中的年, 月, 日.

细节: Calendar 是一个抽象类, 不能直接创建对象.

获取 Calendar 日历类对象的方法:


图2

图3

BuddhistCalendar 是佛历.

JapaneseImperialCalendar 是日本帝国历.

GregorianCalendar 是格林威治日历, 即公历.

程序示例:

import java.util.Calendar;

public class CalendarDemo2 {
    public static void main(String[] args) {
        /*
         * public static Calendar lgetInstance() 获取当前时间的日历对象
         * 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) 为某个字段增加/减少指定的值
         */

        // 1. 获取日历对象
        // 细节 1: Calendar 是一个抽象类, 不能直接 new, 而是通过一个静态方法获取到子类对象
        // 底层原理:
        // 会根据系统的不同时区来获取不同的日历对象, 默认表示当前时间. 
        // 把会把时间中的纪元, 年, 月, 日, 时, 分, 秒, 星期, 等等的都放到一个数组当中
        // 日 : 纪元
        // 1 : 年
        // 2 : 月
        // 3 : 一年中的第几周
        // 4 : 一个月中的第几周
        // 5 : 一个月中的第几天 (日期)
        // ....

        // 细节 2:
        // 月份: 范围 0~11 如果获取出来的是 0, 那么实际上是 1 月. 
        // 星期: 在老外的眼里, 星期日是一周中的第一天
        // 1 (星期日) 2 (星期一) 3 (星期二) 4 (星期三) 5 (星期四) 6 (星期五) 7 (星期六)
        Calendar c = Calendar.getInstance();
        System.out.println(c);
    }
}

getInstance() 源码:


图4

进入 createCalendar() 方法:


图5

Calendar 可以看作是一个抽象类. 它的实现, 采用了设计模式中的工厂方法.

当我们通过 Calendar.getInstance() 获取日历时, 默认的是返回的一个 GregorianCalendar 对象.

程序示例:

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

public class CalendarDemo2 {
    public static void main(String[] args) {
        /*
         * public static Calendar lgetInstance() 获取当前时间的日历对象
         * 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) 为某个字段增加/减少指定的值
         */

        // 1. 获取日历对象
        // 细节 1: Calendar 是一个抽象类, 不能直接 new, 而是通过一个静态方法获取到子类对象
        // 底层原理:
        // 会根据系统的不同时区来获取不同的日历对象, 默认表示当前时间. 
        // 把会把时间中的纪元, 年, 月, 日, 时, 分, 秒, 星期, 等等的都放到一个数组当中
        // 日 : 纪元
        // 1 : 年
        // 2 : 月
        // 3 : 一年中的第几周
        // 4 : 一个月中的第几周
        // 5 : 一个月中的第几天 (日期)
        // ....  一共 17 个属性, 所以索引最大为 16

        // 细节 2:
        // 月份: 范围 0~11 如果获取出来的是. 那么实际上是 1 月. 
        // 星期: 在老外的眼里,星期日是一周中的第一天
        // 1 (星期日) 2 (星期一) 3 (星期二) 4 (星期三) 5 (星期四) 6 (星期五) 7 (星期六)

        Calendar c = Calendar.getInstance();

        // 2. 修改一下日历代表的时间
        Date d = new Date(0L);
        c.setTime(d);
        System.out.println(c);
    }
}

程序示例:

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

public class CalendarDemo2 {
    public static void main(String[] args) {
        /*
         * public static Calendar lgetInstance() 获取当前时间的日历对象
         * 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) 为某个字段增加/减少指定的值
         */

        // 1. 获取日历对象
        // 细节 1: Calendar 是一个抽象类, 不能直接 new, 而是通过一个静态方法获取到子类对象
        // 底层原理:
        // 会根据系统的不同时区来获取不同的日历对象, 默认表示当前时间. 
        // 把会把时间中的纪元, 年, 月, 日, 时, 分, 秒, 星期, 等等的都放到一个数组当中
        // 日 : 纪元
        // 1 : 年
        // 2 : 月
        // 3 : 一年中的第几周
        // 4 : 一个月中的第几周
        // 5 : 一个月中的第几天 (日期)
        // ....  一共 17 个属性, 所以索引最大为 16

        // 细节 2:
        // 月份: 范围 0~11 如果获取出来的是. 那么实际上是 1 月. 
        // 星期: 在老外的眼里,星期日是一周中的第一天
        // 1 (星期日) 2 (星期一) 3 (星期二) 4 (星期三) 5 (星期四) 6 (星期五) 7 (星期六)

        Calendar c = Calendar.getInstance();

        // puslic int get(int field) 取日期中的某个字段信息
        // public void set(int field,int value) 修改日历的某个字段信息
        // public void add(int fieldint amount) 为某个字段增加/减少指定的值

        int year = c.get(1);
        int month = c.get(2);
        int date = c.get(5);
        System.out.println(year + ", " + month + ", " + date);  // 2024, 8, 19

        Date d = new Date(0L);
        c.setTime(d);
        int year1 = c.get(1);
        int month1 = c.get(2) + 1;
        int date1 = c.get(5);
        System.out.println(year1 + ", " + month1 + ", " + date1);  // 1970, 1, 1

        // Java 在 Calendar 类中, 把索引对应的数字都定义成常量,
        // 用数字当然也可以, 但是容易忘记, 阅读性也很低, 以后建议用常量,
        // 常量值可以进入 Calendar 类的源码中查看

        int year2 = c.get(Calendar.YEAR);
        int month2 = c.get(Calendar.MONTH) + 1;
        int date2 = c.get(Calendar.DAY_OF_MONTH);
        int week2 = c.get(Calendar.DAY_OF_WEEK);
        System.out.println(year2 + "," + month2 + "," + date2 + "," + week2);  // 1970,1,1,5
        // 最后的数字 5 表示星期四, 但是阅读性不强, 可以将其显示为星期四, 将该操作放在 getWeek() 中
        System.out.println(year2 + "," + month2 + "," + date2 + "," + getWeek(week2));  // 1970,1,1,星期四
    }

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

程序示例:

import java.util.Calendar;

public class CalendarDemo2 {
    public static void main(String[] args) {
        /*
         * public static Calendar lgetInstance() 获取当前时间的日历对象
         * 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) 为某个字段增加/减少指定的值
         */

        // 1. 获取日历对象
        // 细节 1: Calendar 是一个抽象类, 不能直接 new, 而是通过一个静态方法获取到子类对象
        // 底层原理:
        // 会根据系统的不同时区来获取不同的日历对象, 默认表示当前时间. 
        // 把会把时间中的纪元, 年, 月, 日, 时, 分, 秒, 星期, 等等的都放到一个数组当中
        // 日 : 纪元
        // 1 : 年
        // 2 : 月
        // 3 : 一年中的第几周
        // 4 : 一个月中的第几周
        // 5 : 一个月中的第几天 (日期)
        // ....  一共 17 个属性, 所以索引最大为 16

        // 细节 2:
        // 月份: 范围 0~11 如果获取出来的是. 那么实际上是 1 月. 
        // 星期: 在老外的眼里,星期日是一周中的第一天
        // 1 (星期日) 2 (星期一) 3 (星期二) 4 (星期三) 5 (星期四) 6 (星期五) 7 (星期六)

        Calendar c = Calendar.getInstance();

        // puslic int get(int field) 取日期中的某个字段信息
        // public void set(int field,int value) 修改日历的某个字段信息
        // public void add(int fieldint amount) 为某个字段增加/减少指定的值

        c.set(Calendar.YEAR, 2023);
        c.set(Calendar.MONTH, 8);
        c.set(Calendar.MONTH, 12);  // 月份大于 11 时, 自动改变年份, 自动向后排, 此时相当于下一年的一月份
        c.set(Calendar.DAY_OF_MONTH, 10);

        // 调用方法在这个基础上增加一个月
        c.add(Calendar.MONTH, -1);

        int year2 = c.get(Calendar.YEAR);
        int month2 = c.get(Calendar.MONTH) + 1;
        int date2 = c.get(Calendar.DAY_OF_MONTH);
        int week2 = c.get(Calendar.DAY_OF_WEEK);
        System.out.println(year2 + "," + month2 + "," + date2 + "," + getWeek(week2));  // 2023,12,10,星期日
    }

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

JDK8 新增的时间相关类


图1

图2

分成四组:


图3

全世界一共分为 24 个时区. 每一个时区内, 时间都是一样的.

但是 Java 定义时区时不是按照东一区, 东二区这种方式去定义的. 而是按照洲名/城市名或者国家名/城市名的格式来定义.

在中国, Java 定义了不止一个时区: Asia/Shanghai, Asia/Taipei, Asia/Chongqing. 一般都用上海.

全世界范围内, Java 一共定义了 600 个时区.

ZoneId 时区


图1

点击控制台, 点击 Ctrl + F, 可以在控制台输出的内容中进行搜索.

程序示例:

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

public class Demo1 {
    public static void main(String[] args) {
        /*
        static Set<string> getAvailableZoneIds() 获取 Java 中支持的所有时区
        static ZoneId systemDefault() 获取系统默认时区
        static Zoneld of(string zoneld) 获取一个指定时区
        */

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

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

        // 3. 获取指定的时区
        ZoneId zoneId1 = ZoneId.of("Asia/Pontianak");
        System.out.println(zoneId1);  // Asia/Pontianak
    }
}

Instant 时间戳


图1

程序示例:

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

public class Demo2 {
    public static void main(String[] args) {
        /*
         * static Instant now() 获取当前时间的 Instant 对象 (标准时间)
         * static Instant ofXxxx(long epochMilli) 根据 (秒/毫秒/纳秒) 获取 Instant 对象
         * ZonedDateTime atZone(ZoneIdzone) 指定时区
         * boolean isxxx(Instant otherInstant) 判断系列的方法
         * Instant minusXxx(long millisToSubtract) 减少时间系列的方法
         * Instant plusXxx(long millisToSubtract) 增加时间系列的方法
         */
        // 1. 获取当前时间的 Instant 对象 (标准时间)
        Instant now = Instant.now();
        System.out.println(now);

        // 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

        Instant instant3 = Instant.ofEpochSecond(1L, 1000000000L);
        System.out.println(instant3);  // 1970-01-01T00:00:027

        // 3. 指定时区
        ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
        System.out.println(time);

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

        // 5. 用于时间的判断
        // isBefore: 判断调用者代表的时间是否在参数表示时间的前面
        boolean result1 = instant4.isBefore(instant5);
        System.out.println(result1);  // true

        // isAfter: 判断调用者代表的时间是否在参数表示时间的后面
        boolean result2 = instant4.isAfter(instant5);
        System.out.println(result2);  // false

        // 6. Instant minusXxx(long millisToSubtract) 减少时间系列的方法
        Instant instant6 = Instant.ofEpochMilli(3000L);
        System.out.println(instant6);  // 1970-01-01T00:00:03Z

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

ZoneDateTime 带时区的时间


图1

程序示例:

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

public class Demo3 {
    public static void main(String[] args) {
        /*
         * static ZonedDateTime now() 获取当前时间的 ZonedDateTime 对象
         * static ZonedDateTime ofXxxx(. . . ) 获取指定时间的 ZonedDateTime 对象
         * ZonedDateTime withXxx(时间) 修改时间系列的方法
         * ZonedDateTime minusXxx(时间) 减少时间系列的方法
         * ZonedDateTime plusXxx(时间) 增加时间系列的方法
         */
        // 1. 获取当前时间对象 (带时区)
        ZonedDateTime now = ZonedDateTime.now();
        System.out.println(now);

        // 2. 获取指定的时间对象 (带时区) 1/年月日时分秒纳秒方式指定
        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);

        // 3. withXxx 修改时间系列的方法
        ZonedDateTime time3 = time2.withYear(2000);
        System.out.println(time3);

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

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

DateTimeFormatter 类: 用于时间的格式化和解析


图1

程序示例:

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

public class demo4 {
    public static void main(String[] args) {
        /*
         * static DateTimeFormatter ofPattern(格式) 获取格式对象
         * String format(时间对象) 按照指定方式格式化
         */
        // 获取时间对象
        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));
    }
}

LocalDate, LocalTime, LocalDateTime 类

这三个类都是和 日历 Calendar 相关的.


图1

图2

程序示例:

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();
        // System.out.println("今天的日期:" + nowDate);
        // 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 m = ldDate.getMonth();
        System.out.println(m);
        System.out.println(m.getValue());

        // 方式二:
        int month = ldDate.getMonthValue();
        System.out.println("month: " + 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);

        // 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.from(nowDate1);

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

程序示例:

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)); // 时分
        System.out.println(LocalTime.of(8, 20, 30)); // 时分秒
        System.out.println(LocalTime.of(8, 20, 30, 150)); // 时分秒纳秒
        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));

        // plus 系列的方法, 只能修改时, 分, 秒
        System.out.println(nowTime.plusHours(10));
    }
}

程序示例:

public class LocalDateTimeDemo {
    public static void main(String[] args) {
        // 当前时间的的日历对象 (包含年月日时分秒)
        LocalDateTime nowDateTime = LocalDateTime.now();

        System.out.println("今天是:" + nowDateTime); // 今天是: 
        System.out.println(nowDateTime.getYear()); // 年
        System.out.println(nowDateTime.getMonthValue()); // 月
        System.out.println(nowDateTime.getDayOfMonth()); // 日
        System.out.println(nowDateTime.getHour());  // 时
        System.out.println(nowDateTime.getMinute());  // 分
        System.out.println(nowDateTime.getSecond());  // 秒
        System.out.println(nowDateTime.getNano());  // 纳秒
        // 日: 当年的第几天
        System.out.println("dayofYear:" + nowDateTime.getDayOfYear());
        // 星期
        System.out.println(nowDateTime.getDayOfWeek());
        System.out.println(nowDateTime.getDayOfWeek().getValue());
        // 月份
        System.out.println(nowDateTime.getMonth());
        System.out.println(nowDateTime.getMonth().getValue());

        LocalDate ld = nowDateTime.toLocalDate();
        System.out.println(ld);

        LocalTime lt = nowDateTime.toLocalTime();
        System.out.println(lt.getHour());
        System.out.println(lt.getMinute());
        System.out.println(lt.getSecond());
    }
}

三个工具类: Duration, Period 和 ChronoUnit

程序示例:

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

public class PeriodDemo {
    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());
    }
}

程序示例:

import java.time.Duration;
import java.time.LocalDateTime;

public class DurationDemo {
    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);

        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());  // 两个时间差的纳秒数
    }
}

程序示例:

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));
    }
}
posted @ 2024-11-17 14:54  有空  阅读(33)  评论(0)    收藏  举报