Java Review (二十一、基础类库----日期、时间类)

简介: Java Review (二十一、基础类库----日期、时间类)

     

文章目录

Java 原本提供了 Date 和 Calendar 用于处理日期、时间的类,包括创建日期 、  时间对象,获取系统当前日期、时间等操作 。 但 Date 不仅无法实现国际化 ,而且它对不同属性也使用了前后矛盾的偏移量 ,比如月份与小时都是从  0 开始的,月份中的天数则是从 1 开始的,年又是从 1900 开始的,而java.util.Calendar 则显得过于复杂  ,从下面介绍中会看到传统 Java 对日期、时间处理的不足 。 Java 8 吸取了 Joda-Time 库( 一个被广泛使用的日期、  时间库)的经验 , 提供了一套全新的日期时间库 。

在计算机中只需要存储一个整数表示某一时刻。当需要显示为某一地区的当地时间时,就把它格式化为一个字符串

Date 类

  • Date(): 生成一个代表当前日期时间的 Date 对象 。 该构造器在底层调用 System .currentTimeMillis()获得 long 整数作为日期参数。
  • Date(long  date): 根据指定的 long 型整数来生成一个 Date 对象 。该构造器的参数表示创建的 Date对象和 GMT 1970 年 1 月  1 日 00:00:00 之间的时间差 ,以毫秒作为计时单位 。与 Date 构造器相同的是, Date 对象的大部分方法也  Deprecated 了, 剩下为数不多的几个方法。
  • boolean after(Date when): 测试该日期是否在指定日期 when 之后 。
  • boolean before(Date when): 测试该日期是否在指定日期 when 之前 。
  • long getTime(): 返回该时间对应的 long 型整数 ,即从 GMT 1970-01-0100:00:00 到该 Date 对象
    之间的时间差,以毫秒作为计时单位。
  • void setTime(long time): 设置该 Date 对象的时间。

下面程序示范了 Date 类的用法 :

DateTest.java

public class DateTest
{
  public static void main(String[] args)
  {
    Date d1 = new Date();
    // 获取当前时间之后100ms的时间
    Date d2 = new Date(System.currentTimeMillis() + 100);
    System.out.println(d2);
    System.out.println(d1.compareTo(d2));
    System.out.println(d1.before(d2));
    //自定义输出时间日期
    // 获取当前时间:
        Date d3 = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(sdf.format(d3));
  }
}

Date对象有几个严重的问题:它不能转换时区,除了toGMTString()可以按GMT+0:00输出外,Date总是以当前计算机系统的默认时区为基础进行输出。此外,我们也很难对日期和时间进行加减,计算两个日期相差多少天,计算某个月第一个星期一的日期等。

API:java.util.Date

Calendar 类

因为 Date 类在设计上存在一些缺陷,所以 Java 提供了 Calendar 类来更好地处理日期和时间 。

Calendar 类本身是一个抽象类,它是所有日历类的模板,并提供了一些所有日历通用的方法 。

它本身不能直接实例化,程序只能创建 Calendar 子类的实例, Java 本身提供了 一个 GregorianCalendar 类,一个代表格里高利日历的子类,它代表了通常所说的公历 。

当然,也可以创建自己的 Calendar 子类,然后将它作为 Calendar 对象使用。

Calendar 类是一个抽象类,所以不能使用构造器来创建 Calendar 对象 。 但它提供了几个静态getInstance()方法来获取 Calendar 对象。

Calendar 与 Date 都是表示日期的工具类,它们 直接可以自由转换,如下代码所示 :

// 创建一个默认的 Calendar 对象
Calendar calendar = Calendar.getlnstance();
// 从 Calendar 对象中取出 Date 对象
Date date = calendar .getTime();
// 通过 Date 对象获得对应的 Calendar 对象
// 因为 Calendar / GregorianCalendar 没有构造函数可以接收 Date 对象
// 所以必须先获得一个 C alendar 实例,然后调用其 setTime () 方法
Calendar calendar2 = Calendar . getInstance();
calendar2.setTime(date);

