上帝视角学JAVA- 基础12-常用类02-时间类相关【2021-08-17】

1、System 类

这个类的构造器是私有的,所有不能创建这个类的对象。要想使用,只能是通过调用其静态方法。

1.1、currentTimeMillis() 静态方法

获取当前时间与1970年1月1日0时0分0秒的时间差,单位为毫秒,返回值是一个long型数。

这种毫秒数通常叫做时间戳。以下统一叫做时间戳。

long l = System.currentTimeMillis();

1.2 exit 方法

exit(int status) 退出程序, 参数status为 0 表示正常退出。非0即异常退出

在图形化界面中,可以使用该方法进行退出程序。

1.3 gc 方法

void gc() 方法是 请求系统进行垃圾回收,至于系统是否立即回收,取决于系统中垃圾回收算法的实现以及系统执行时的情况。

1.4 getProperty 方法

String getProperty(String key) 方法 获取系统中属性名为key的属性对应的值。

系统有上图这些常用的属性。

2、Date 类

这里讲的Date类在 java.util包下。

注意 java.sql下也有一个Date类。而且是util包下的子类。

2.1 使用【 java.util.Date】

1、构造器使用

  • 无参构造器:创建一个对应当前时间的对象

Date date = new Date(); 
System.out.println(date);
​
// 输出  这样输出是因为Date类中重写的toString方法。返回的是当前的 年月日时分秒
Tue Aug 10 19:19:44 CST 2021
  • 有参构造器1: 创建一个指定时间的对象。已经过时,不建议使用。

Date date1 = new Date(2010, 1, 31);
  • 有参构造器2:根据时间戳创建一个时间对象。

Date date1 = new Date(1628594619869L);
System.out.println(date1);
// 输出
Tue Aug 10 19:23:39 CST 2021

2、方法

getTime方法: 也是返回当前时间戳

Date date = new Date();
System.out.println(date.getTime());
// 输出
// 1628594619869

2.2、数据库中的Date类

【 java.sql.Date】

Date date = new Date();
// 如果已经导了util的Date,创建同名的sql下的Date对象就要写全类名
java.sql.Date date1 = new java.sql.Date(1628594619869L);
System.out.println(date1);
// 输出: 2021-08-10

只输出 2021-08-10 说明 sql包下的Date也是重写了toString方法的。

如果互转?

1、sql(子)下转 util (父)的Date

直接赋值即可,利用多态。

2、util (父)转 sql(子) 对象

Date date = new Date();
// 利用构造器转换,先获取时间戳。
java.sql.Date date1 = new java.sql.Date(date.getTime());
System.out.println(date1);

3、SimpleDateFormat 类

SimpleDateFormat 这是一个对日期进行格式化的类。

1、格式化:日期 转 字符串

    @Test
    public void DateTest(){
        // 实例化日期格式化类
        SimpleDateFormat dateFormat = new SimpleDateFormat();
        // 生成一个当前时间对象
        Date date = new Date();
        // 格式化
        String format = dateFormat.format(date);
        System.out.println(format);
    }
 // 输出:
21-8-11 下午6:56

2、解析:字符串 转 日期

    @Test
    public void DateTest() throws ParseException {
        // 实例化日期格式化类
        SimpleDateFormat dateFormat = new SimpleDateFormat();
        // 默认解析
        String str = "21-8-11 下午7:00";
        Date parse = dateFormat.parse(str);
        System.out.println(parse);
    }
// 输出
Wed Aug 11 19:00:00 CST 2021
    
    @Test
    public void DateTest() throws ParseException {
        // 实例化日期格式化类,指定格式化形式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

        String str = "2001-07-04T12:08:56.235-0700";
        Date parse = dateFormat.parse(str);
        System.out.println(parse);
    }

  

上图为支持的字符串格式。否则会抛异常。

4、Calendar 类

日历类

这是一个抽象类。不能直接new对象

1、实例化

// 方式1:创建其子类 GregorianCalendar
GregorianCalendar calendar = new GregorianCalendar();

// 方式2:调用静态方法 getInstance() 实际还是子类GregorianCalendar的对象
Calendar instance = Calendar.getInstance();

2、常用方法

  • get 方法

// 获取今天是这个月的第几天。今天11号
int i = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(i);  // 11

