Java日期&时间处理

Calendar日期处理

Calendar相比于Date多了可以对时间运算的功能,也可以通过getTime方法把Calendar转化为Date

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

public class TestDate {
    public static void main(String[] args) {
        // 获取Calendar实例
        Calendar cal = Calendar.getInstance();
        // 获取年、月、日、时、分、秒
        System.out.println(cal.get(Calendar.YEAR));
        System.out.println(cal.get(Calendar.MONTH));
        System.out.println(cal.get(Calendar.DAY_OF_MONTH));// 一月中的第几天
        System.out.println(cal.get(Calendar.HOUR_OF_DAY)); //时间(24小时制)
        System.out.println(cal.get(Calendar.MINUTE));
        System.out.println(cal.get(Calendar.SECOND));
        /**
        Calendar.YEAR:			 年
		Calendar.MONTH: 		 月(从0开始计算,因此输出显示时候要+1)
		Calendar.DAY_OF_YEAR:    一年中的第几天
		Calendar.DAY_OF_MONTH:   一月中的第几天
		Calendar.DAY_OF_WEEK:    一周中的第几天
		Calendar.HOUR: 			 时间(12小时制)
		Calendar.HOUR_OF_DAY: 	 时间(24小时制)
		Calendar.MINUTE: 		 分钟 
		Calendar.SECOND: 		 秒*/
        // 把Calendar转化为Date
        Date date = cal.getTime();
    }
}

Date时间处理

一、新建一个表示"此刻"的日期,打印出来

Date rightNow = new Date();
System.out.println("当前时刻:" + rightNow);
System.out.println("当前年份:" + rightNow.getYear());
System.out.println("当前月份:" + rightNow.getMonth());

//输出结果
当前时刻:Fri Jan 06 11:06:44 GMT+08:00 2023
当前年份:123
当前月份:0

二、构造一个指定年、月、日的时间

 Date rightNow = new Date(2023, 1, 1);

连构造函数都被弃用了
你或者想说,可以使用SimpleDateFormat

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");

LocalDateTime

自 Java8开始, JDK中其实就增加了一系列表示日期和时间的新类,最典型的就是 LocalDateTime。它的出现就是为了替换 JDK版本中的 Date。

一、首先感受一下其用法:

LocalDateTime rightNow = LocalDateTime.now();
System.out.println("当前时刻:" + rightNow);
System.out.println("当前年份:" + rightNow.getYear());
System.out.println("当前月份:" + rightNow.getMonth());
System.out.println("当前日份:" + rightNow.getDayOfMonth());
System.out.println("当前时:" + rightNow.getHour());
System.out.println("当前分:" + rightNow.getMinute());
System.out.println("当前秒:" + rightNow.getSecond());

//输出结果
当前时刻:2023-01-06T11:14:32.180
当前年份:2023
当前月份:JANUARY
当前日份:6
当前时:11
当前分:14
当前秒:32

二、构造一个指定年、月、日的时间:

LocalDateTime before = LocalDateTime.of(2020, 12, 1, 0, 0, 0);

//结果
2020-12-01T00:00

三、修改日期

LocalDateTime now = LocalDateTime.now();
// 减少三个月
LocalDateTime minusMonths = now.minusMonths(3);
//增加三个月
LocalDateTime plusMonths = now.plusMonths(3);
// 修改年份到2030
LocalDateTime withYear = now.withYear(2030);
// 修改小时到20:00
LocalDateTime withHour = now.withHour(20);

四、格式化日期

LocalDateTime rightNow = LocalDateTime.now();
String result1 = rightNow.format(DateTimeFormatter.ISO_DATE);
String result2 = rightNow.format(DateTimeFormatter.BASIC_ISO_DATE);
String result3 = rightNow.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));

System.out.println("格式化后的日期(基本样式一举例):" + result1);
System.out.println("格式化后的日期(基本样式二举例): " + result2);
System.out.println("格式化后的日期(自定义样式举例):" + result3);

//输出结果
格式化后的日期(基本样式一举例)2023-01-06
格式化后的日期(基本样式二举例)20230106
格式化后的日期(自定义样式举例)2023/01/06

五、时间反解析

给你一个陌生的字符串,你可以按照你需要的格式把时间给反解出来

LocalDateTime time = LocalDateTime.parse("2022--01--01 11:21", DateTimeFormatter.ofPattern("yyyy--MM--dd HH:mm"));
System.out.println("字符串反解析后的时间为:" + time);

//输出结果
字符串反解析后的时间为:2022-01-01T11:21

六、获取毫秒数

//获取秒数
Long second = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
//获取毫秒数
Long milliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
 

七、LocalDateTime与String互转

//时间转字符串格式化
 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
 String dateTime = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
 
//字符串转时间
String dateTimeStr = "2018-07-28 14:11:15";
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, df);

零零散散举了这么些例子,我想 LocalDateTime怎么地也不输 Date吧!