Calendar 类提供了大量访问、修改日期时间的方法,常用 方法如下 。

  • void add(int field, int amount): 根据日历的规则,为给定的日历宇段添加或减去指定的时间量 。
  • int get(int field): 返回指定日历宇段的值 。
  • int getActualMaximum(int field): 返回指定日历字段可能拥有的最大值 。 例如月,最大值为 11 。
  • int getActualMinimum(int field): 返回指定日历字段可能拥有的最小值 。 例如月,最小值为 0 。
  • void roll(int field, int amount): 与 addO方法类似,区别在于加上 amount 后超过了该字段所能表
    示的最大范围时,也不会向上一个字段进位 。
  • void set(int field, int value): 将给定的日历宇段设置为给定值 。
  • void set(int year, int month, int date): 设置 Calendar 对象的年、月、日 三个字段的值 。
  • void set(int year, int month, int date, int hourOfDa弘 int minute, int second): 设置 Calendar 对象的年、月、日、时、分、秒 6 个字段的值 。

上面的很多方法都需要一个 int 类型的 field 参数, field 是 Calendar 类的类变量 :

类变量 描述
Calendar.YEAR 年份
Calendar.MONTH 月份
Calendar.DATE 日期
Calendar.DAY_OF_MONTH 日期,和上面的字段意义完全相同
Calendar.HOUR 12小时制的小时
Calendar.HOUR_OF_DAY 24小时制的小时
Calendar.MINUTE 分钟
Calendar.SECOND
Calendar.DAY_OF_WEEK 星期几

CalendarTest.java

public class CalendarTest
{
  public static void main(String[] args)
  {
    Calendar c = Calendar.getInstance();
    // 取出年
    System.out.println(c.get(YEAR));
    // 取出月份
    System.out.println(c.get(MONTH));
    // 取出日
    System.out.println(c.get(DATE));
    // 分别设置年、月、日、小时、分钟、秒
    c.set(2003 , 10 , 23 , 12, 32, 23); //2003-11-23 12:32:23
    System.out.println(c.getTime());
    // 将Calendar的年前推1年
    c.add(YEAR , -1); //2002-11-23 12:32:23
    System.out.println(c.getTime());
    // 将Calendar的月前推8个月
    c.roll(MONTH , -8); //2002-03-23 12:32:23
    System.out.println(c.getTime());
    Calendar cal1 = Calendar.getInstance();
    cal1.set(2003, 7, 23, 0, 0 , 0); // 2003-8-23
    cal1.add(MONTH, 6); //2003-8-23 => 2004-2-23
    System.out.println(cal1.getTime());
    Calendar cal2 = Calendar.getInstance();
    cal2.set(2003, 7, 31, 0, 0 , 0); // 2003-8-31
    // 因为进位到后月份改为2月,2月没有31日,自动变成29日
    cal2.add(MONTH, 6); // 2003-8-31 => 2004-2-29
    System.out.println(cal2.getTime());
    Calendar cal3 = Calendar.getInstance();
    cal3.set(2003, 7, 23, 0, 0 , 0); //2003-8-23
    // MONTH字段“进位”,但YEAR字段并不增加
    cal3.roll(MONTH, 6); //2003-8-23 => 2003-2-23
    System.out.println(cal3.getTime());
    Calendar cal4 = Calendar.getInstance();
    cal4.set(2003, 7, 31, 0, 0 , 0); //2003-8-31
    // MONTH字段“进位”后变成2,2月没有31日,
    // YEAR字段不会改变,2003年2月只有28天
    cal4.roll(MONTH, 6); //2003-8-31 => 2003-2-28
    System.out.println(cal4.getTime());
  }
}

API:java.util.Calnedar

API:java.util.GregorianCalendar

Java 8 新增的日期、时间包