类似的,可以获取这一周的第几天,今天的第几天。以及这个月的第几周。

  • set 方法 修改当前对象

Calendar calendar = Calendar.getInstance();

System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 11
calendar.set(Calendar.DAY_OF_MONTH, 20);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH));  // 20
  • add 方法 也是修改当前对象,是添加。 如果要减去几天 就是 添加一个负数

Calendar calendar = Calendar.getInstance();

System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 11
calendar.add(Calendar.DAY_OF_MONTH, 3);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 14
  • getTime 方法 获取Date对象 相当于 日历类转 Date类

Calendar calendar = Calendar.getInstance();

Date time = calendar.getTime();
System.out.println(time); // Wed Aug 11 19:36:28 CST 2021
  • setTime 方法 getTime的逆过程

Calendar calendar = Calendar.getInstance();


Date time = new Date();
calendar.setTime(time);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 11

注意: 月份是从0开始。 1月是0 、12月是11

获取星期时, 周日是1,周六是7

5、JDK 8 新时间Api

JDK8之前的Date类的缺点:

  • 可变性:像日期和时间应该是不可变的,而Date和Calendar都是可变的。

  • 偏移性:Date中的年份是从1900年开始,月份从0开始

    Date time = new Date(2021, 7, 12);
    System.out.println(time); 
    // Fri Aug 12 00:00:00 CST 3921

    我们期望的是2021年7月12日,而事实上确实3921年8月12日。因为Date是从1900年开始的,月份从0开始. 需要减去偏移量才能得到想要的。如下面的代码:

    Date time1 = new Date(2021 - 1900, 7 - 1, 12);
    System.out.println(time1);
    // Mon Jul 12 00:00:00 CST 2021 
  • 格式化:格式化只对Date有效,Calendar 不能格式化

  • 安全性:不是线程安全的

5.1 新Api java.time、java.format包

  • LocalDate:本地日期

  • LocalTime:本地时间

  • LocalDateTime:本地日期时间

1、now() 方法:获取当前时间 【类方法】

// 本地日期
LocalDate date = LocalDate.now();
// 本地时间
LocalTime time = LocalTime.now();
// 本地日期时间
LocalDateTime dateTime = LocalDateTime.now();

System.out.println(date);
System.out.println(time);
System.out.println(dateTime);
// 输出
2021-08-12
07:46:06.166
2021-08-12T07:46:06.166

实例化的第一种方法。获取当前的日期、时间等。

2、of() 方法:指定日期时间的方法。没有偏移量【类方法】

LocalDate date = LocalDate.of(2020, 5, 20);
LocalTime time = LocalTime.of(5,20,20);
LocalDateTime dateTime = LocalDateTime.of(2020, 5, 20, 5, 20, 20);
System.out.println(date);
System.out.println(time);
System.out.println(dateTime);
// 输出
2020-05-20
05:20:20
2020-05-20T05:20:20

以上2个方法为类方法,通过类名调用。

3、getxxx方法 : 获取时间 【成员方法】

这3个类都有类似的方法,为了简单,只以 LocalDateTime 为例。

// 类方法now 获取对象
LocalDateTime dateTime = LocalDateTime.now();

// 获取本月第几天
int dayOfMonth = dateTime.getDayOfMonth();
// 获取 星期几
DayOfWeek dayOfWeek = dateTime.getDayOfWeek();
// 获取 今天是今年的第几天
int dayOfYear = dateTime.getDayOfYear();
// 获取 小时
int hour = dateTime.getHour();
// 获取 月份
Month month = dateTime.getMonth();
// 获取 分钟
int minute = dateTime.getMinute();
// 获取 年份
int year = dateTime.getYear();
// 获取 秒
int second = dateTime.getSecond();
// 获取 纳秒
int nano = dateTime.getNano();
System.out.println(dayOfMonth); // 12
System.out.println(dayOfWeek);  // THURSDAY
System.out.println(dayOfYear);  // 224
System.out.println(hour);		// 7
System.out.println(month);		// AUGUST
System.out.println(minute);		// 59
System.out.println(year);		// 2021
System.out.println(second);		// 19
System.out.println(nano);		// 429000000

4、with 方法:修改、设置时间。相对于对象的时间,返回新的对象 【成员方法】