Date与LocalDate、LocalDateTime的区别

  • Date 类:

    • java.util.Date 是 Java 早期提供的日期和时间类,从 JDK 1.0 就存在。它同时包含日期和时间信息,使用一个长整型数值表示自 1970 年 1 月 1 日 00:00:00 GMT(格林尼治标准时间)起至今的毫秒数。Date 类存在一些问题,例如它不是线程安全的,而且设计上有些缺陷,因此在 Java 8 后推荐使用新的日期时间类。
  • LocalDate 类:

    • java.time.LocalDate 是 Java 8 引入的日期类,用于表示日期(年、月、日),不包含时间信息。它提供了丰富的方法来操作日期,例如获取年、月、日,进行日期比较和计算等。LocalDate 是不可变的(immutable),类似于 String,操作 LocalDate 时不会修改原始对象,而是返回一个新的对象。
  • LocalDateTime 类:

    • java.time.LocalDateTime 是 Java 8 引入的日期时间类,用于表示日期和时间,但不包含时区信息。它与 LocalDate 类似,但额外包含了时间部分(时、分、秒、毫秒)。LocalDateTime 也是不可变的,可以进行日期时间的各种操作,如格式化、加减时间等。
  1. 主要区别
  • 精度与范围

    • Date:存储的是自Unix纪元以来的毫秒数,因此它的精度是到毫秒级别。
    • LocalDate:只表示日期,没有时间信息,精度到天。
    • LocalDateTime:同时表示日期和时间,精度同样是到纳秒级别。
  • 时区

    • Date:虽然实际存储的是UTC时间戳,但是由于其设计原因,在显示和解析时可能会受到默认时区的影响。
    • LocalDate和LocalDateTime:都不包含时区信息,代表的是本地日期和时间。
  • 可变性

    • Date:是可变的,可以通过方法修改其内部值。
    • LocalDate和LocalDateTime:都是不可变的,每次更改都会返回一个新的实例。
  • 易用性与安全性

    • Date:使用起来较为繁琐,且容易出现并发问题,因为很多操作不是线程安全的。
    • LocalDate和LocalDateTime:具有更好的API设计,易于理解和使用,同时由于不可变性,更有利于编写线程安全的代码。

线程安全性问题

其实上面讲来讲去只讲了两者在用法上的差别,这其实倒还好,并不致命,可是接下来要讨论的线程安全性问题才是致命的!

其实以前我们惯用的 Date时间类是可变类,这就意味着在多线程环境下对共享 Date变量进行操作时,必须由程序员自己来保证线程安全!否则极有可能翻车。

而自 Java8开始推出的 LocalDateTime却是线程安全的,开发人员不用再考虑并发问题,这点我们从 LocalDateTime的官方源码中即可看出:

/**
 *
 * @implSpec
 * This class is immutable and thread-safe. //这个类是线程安全的
 *
 * @since 1.8
 */
public final class LocalDateTime
        implements Temporal, TemporalAdjuster, ChronoLocalDateTime<LocalDate>, Serializable {
		...        
}

日期格式化的选择

大家除了惯用 Date来表示时间之外,还有一个用于和 Date连用的 SimpleDateFormat 时间格式化类大家可能也戒不掉了!

SimpleDateFormat最主要的致命问题也是在于它本身并不线程安全,这在它的源码注释里已然告知过了:

 /* 
 * Date formats are not synchronized. //日期格式不同步。
 * It is recommended to create separate format instances for each thread.
 * If multiple threads access a format concurrently, it must be synchronized
 * externally.
 *
 * @see          java.util.Calendar
 * @see          java.util.TimeZone
 * @see          DateFormat
 * @see          DateFormatSymbols
 * @author       Mark Davis, Chen-Lieh Huang, Alan Liu
 */
public class SimpleDateFormat extends DateFormat {
	...
}

那取而代之,我们现在改用什么呢?其实在前文已经用到啦,那就是了 DateTimeFormatter了,他也是线程安全的:

/*
 * @implSpec
 * This class is immutable and thread-safe. //这个类是线程安全的
 *
 * @since 1.8
 */
public final class DateTimeFormatter {
	...
}

小结

Date或者 SimpleDateFormat是老版日期时间类,Java8提供了新版的Ap-iLocalDateTime它的出现就是为了替换 JDK版本中的 Date。在Java 8及之后的版本中,推荐尽量使用java.time.LocalDateTime来处理日期和时间,避免使用过时的java.util.Date类。如果在不同的API之间频繁进行转换,可以借助Java 8提供的日期时间API,使得操作更加直观和简洁。

java属性类型对应关系:

属性类型  -- Api
Date     -- new Date();
DateTime -- LocalDateTime

两者之间的转换关系:
将 java.util.Date 转换为 java.time.LocalDateTime:

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        // 创建一个 java.util.Date 对象
        Date utilDate = new Date();

        // 将 java.util.Date 转换为 java.time.LocalDateTime
        LocalDateTime localDateTime = utilDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();

        System.out.println("java.util.Date: " + utilDate);
        System.out.println("java.time.LocalDateTime: " + localDateTime);
    }
}

将 java.time.LocalDateTime 转换为 java.util.Date:

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        // 创建一个 java.time.LocalDateTime 对象
        LocalDateTime localDateTime = LocalDateTime.now();

        // 将 java.time.LocalDateTime 转换为 java.util.Date
        Date utilDate = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());

        System.out.println("java.time.LocalDateTime: " + localDateTime);
        System.out.println("java.util.Date: " + utilDate);
    }
}

在上面的代码示例中,我们使用了Date.from()方法将java.time.LocalDateTime转换为java.util.Date,以及使用java.util.Date的toInstant()方法将其转换为java.time.LocalDateTime。需要注意的是,在这些转换过程中,时区的信息也被考虑进去了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芝士汉堡 ིྀིྀ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值