Java 8 开始专 门新增了 一个 java.time 包, 该包下包含了 如下常用的类 :

  • Clock: 该类用于获取指定时区的当前 日期、时间 。 该类可取代 System 类的 currentTimeMillis()方法,而且提供了更多方法来获取当前日期、时间 。 该类提供了大量静态方法来获取 Clock 对
    象 。
  • Duration: 该类代表持续时间 。 该类可 以非常方便地获取一段时间 。
  • Instant:  代表一个具体的时刻,可以精确到纳秒 。 该类提供了静态 的 now()方法来获取当前时刻,也提供了 静态的 now(Clock  clock)方法来获取 clock 对应的时刻 。 除此之外, 它还提供了 一系列minusXxx()方法在当前时刻基础上减去一段时间 ,  也提供了 plusXxx()方法在当前时刻基础上加上一段时 间 。
  • LocalDate: 该类代表不带时区的日期 ,例如  2007-12-03 。 该类提供了静态的 now()方法来获取当前日期,也提供了静态的 now(Clock clock)方法来获取 clock  对应的日期 。 除此之外 , 它还提供了 rninusXxxO方法在当前年份基础上减去几年、几月、几周或几日等,也提供了  plusXxx()方法在当前年份基础上加上几年、几月、几周或几日等 。
  • LocalTime: 该类代表不带时 区的 时间,例如 10:15 : 30 。 该类提供了静态的 now()方法来获取当
    前时间,也提供了静态的 now(Clock clock)方法来获取 clock 对应的时间 。 除此之外,它还提供
    了 rninusXxx()方法在当前年份基础上减去几小时、几分、几秒等,也提供了plusXxx()方法在当前年份基础上加上几小时、几分、 几秒等。
  • LocalDateTime:  该类代表不带时区的日期 、时间, 例如 2007-12-03Tl 0: 15 :3 0 。 该类提供了静态的 now()方法来获取当前日期、  时间,也提供 了静态的 now(Clock clock)方法来获取 clock 对应的日期、时间 。 除此之外,它还提供了  minusXxx()方法在当前年份基础上减去几年 、几月 、几日、几小时、几分、 几秒等, 也提供 了  plusXxxO方法在当前年份基础上加上几年、几月 、几日、几小时、几分 、 几秒等 。
  • MonthDay: 该类仅代表月日 ,例如一04-12 。 该类提供了静态 的 nowO方法来获取当前月日 ,也提供了静态的 now(Clock clock)方法来获取 clock 对应的月日 。
  • Year:  该类仅代表年,例如 2014 。 该类提供了静态的 now()方法来获取当前年份 ,也提供了静态的 now(Clock clock)方法来获取  clock 对应的年份 。 除此之外,它还提供了 rninusYears()方法在当前年份基础上减去几年 ,也提供了  plusYearsO方法在当前年份基础上加上几年 。
  • YearMonth: 该类仅代表年月 ,例如 2014-04 。  该类提供了静态的 nowO方法来获取当前年月,也提供了静态的 now(Clock clock)方 法来获取 clock 对 应的年月 。  除此之外 ,它还提供了rninusXxx()方法在当前年月基础上减去几年 、几月 ,也提供了  plusXxx()方法在当前年月基础上加上几年、几月 。
  • ZonedDateTime: 该类代表一个时区化的日期 、时间 。
  • Zoneld: 该类代表一个时区 。
  • DayOtweek: 这是一个枚举类,定义了周日到周六的枚举值 。
  • Month: 这也是一个枚举类,定义了 一月到十二月的枚举值 。

        NewDatePackageTest.java  