LocalDateTime dateTime = LocalDateTime.now();
System.out.println(dateTime);  // 2021-08-12T08:08:11.547
LocalDateTime dateTime1 = dateTime.withDayOfMonth(20);
System.out.println(dateTime1); // 2021-08-20T08:08:11.547

使用 dateTime 调用 withDayOfMonth(20) 方法 得到了相对 dateTime 对象的月份的第20天的 一个LocalDateTime对象 dateTime1,不会修改原来的dateTime对象。即不可变了。

LocalDateTime dateTime = LocalDateTime.now();
System.out.println(dateTime); // 2021-08-12T08:40:23.263
// 修改月份为5月,得到新的对象。原对象不变。
LocalDateTime dateTime1 = dateTime.withMonth(5);
System.out.println(dateTime1); // 2021-05-12T08:40:23.263

5、plus 方法:加,也是相对当前对象进行运算,得到新对象。【成员方法】

可以加小时,天、分钟、月、周、年等等。如果是加一个负数,就是减。

LocalDateTime dateTime = LocalDateTime.now();
System.out.println(dateTime); //2021-08-12T08:46:46.246
// 在dateTime基础上加上5天
LocalDateTime dateTime1 = dateTime.plusDays(5);
// 在dateTime基础上加上-5天,即减去5天
LocalDateTime dateTime2 = dateTime.plusDays(-5);
System.out.println(dateTime1); //2021-08-17T08:46:46.246
System.out.println(dateTime2); //2021-08-07T08:46:46.246
// 运算后原对象不变
System.out.println(dateTime); //2021-08-12T08:46:46.246

5.2 Instant 类 瞬时

在java中,以1970年开始,以毫秒为单位计算。

linux是1970年以秒为单位。

Instant now = Instant.now();
System.out.println(now);
// 输出
2021-08-12T00:53:51.875Z

输出的时间与我们的时间差8个小时。这个是以本初子午线为标准,我们是东八区。需要加上8小时。

  • atOffset 方法 设置偏移量 【成员方法】

Instant now = Instant.now();
OffsetDateTime time = now.atOffset(ZoneOffset.ofHours(8));
System.out.println(time); 
// 输出
2021-08-12T08:57:03.074+08:00

使用成员方法 atOffset 可以设置偏移量,纠正时间差。

  • toEpochMilli 计算 1970-01-01T00:00:00Z 到当前时间的毫秒数 【成员方法】

Instant now = Instant.now();
long l = now.toEpochMilli();
System.out.println(l); // 1628730009228
  • ofEpochMilli 通过 毫秒数得到Instance对象 【类方法】

Instant instant = Instant.ofEpochMilli(1628730009228L);
System.out.println(instant);

5.3 格式化类

java.time.format.DateTimeFormatter 类

该类用来格式化或解析日期或者时间

  • 预定义的标注格式、国际标准

// 预定义的格式化
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
LocalDateTime now = LocalDateTime.now();
// 使用成员方法 format 方法将时间格式化为 字符串
String format = formatter.format(now);
System.out.println(format); // 2021-08-13T16:23:34.699

// 字符串解析
TemporalAccessor parse = formatter.parse("2021-08-13T16:22:24.841");
System.out.println(parse);  // {},ISO resolved to 2021-08-13T16:22:24.841

预定义的方式看看就好,基本不用。

  • 预定义的 本地化相关的格式 ofLocalizedDateTime、ofLocalizedDate

// 使用类方法 ofLocalizedDateTime 获取一个 DateTimeFormatter 对象。
// 参数是一个 FormatStyle 枚举对象
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
LocalDateTime now = LocalDateTime.now();
// 调用 format 方法进行格式化
String format = formatter.format(now);
System.out.println(format); // 21-8-13 下午4:29
// 字符串解析
TemporalAccessor parse = formatter.parse("21-8-13 下午4:29");
System.out.println(parse); // {},ISO resolved to 2021-08-13T16:29

这个也是看看就好。

  • 自定义的格式 这个才是我们需要的

// 自定义的格式化, yyyy 表示年 MM 月 dd 日  hh 时 mm 分 ss 秒   - 连接符号
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
LocalDateTime now = LocalDateTime.now();
// 格式化
String format = formatter.format(now);
System.out.println(format); // 2021-08-13 04:38:17
// 解析
TemporalAccessor parse = formatter.parse("2021-08-13 04:38:17");
System.out.println(parse);
// {NanoOfSecond=0, MicroOfSecond=0, MinuteOfHour=38, MilliOfSecond=0, SecondOfMinute=17, HourOfAmPm=4},ISO resolved to 2021-08-13