public class NewDatePackageTest
{
  public static void main(String[] args)
  {
    // -----下面是关于Clock的用法-----
    // 获取当前Clock
    Clock clock = Clock.systemUTC();
    // 通过Clock获取当前时刻
    System.out.println("当前时刻为:" + clock.instant());
    // 获取clock对应的毫秒数,与System.currentTimeMillis()输出相同
    System.out.println(clock.millis());
    System.out.println(System.currentTimeMillis());
    // -----下面是关于Duration的用法-----
    Duration d = Duration.ofSeconds(6000);
    System.out.println("6000秒相当于" + d.toMinutes() + "分");
    System.out.println("6000秒相当于" + d.toHours() + "小时");
    System.out.println("6000秒相当于" + d.toDays() + "天");
    // 在clock基础上增加6000秒,返回新的Clock
    Clock clock2 = Clock.offset(clock, d);
    // 可看到clock2与clock1相差1小时40分
    System.out.println("当前时刻加6000秒为:" +clock2.instant());
    // -----下面是关于Instant的用法-----
    // 获取当前时间
    Instant instant = Instant.now();
    System.out.println(instant);
    // instant添加6000秒(即100分钟),返回新的Instant
    Instant instant2 = instant.plusSeconds(6000);
    System.out.println(instant2);
    // 根据字符串中解析Instant对象
    Instant instant3 = Instant.parse("2014-02-23T10:12:35.342Z");
    System.out.println(instant3);
    // 在instant3的基础上添加5小时4分钟
    Instant instant4 = instant3.plus(Duration
      .ofHours(5).plusMinutes(4));
    System.out.println(instant4);
    // 获取instant4的5天以前的时刻
    Instant instant5 = instant4.minus(Duration.ofDays(5));
    System.out.println(instant5);
    // -----下面是关于LocalDate的用法-----
    LocalDate localDate = LocalDate.now();
    System.out.println(localDate);
    // 获得2014年的第146天
    localDate = LocalDate.ofYearDay(2014, 146);
    System.out.println(localDate); // 2014-05-26
    // 设置为2014年5月21日
    localDate = LocalDate.of(2014, Month.MAY, 21);
    System.out.println(localDate); // 2014-05-21
    // -----下面是关于LocalTime的用法-----
    // 获取当前时间
    LocalTime localTime = LocalTime.now();
    // 设置为22点33分
    localTime = LocalTime.of(22, 33);
    System.out.println(localTime); // 22:33
    // 返回一天中的第5503秒
    localTime = LocalTime.ofSecondOfDay(5503);
    System.out.println(localTime); // 01:31:43
    // -----下面是关于localDateTime的用法-----
    // 获取当前日期、时间
    LocalDateTime localDateTime = LocalDateTime.now();
    // 当前日期、时间加上25小时3分钟
    LocalDateTime future = localDateTime.plusHours(25).plusMinutes(3);
    System.out.println("当前日期、时间的25小时3分之后:" + future);
    // 下面是关于Year、YearMonth、MonthDay的用法示例-----
    Year year = Year.now(); // 获取当前的年份
    System.out.println("当前年份:" + year); // 输出当前年份
    year = year.plusYears(5); // 当前年份再加5年
    System.out.println("当前年份再过5年:" + year);
    // 根据指定月份获取YearMonth
    YearMonth ym = year.atMonth(10);
    System.out.println("year年10月:" + ym); // 输出XXXX-10,XXXX代表当前年份
    // 当前年月再加5年,减3个月
    ym = ym.plusYears(5).minusMonths(3);
    System.out.println("year年10月再加5年、减3个月:" + ym);
    MonthDay md = MonthDay.now();
    System.out.println("当前月日:" + md); // 输出--XX-XX,代表几月几日
    // 设置为5月23日
    MonthDay md2 = md.with(Month.MAY).withDayOfMonth(23);
    System.out.println("5月23日为:" + md2); // 输出--05-23
  }
}

API:java.time


参考:

【1】:《疯狂Java讲义》

【2】:Date和Calendar

【3】:Java 日期时间

【4】:LocalDateTime详解

【5】:ZonedDateTime详解

【6】:DateTimeFormatter详解

【7】:Java日期时间新旧API转换、在数据库中存储日期和时间


目录
相关文章
|
2天前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
|
19天前
|
存储 安全 Java
java.util的Collections类
Collections 类位于 java.util 包下,提供了许多有用的对象和方法,来简化java中集合的创建、处理和多线程管理。掌握此类将非常有助于提升开发效率和维护代码的简洁性,同时对于程序的稳定性和安全性有大有帮助。
41 17
|
11天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
15天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
55 4
|
16天前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
34 2
|
20天前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
|
24天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
24天前
|
Java API Maven
如何使用 Java 字节码工具检查类文件的完整性
本文介绍如何利用Java字节码工具来检测类文件的完整性和有效性,确保类文件未被篡改或损坏,适用于开发和维护阶段的代码质量控制。
|
24天前
|
存储 Java 编译器
java wrapper是什么类
【10月更文挑战第16天】
27 3
|
27天前
|
Java 程序员 测试技术
Java|让 JUnit4 测试类自动注入 logger 和被测 Service
本文介绍如何通过自定义 IDEA 的 JUnit4 Test Class 模板,实现生成测试类时自动注入 logger 和被测 Service。
23 5
下一篇
无影云桌面