自定义的方式就是使用类方法 ofPattern 得到 DateTimeFormatter 对象。参数就是我们自己定义的 格式。

yyyy 表示年 MM 月 dd 日 hh 时 mm 分 ss 秒 - 连接符号

5.4 转换

6、比较器

正常情况下,java的引用数据类型只能进行比较 地址是否系统 ==

不是比较对象的大小。但是我们可以重新 equals 方法,来比较2个对象是否相等。

这还是比较相等,没有比较大于、小于。

实际开发中,需要对对象进行排序。一般是对对象的某一个属性或者某几个属性进行比较。

java提供了2个比较的接口:Comparable 接口和 Comparator接口

6.1 Comparable

public interface Comparable<T> {
    
    public int compareTo(T o);
}

Comparable 接口只有一个 compareTo方法,返回值为 int型,不抛异常。

String类实现了 Comparable 接口,对compareTo方法进行了实现。所以可以进行比较排序。

 public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

上面的代码是String类的重写。可以看一下。

重写 compareTo 的规则:

  • 当前对象 this 大于 形参对象,返回正整数 一般是 1

  • 当前对象 this 小于 形参对象,返回负整数 一般是 -1

  • 当前对象 this 等于 形参对象,返回 0

自定义的类,想要排序,可以实现 Comparable 接口,实现这个 compareTo 方法。

这个用的不多,因为实现这个方法相当于写死了,不灵活。

6.2 Comparator 接口 定制比较

这个接口是因为 我们写的类经常没有实现 Comparable 接口,或者说实现了但是想换一种方式排序,想要更灵活的比较,就出现这个接口。

这个接口的代码较多。可以自己去看源码。

主要 需要实现 compare 方法

int compare(T o1, T o2);

T是泛型。后续介绍。

看下面的例子:

String[] arr = new String[]{"AA","CC","KK","ZZ","JJ"};
Arrays.sort(arr, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return -o1.compareTo(o2);
    }
});

在sort方法里面的第二个参数可以传一个 Comparator的实现类对象。这里是使用的匿名实现类,因为只用一次。

这个匿名实现类必须要实现 compare 方法。其实 Comparator 里面还有一个抽象方法既不是 默认方法也不是 静态方法,那就是 equals 方法。按照接口的定义,equals方法是必须要在实现类中实现的。但是这里可以不实现这个方法。原因是 实现类必定继承了Object类。Object类里面已经有这个equals方法的实现了。即如果实现类不重写这个方法,就会直接拿Object类的这个方法。只要可以找到实现的方法体,就没有强制一定要重写。

因此,Comparator 接口只有一个必须要实现的方法 compare。

compare 方法里面写自己的比较逻辑。这里是调用String类自带的compartTo方法,对结果取反,即反向排序。

上面的写法中,指定了泛型为String,如果没有指定,就必须写成下面这种样子:

String[] arr = new String[]{"AA","CC","KK","ZZ","JJ"};
Arrays.sort(arr, new Comparator() {
    @Override
    public int compare(Object o1, Object o2) {
        if (o1 instanceof String && o2 instanceof String){
            String s1 = (String) o1;
            String s2 = (String) o2;
            return -s1.compareTo(s2);
        }
        throw new RuntimeException("输入的数据类型不匹配");
    }
});

这个接口实质就是在 compare 接口里面实现 这个compare方法。关键是比较的逻辑编写。

原则还是上面Comparable里面讲的原则。

7、BigInteger、BigDecimal 类

1、BigInteger

可以表示非常大的正数

public class BigInteger extends Number implements Comparable<BigInteger> {}

BigInteger 可以表示 不可变的任意精度的整数。

BigInteger提供所有java的基本整数操作符的对应物。还提供 模运算、GCD运算、质数测试、素数生成、位操作等

2、BigDecimal

一般的float、double类可以用来做科学技术或工程技术,商业计算中,对数字要求精度比较高,需要使用BigDecimal类

public class BigDecimal extends Number implements Comparable<BigDecimal> {}

BigDecimal 支持不可变的、任意精度的有符号十进制定点数。

有很多的构造方法。

里面提供了很多的方法进行运算。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值