美文网首页
Java中的日期和时间

Java中的日期和时间

作者: 仲伦 | 来源:发表于2019-10-22 14:37 被阅读0次

    根据个人目前正在编写的《Java核心编程-基础篇》的规划,这部分属于第15章内容,这里沿用了书中的章节编号。另外,因为原文篇幅太长,这里适当做了删减。

    15.1、概述

    在 Java 8 之前,Java 语言表示时间的方法很简单,几乎都是采用毫秒值来表示时间。

    比如获得系统当前时间可以使用以下方法:

    long now = System.currentTimeMillis();
    System.out.println( now );
    

    这里获取的毫秒值是从 格里高利历 的 1970年1月1日 0点0分0秒0毫秒 至现在所经历的毫秒数。

    即使是在 java.util.Date 类的实例 或 java.util.Calendar类的实例中,也仍然是通过毫秒值来表示时间。

    因为 java.util.Date 类的实例 或 java.util.Calendar类在设计上的缺陷,

    从 Java 8 开始提供了一个全新的包 (java.time ) 来表示时区、日期、时间。

    接下来我们将从 DateCalendar 说起,来研究 时期、时间的表示方法 以及 日期格式化 等操作。

    15.2、Date 类

    Date 类的实例表示特定的瞬间( 精确到毫秒 )。

    package java.util;
    
    import java.io.Serializable ;
    
    public class Date implements Serializable, Cloneable, Comparable<Date> {
        
    }
    

    Date 类实现了 SerializableCloneableComparable 等接口。

    15.2.1、实例字段

    Date 类中封装了一个 long 类型的字段,用来保存 Date 实例所表示的时间:

    private transient long fastTime;
    

    15.2.2、构造方法

    目前还有两个未被废弃的构造方法:

    public Date( long millis ) {
        fastTime = millis ;
    }
    
    public Date() {
        this( System.currentTimeMillis() );
    }
    

    举例:

    import java.util.Date;
    
    public class DateTest1 {
        public static void main(String[] args) {
            // 构造方法内部将 System.currentTimeMillis() 保存到 fastTime 字段中
            Date date = new Date();
            System.out.println( date ); // CST : China Standard Time
    
            // 构造方法内部将 -1000L 保存到 fastTime 字段中
            Date d = new Date( -1000L );
            System.out.println( d );
        }
    }
    

    注意,输出 date 对象的字符串形式时,CST 表示 China Standard Time ,即中国标准时间。

    15.2.3、实例方法

    Date 类中绝大多数实例方法都已经被废弃(不赞成使用),仅存的几个可用的实例方法如下:

    • public long getTime()

    获取 Date 实例内部存储的毫秒值。

    • public void setTime( long time )

    设置 Date 实例内部存储的毫秒值。

    • public String toString()

    将当前 Date 实例所存储的毫秒值转换为以下形式的 字符串:

    dow mon dd hh:mm:ss zzz yyyy

    其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。

    • public boolean equals( Object obj )

    Date 类重写了从 Object 类继承的 equals 方法用于判断当前 Date 实例与另外一个对象是否"相等"。

    • public boolean after( Date when )

    测试 当前 Date 实例 所表示的时间 是否在 指定Date实例 所表示的时间之后。

    • public boolean before( Date when )

    测试 当前 Date 实例 所表示的时间 是否在 指定Date实例 所表示的时间之前。

    15.2.3.1、Date实例是可变的

    Date 实例 是 【可变的】,在创建 Date 实例后,其内部的 毫秒值 是可以更改的

    import java.util.Date;
    
    public class DateTest2 {
    
        public static void main(String[] args) {
    
            long ms = 1000L * 60 * 60 * 24 * 365 * 30 ;
    
            final Date date = new Date( ms );
            System.out.println( date );
    
            birthdate.setTime( 1000 );
            System.out.println( date );
            
        }
    
    }
    

    15.2.3.2、比较Date实例

    Date实例的比较,可以通过 equalsafterbefore 方法来实现:

    import java.util.Date;
    
    public class DateTest3 {
    
        public static void main(String[] args) {
    
            long ms = 1000L * 60 * 60 * 24 * 365 * 30 ;
    
            Date first = new Date( ms );
            System.out.println( first );
    
            Date second = new Date( ms );
            System.out.println( second );
    
            System.out.println( first == second ); // false
            // java.utl.Date 类 重写了 从 Object 类继承的 equals 方法
            System.out.println( first.equals( second ) ); // true
    
            Date now = new Date();
            System.out.println( now.after( first ) ); // true
            System.out.println( now.after( second ) ); // true
    
            System.out.println( first.before( now ) ); // true
            System.out.println( second.before( now ) ); // true
    
        }
    
    }
    

    不建议使用的比较方法是这样子的:

            long firstTime = first.getTime() ;
            long secondTime = second.getTime() ;
            if( firstTime > secondTime ) {
                System.out.println( first + " 晚于 " + second );
            }
    

    15.3 Calendar类

    Calendar一词表示日历,而 Java 语言中 Calendar 则是一个类,一个声明在 java.util 包中的抽象类。

    Calendar 类为<b style="color:blue;">特定瞬间</b>与<b style="color:blue;">日历字段</b>之间的转换提供了一些方法,并为操作日历字段提供了一些方法

    瞬间可用毫秒值来表示,它是距历元的偏移量。

    历元(epoch) 是指 格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000 ( 格里高利历 ) 。

    15.3.1、日历字段

    日历字段是 Calendar 类中声明的用来表示日期时间中指定部分的常量。
    常用的日历字段如下:

    • Calendar.ERA 对应纪元

    比如罗马儒略历中的 AD 或 BC ( 中文表示为 公元 或 公元前 )

    • Calendar.YEAR 对应年份

    • Calendar.MONTH 对应月份

    月份从 0 开始计数,0 表示 January (一月),1 表示 February ( 二月 )

    • Calendar.DATE 对应月份中的日期

    日期从 1 开始计数,有效范围为 1 ~ 31 。

    • Calendar.HOUR_OF_DAY 对应一天当中的小时

    小时从 0 开始计数,有效范围为 0 ~ 23 。

    • Calendar.MINUTE 对应分钟

    分钟从 0 开始计数,有效范围为 0 ~ 59 。

    • Calendar.SECOND 对应秒

    秒数从 0 开始计数,有效范围为 0 ~ 60 。(要注意闰秒)

    • Calendar.MILLISECOND 对应毫秒

    毫秒数从 0 开始计数,有效范围为 0 ~ 999 。

    • Calendar.DAY_OF_MONTH 对应月份中的日期

    日期从 1 开始计数,有效范围为 1 ~ 31 。

    • Calendar.HOUR 对应上午或下午的小时

    小时从 0 开始计数,有效范围为 0 ~ 11 。

    • Calendar.DAY_OF_WEEK 对应星期

    用于指示一个星期中的某天。

    该字段可取的值可以是 SUNDAYMONDAYTUESDAYWEDNESDAYTHURSDAYFRIDAYSATURDAY

    • Calendar.DAY_OF_YEAR 对应年份中的天数

    指示当前年中的天数。一年中第一天的值为 1,最大值为 366 。

    15.3.2、获取Calendar实例

    15.3.2.1、通过创建子类实例的方式

    GregorianCalendar 类是 Calendar 类的子类,

    通过创建 GregorianCalendar类的实例即可使用 Calendar 中的方法。

    Calendar c = new GregorianCalendar(); // 父类引用 指向 子类对象
    System.out.println( c );
    

    15.3.2.2、通过类方法获取

    Calendar 类中定义了大量的类方法用于获取 Calendar 实例:

    • public static Calendar getInstance()

    举例:

    Calendar c = Calendar.getInstance();
    System.out.println( c );
    
    • public static Calendar getInstance( TimeZone zone, Locale locale )

    举例:

    TimeZone zone = TimeZone.getDefault();
    Locale locale = Locale.getDefault() ;
    
    Calendar c = Calendar.getInstance( zone , locale );
    System.out.println( c );
    

    15.3.3、从 Calendar 实例中获取时间

    Calendar 类中声明了以下方法用于从 特定瞬间 中获取 指定日历字段 对应的值:

    public int get( int calendarField )
    

    同时在 Calendar 类中声明了以下方法用于获取 Calendar实例所表示的瞬间对应的毫秒值:

    public long getTimeInMillis()
    

    举例:

    import java.util.Calendar;
    import java.util.GregorianCalendar;
    
    public class CalendarTest1 {
    
        public static void main(String[] args) {
    
            // 父类引用 指向 子类对象
            Calendar c = new GregorianCalendar();
            System.out.println( c );
    
            // 从 c 对应的 Calendar 实例中获取 日历字段 ERA 对应的值
            int era = c.get( Calendar.ERA ) ; 
            System.out.println( era );
    
            int year = c.get( Calendar.YEAR );
            System.out.println( year );
    
            // 在西方国家,月份的索引从 零 开始,0 表示 1月 , 11 表示12月
            int month = c.get( Calendar.MONTH ); 
            System.out.println( month );
    
            int date = c.get( Calendar.DATE );
            System.out.println( date );
    
            int hourOfDay = c.get( Calendar.HOUR_OF_DAY );
            System.out.println( hourOfDay );
    
            int minute = c.get( Calendar.MINUTE );
            System.out.println( minute );
    
            int second = c.get( Calendar.SECOND );
            System.out.println( second );
    
            // 仅仅获取 MILLISECOND 字段对应的值,取值范围为 [ 0 , 1000 )
            int millis = c.get( Calendar.MILLISECOND ); 
            System.out.println( millis );
            
            System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
    
            // 获取 当前的 Calendar 实例所表示的瞬间 对应的毫秒值(距离历元的偏移量)
            long ms = c.getTimeInMillis(); 
            System.out.println( ms );
            
        }
    
    }
    

    15.3.4、设置 Calendar 实例

    Calendar 类中声明了以下方法用于用于为 指定的 日历字段 设置相应的值:

    public void set( int calendarField, int value )
    

    同时也提供了以下方法来批量设置年、月、日、小时、分钟、秒、毫秒等 日历字段 的值

    public final void set( int year, int month, int date )
    public final void set( int year, int month, int date, int hourOfDay )
    public final void set( int year, int month, int date, int hourOfDay, int minute,int second )
    

    需要注意的是,这里的 hourOfDayCalendar.HOUR_OF_DAY对应,表示一天中的小时,取值范围是 0 ~ 23 。

    另外,Calendar 类中声明了用于清空所有日历字段取值的方法:

    public final void clear()
    

    Calendar 类中也声明了用于清空指定的 日历字段取值的方法:

    public final void clear( int calendarField )
    

    举例:

    import java.util.*;
    
    public class CalendarTest3 {
    
        public static void main(String[] args) {
    
            // 父类引用 指向 子类对象
            Calendar c = new GregorianCalendar();
            System.out.println( c );
    
            c.set( Calendar.YEAR , 1996 ); // 公元1996年
            c.set( Calendar.MONTH , 0 ); // 月份的索引从 0 开始,0表示1月
            c.set( Calendar.DATE , 10 );
            c.set( Calendar.HOUR_OF_DAY , 11 );
            c.set( Calendar.MINUTE , 45 );
            c.set( Calendar.SECOND , 0 );
            c.set( Calendar.MILLISECOND , 0 );
            System.out.println( c );
    
            System.out.println( c.getTimeInMillis() );
            System.out.println( c );
    
            System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
    
            c.clear(); // 清除所有日历字段的值
            System.out.println( c );
    
            // YEAR 、MONTH 、HOUR_OF_DAY 、MINUTE、SECOND
            c.set( 0 , 0 , 10 , 11 , 45 , 30 );
            c.set( Calendar.MILLISECOND , 100 );
    
            System.out.println( c.getTimeInMillis() );
            System.out.println( c );
    
        }
    
    }
    
    

    15.3.5、将 Calendar 实例转换为 Date类型的实例

    Calendar 类中声明了用于将当前的Calendar实例所表示的瞬间转换为Date实例的方法:

    public final Date getTime()
    

    举例:

    import java.util.*;
    
    public class CalendarTest2 {
    
        public static void main(String[] args) {
    
            // 父类引用 指向 子类对象
            Calendar c = new GregorianCalendar();
            System.out.println( c );
    
            // java.util.Date 类中的 getTime() 方法可以返回一个毫秒值
            // java.util.Calendar 类中的 getTime() 用于返回相应的 Date 实例
            Date date = c.getTime(); // 返回 当前 Calendar 实例所表示的瞬间 对应的 Date 实例
            System.out.println( date );
    
        }
    
    }
    
    

    15.3.6、获取任意时间对应的Date实例

    截至目前,我们可以借助于 Calendar 实例来获取任意时间对应的 Date 实例,其步骤为

    • a>、获得 Calendar 实例
    • b>、清空所有日历字段的值
    • c>、根据实际需要设置 年月日、时分秒 等日历字段的值
    • d>、获取 Calendar 实例所表示的瞬间 对应的 Date 实例

    举例:

    import java.util.*;
    
    public class CalendarTest4 {
    
        public static void main(String[] args) {
    
            TimeZone zone = TimeZone.getDefault();
            Locale locale = Locale.getDefault() ;
    
            // 1、获得 Calendar 实例
            Calendar c = Calendar.getInstance( zone , locale );
            System.out.println( c );
    
            // 2、清空所有日历字段的值
            c.clear();
    
            // 3、根据实际需要设置 年月日、时分秒
            c.set( 1998 , 10 , 20 , 5 , 30 , 40 );
            c.set( Calendar.MILLISECOND , 0 );
    
            // 4、获取 Calendar 实例所表示的瞬间 对应的 Date 实例
            Date date = c.getTime();
            System.out.println( date );
    
        }
    
    }
    

    在 Java 8 之前,获得 任意的 年月日、时分秒 对应的 Date 实例,可以使用两种方法:

    • 通过将特定格式的字符串解析为Date实例 ( 在 DateFormat 中讲解 )
    • 通过 Calendar 实例来获取

    15.4 DateFormat 类

    java.text.DateFormat 类提供了用于将日期格式化和解析字符串为Date实例的方法:

    public final String format( Date date )
    public Date parse(String source) throws ParseException
    

    但是 DateFormat 类是个抽象类,其子类 SimpleDateFormat 是个具体类(非抽象类)。

    SimpleDateFormat 类的构造方法:

    public SimpleDateFormat()
    public SimpleDateFormat( String pattern )
    public SimpleDateFormat( String pattern , Locale locale )
    public SimpleDateFormat( String pattern , DateFormatSymbols formatSymbols )
    

    其中最常用的是:

    public SimpleDateFormat( String pattern )
    

    参数中的 pattern 表示日期的模式。

    日期模式的字符串可以使用以下模式字母:

    dateformat-pattern.png

    比如 yyyy-MM-dd 对应 1996-12-12

    15.4.1、日期格式化

    日期格式化举例:

    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Locale;
    
    /**
     * 重要: 将 java.util.Date 实例所表示的 【瞬间】 格式化为 【特定模式】的字符串
     */
    public class DateFormatTest1 {
    
        public static void main(String[] args) {
    
            long ms = 1000L * 60 * 60 * 24 * 365 * 30 ;
    
            Date birthdate = new Date( ms );
    
            String pattern = "G yyyy年MM月dd日 EEEE HH:mm:ss.SSS" ; // 确定 "日期时间" 的模式
    
            DateFormat df = new SimpleDateFormat( pattern );
    
            String s = df.format( birthdate );
    
            System.out.println( s );
    
        }
    
    }
    

    15.4.2、解析字符串为Date实例

    将指定字符串按照特定的模式解析为 Date 实例:

    import java.text.DateFormat;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Locale;
    import java.util.Scanner;
    
    /**
     * 重要: 将 字符串 解析为 java.util.Date 实例
     */
    public class DateFormatTest2 {
    
        public static void main(String[] args) {
    
            final String pattern = "yyyy-MM-dd" ;
            DateFormat df = new SimpleDateFormat( pattern );
    
            Scanner sc = new Scanner( System.in );// 创建扫描器用户读取用户输入的数据
    
            System.out.println( "请输入一个日期( 格式为 " + pattern + " ,比如 2019-09-01 )" );
            String s = sc.nextLine(); // 读取用户输入的整行数据
            System.out.println( "你输入的是: " + s );
    
            try {
                // 将 字符串 解析为 Date 类型的实例
                Date date = df.parse( s ); // 可能抛出 ParseException 异常
                System.out.println( date );
                long time = date.getTime() ;
                System.out.println( time );
            } catch ( ParseException e ) {
                System.out.println( "你输入的日期格式不符合 " + pattern );
                e.printStackTrace();
            }
    
            sc.close(); // 关闭扫描器
        }
    
    }
    

    15.5 LocalDate类

    有鉴于 java.util.Date 类 和 java.util.Calendar 类在设计上的缺陷,从 Java 8 开始,JDK 中新增了 java.time 包,其中定义了大量的用来表示日期、时间的类型。

    15.5.1、LocalDate类的设计

    java.time.LocalDate 类是一个不可变类,该类是被 final 所修饰,因此该类没有子类。

    package java.time;
    
    // 省略 import 语句
    
    public final class LocalDate
           implements Temporal, TemporalAdjuster, ChronoLocalDate, Serializable {
        // 省略其它代码
        private final int year; // The year.
        private final short month; // The month-of-year.
        private final short day; // The day-of-month.
        // 省略其它代码  
    }
    

    java.time.LocalDate 类中声明了三个实例字段用来存储 年份、月份、日期:

        private final int year;
        private final short month;
        private final short day;
    

    因为它们都是 final 修饰的,因此一旦创建 LocalDate 实例,其 年份、月份、日期 的值再也不能被更改。

    另外,LocalDate 类还声明了以下常量:

        public static final LocalDate MIN = LocalDate.of( Year.MIN_VALUE, 1, 1 );
        public static final LocalDate MAX = LocalDate.of( Year.MAX_VALUE, 12, 31 );
        public static final LocalDate EPOCH = LocalDate.of( 1970, 1, 1 );
    

    从常量命名可知,MAXMIN 分别表示 LocalDate 所能表示的日期的最大值和最小值。

    EPOCH 则表示历元对应的日期。

    15.5.2、获取 LocalDate 实例

    java.time.LocalDate 类提供了许多类方法用于获取 LocalDate 实例,以下是几个常用的方法:

    public static LocalDate now() 
    public static LocalDate of( int year , int month , int dayOfMonth ) 
    public static LocalDate ofYearDay( int year , int dayOfYear )
    

    举例:

    import java.time.LocalDate;
    
    
    public class LocalDateTest1 {
    
        public static void main(String[] args) {
    
            // 通过 LocalDate 类中的 类方法 ( now ) 来获取 LocalDate 实例
            LocalDate now = LocalDate.now();
            System.out.println( now );
    
            // 通过 LocalDate 类中的 类方法 ( of ) 来获取 LocalDate 实例
            LocalDate birthdate = LocalDate.of( 1999 , 12 , 31 );
            System.out.println( birthdate );
    
            // 通过 LocalDate 类中的 类方法 ( ofYearDay ) 来获取 LocalDate 实例
            LocalDate date = LocalDate.ofYearDay( 2019 , 244 );
            System.out.println( date );
    
        }
    
    }
    

    15.5.3、常用实例方法

    LocalDate 类中定义了大量的实例方法,其中比较常用的是:

    • public int getYear() 用于获取年份
    • public int getMonthValue() 用于获取月份 ( 取值范围是 1 ~ 12 )
    • public int getDayOfMonth() 用于获取日期 ( 取值范围是 1 ~ 31 )
    • public DayOfWeek getDayOfWeek() 用于获取星期 ( 返回类型为 DayOfWeek )
    • public boolean isLeapYear() 用于判断 LocalDate 实例对应的年份是否是闰年
    • public int lengthOfYear() 用于获取 LocalDate 实例对应的年份的总天数
    • public int lengthOfMonth() 用于获取 LocalDate 实例对应的月份的总天数

    举例:

    import java.time.DayOfWeek;
    import java.time.LocalDate;
    
    public class LocalDateTest2 {
    
        public static void main(String[] args) {
    
            LocalDate n = LocalDate.now() ;
    
            System.out.println( n.getYear() + "年" );
            System.out.println( n.getMonthValue() + "月" );
            System.out.println( n.getDayOfMonth() + "日" );
    
            System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
    
            DayOfWeek day = n.getDayOfWeek();
            System.out.println( day );
    
            System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
    
            boolean leap = n.isLeapYear();
            System.out.println( leap );
    
            System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
    
            System.out.println( n.lengthOfYear() );
            System.out.println( n.lengthOfMonth() );
    
        }
    
    }
    

    同时,LocalDate 类中定义了用于比较 LocalDate 实例的方法:

    public boolean equals( Object obj )
    public boolean isEqual( ChronoLocalDate other )
    public boolean isBefore( ChronoLocalDate other )
    public boolean isAfter( ChronoLocalDate other )
    

    另外,LocalDate 类还定义了 在指定的 LocalDate 对应的日期基础上 增加或减少 指定时间的方法:

    public LocalDate plusYears( long yearsToAdd )
    public LocalDate plusDays( long daysToAdd ) 
    public LocalDate plusMonths( long monthsToAdd )
    public LocalDate plusWeeks( long weeksToAdd )
    

    举例:

    import java.time.DayOfWeek;
    import java.time.LocalDate;
    
    
    public class LocalDateTest3 {
    
        public static void main(String[] args) {
    
            LocalDate n = LocalDate.now(); // 获得当前日期
            System.out.println( n );
    
            System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
    
            // 在 n 所表示的日期基础上减少18年后返回 新的 LocalDate 实例
            LocalDate f = n.plusYears( -18 ); 
            System.out.println( f );
    
            System.out.println( n == f );
            System.out.println( n.equals( f ) );
            System.out.println( n.isEqual( f ) ); // 比较两个 LocalDate 实例是否相等
            System.out.println( n.isAfter( f ) );
            System.out.println( n.isBefore( f ) );
    
            System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
    
            // 在 f 所表示的日期基础上增加18年后返回 新的 LocalDate 实例
            LocalDate s = f.plusYears( 18 ); 
            System.out.println( s == n );
            System.out.println( s.equals( n ) );
            System.out.println( s.isEqual( n ) );
    
            System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
    
            // 在 n 所表示的日期基础上增加 10天 后返回 新的 LocalDate 实例
            LocalDate t = n.plusDays( 10 );
            System.out.println( t );
    
            // 在 n 所表示的日期基础上增加 5个月 后返回 新的 LocalDate 实例
            LocalDate o = n.plusMonths( 5 );
            System.out.println( o );
    
            // 在 n 所表示的日期基础上增加 9周 后返回 新的 LocalDate 实例
            LocalDate x = n.plusWeeks( 9 );
            System.out.println( x );
    
        }
    
    }
    
    

    15.6 LocalTime 类

    15.6.1、LocalTime 类的设计

    java.time.LocalTime 类是一个不可变类,该类是被 final 所修饰,因此该类没有子类。

    package java.time;
    
    // 省略 import 语句
    
    public final class LocalTime
           implements Temporal, TemporalAdjuster, Comparable<LocalTime>, Serializable {
        // 省略其它代码
        private final byte hour ; // The hour.
        private final byte minute ; // The minute.
        private final byte second ; // The second.
        private final int nano ; // The nanosecond.
        // 省略其它代码
    }
    

    java.time.LocalTime 类中声明了四个实例字段用来存储 小时、分钟、秒、纳秒:

        private final byte hour ;
        private final byte minute ;
        private final byte second ;
        private final int nano ;
    

    因为它们都是 final 修饰的,因此一旦创建 LocalTime 实例,其中各个字段的值再也不能被更改。

    15.6.2、获取 LocalTime 实例

    java.time.LocalTime 类提供了许多类方法用于获取 LocalTime 实例,以下是几个常用的方法:

    public static LocalTime now()
    public static LocalTime of( int hour , int minute )
    public static LocalTime of( int hour , int minute , int second )
    public static LocalTime of( int hour , int minute , int second , int nanoOfSecond)
    

    举例:

    import java.time.LocalTime;
    
    public class LocalTimeTest1 {
    
        public static void main(String[] args) {
    
            LocalTime now = LocalTime.now();
            System.out.println( now );
    
            LocalTime f = LocalTime.of( 12,0 );
            System.out.println( f );
    
            LocalTime s = LocalTime.of( 12,24 , 36 );
            System.out.println( s );
    
            //   1s = 1000ms (毫秒)
            //  1ms = 1000us (微秒)
            //  1us = 1000ns ( 纳秒 或 毫微秒 )
            LocalTime t = LocalTime.of( 12,24 , 36 , 100200300);
            System.out.println( t );
    
        }
    
    }
    

    15.6.3、常用实例方法

    LocalTime 类中定义了大量的实例方法,其中比较常用的是:

    • public int getHour() 用于获取小时 (取值范围为 0 ~ 23 )
    • public int getMinute() 用于获取分钟 (取值范围为 0 ~ 59 )
    • public int getSecond() 用于获取秒 (取值范围为 0 ~ 59 )
    • public int getNano() 用于获取纳秒 (取值范围为 0 ~ 999999999 )

    举例:

    import java.time.LocalTime;
    
    public class LocalTimeTest2 {
    
        public static void main(String[] args) {
    
            LocalTime now = LocalTime.now();
            System.out.println( now );
    
            System.out.println( now.getHour() + "时" );
            System.out.println( now.getMinute() + "分" );
            System.out.println( now.getSecond() + "秒" );
    
            long nano = now.getNano(); // 其返回值为 0 ~ 999999999
            long ms = nano / 1000000 ; // 求取毫秒部分的数值( 范围为 0 ~ 999 )
            System.out.println( ms + "毫秒" );
            long us = nano % 1000000 / 1000 ; // 求取微秒部分的数值( 范围为 0 ~ 999 )
            System.out.println( us + "微秒" );
            long ns = nano % 1000000 % 1000 ; // 求取纳秒部分的数值( 范围为 0 ~ 999 )
            System.out.println( ns + "纳秒" );
    
        }
    
    }
    

    同时,LocalTime 类中定义了用于比较 LocalTime 实例的方法:

    public boolean isAfter( LocalTime other )
    public boolean isBefore( LocalTime other )
    public boolean equals( Object obj )
    

    另外,LocalTime 类还定义了 在指定的 LocalTime 对应的时间基础上 增加或减少 指定时间的方法:

    public LocalTime plusHours( long hoursToAdd )
    public LocalTime plusMinutes( long minutesToAdd )
    public LocalTime plusSeconds( long secondstoAdd )
    public LocalTime plusNanos( long nanosToAdd )
    

    举例:

    import java.time.LocalTime;
    
    public class LocalTimeTest3 {
    
        public static void main(String[] args) {
    
            LocalTime time = LocalTime.now(); // 获取当前时间
            System.out.println( time );
    
            // 在 time 所表示的时间基础上增加 5 小时后返回新的 LocalTime 实例
            LocalTime t1 = time.plusHours( 5 );
            System.out.println( t1 );
    
            // 在 time 所表示的时间基础上减少 20 分钟 后返回新的 LocalTime 实例
            LocalTime t2 = time.plusMinutes( -20 );
            System.out.println( t2 );
    
            // 在 time 所表示的时间基础上增加 30 秒 后返回新的 LocalTime 实例
            LocalTime t3 = time.plusSeconds( 30 );
            System.out.println( t3 );
    
            // 在 time 所表示的时间基础上增加 100200300 纳秒 后返回新的 LocalTime 实例
            LocalTime t4 = time.plusNanos( 100200300L );
            System.out.println( t4 );
    
            System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
    
            System.out.println( t1.isAfter( t2 ) );
            System.out.println( t2.isBefore( t3 ) );
            System.out.println( t3.equals( t4 ) );
    
        }
    
    }
    

    15.7 LocalDateTime类

    15.7.1、LocalDateTime 类的设计

    java.time.LocalDateTime 类是一个 不可变类,该类是被 final 所修饰,因此该类没有子类。

    package java.time;
    
    // 省略 import 语句
    
    public final class LocalDateTime
           implements Temporal, TemporalAdjuster, ChronoLocalDateTime<LocalDate>,
                      Serializable {
        // 省略其它代码
        private final LocalDate date ; // The date part.
        private final LocalTime time ; // The time part.
        // 省略其它代码
    }
    

    java.time.LocalDateTime 类中声明了两个实例字段用来存储 日期 和 时间 :

        private final LocalDate date ;
        private final LocalTime time ;
    

    这里需要注意,不仅仅 datetime 字段是 final 修饰的,LocalDateLocalTime 类中的实例字段也是 final 修饰的,因此 LocalDateTime 的实例一经创建,其内部的各项取值都是不可更改的。

    15.7.2、获取 LocalDateTime 实例

    举例:

    
    import java.time.LocalDate;
    import java.time.LocalDateTime; 
    import java.time.LocalTime;
    
    public class LocalDateTimeTest1 {
    
        public static void main(String[] args) {
    
            LocalDateTime datetime = LocalDateTime.now();
            System.out.println( datetime );
    
            LocalDateTime first = LocalDateTime.of( 1996 , 7 , 4 , 7 , 30 ) ;
            System.out.println( first );
    
            LocalDateTime second = LocalDateTime.of( 1999 , 11 ,  20, 6 , 30 , 7 ) ;
            System.out.println( second );
    
            LocalDateTime third = LocalDateTime.of( 1999 , 11 ,  20, 6 , 30 , 7 , 0 ) ;
            System.out.println( third );
    
            LocalDate date = LocalDate.of( 1997 , 7 , 1 );
            LocalTime time = LocalTime.of( 10 , 20 );
            LocalDateTime fourth = LocalDateTime.of( date , time );
            System.out.println( fourth );
    
        }
    
    }
    

    15.7.3、获取日期时间值

    LocalDateTime 实例中获取 年份、月份、日期 、星期 、小时、分钟、秒、纳秒举例:

    import java.time.LocalDateTime;
    
    public class LocalDateTimeTest2 {
    
        public static void main(String[] args) {
    
            LocalDateTime n = LocalDateTime.now();
    
            System.out.println( n.getYear() + "年" );
            System.out.println( n.getMonthValue() + "月" );
            System.out.println( n.getDayOfMonth() + "日" );
    
            System.out.println( n.getDayOfWeek() );
    
            int hour = n.getHour() ;
            int minute = n.getMinute() ;
            int second = n.getSecond() ;
            int nanos = n.getNano() ;
            System.out.println( hour + ":" + minute + ":" + second + "." + nanos );
    
        }
    
    }
    

    15.7.4、增加或减少指定时间

    在指定的时间基础之上增加或减少时间 ( 年、月、周、天、时、分、秒、纳秒 )举例:

    import java.time.LocalDateTime;
    
    public class LocalDateTimeTest3 {
    
        public static void main(String[] args) {
    
            LocalDateTime dt = LocalDateTime.now();
            System.out.println( dt );
    
            LocalDateTime dt1 = dt.plusYears( -3 ); // 减少 3 年
            System.out.println( dt1 );
    
            LocalDateTime dt2 = dt.plusMonths( 5 ); // 增加 5 个月
            System.out.println( dt2 );
    
            LocalDateTime dt3 = dt.plusWeeks( 10 ); // 增加 10 周
            System.out.println( dt3 );
    
            LocalDateTime dt4 = dt.plusDays( 15 ); // 增加 15 天
            System.out.println( dt4 );
    
            LocalDateTime dt5 = dt.plusHours( 8 ); // 增加 8 小时
            System.out.println( dt5 );
    
            LocalDateTime dt6 = dt.plusMinutes( 30 ); // 增加 30 分钟
            System.out.println( dt6 );
    
            LocalDateTime dt7 = dt.plusSeconds( 50 ); // 增加 50 秒
            System.out.println( dt7 );
    
            LocalDateTime dt8 = dt.plusNanos( 100300500L ); // 增加 100300500L 纳秒
            System.out.println( dt8 );
    
        }
    
    }
    

    15.8、转换

    在 Java 8 提供了新的日期时间API后,我们需要在新旧两套日期时间API之间完成转换。
    这里仅列举几个常见的类型之间的转换方法。

    15.8.1、LocalDateLocalDateTime

    在 LocalDate 实例中已经存在年、月、日的数值,因此将 LocalDate 转换到 LocalDateTime 时需要指定相应的时、分、秒、纳秒等数值,借助于 LocalDate 类中提供的 atStartOfDayatTime 等方法可以完成该操作。

    import java.time.LocalDate;
    import java.time.LocalDateTime;
    
    public class LocalDateTest4 {
    
        public static void main(String[] args) {
    
            LocalDate n = LocalDate.now();
            System.out.println( n );
    
            LocalDateTime datetime =  n.atStartOfDay();
            System.out.println( datetime );
    
            LocalDateTime first = n.atTime( 10 , 20 );
            System.out.println( first );
    
            LocalDateTime second = n.atTime( 10 , 20 , 30 );
            System.out.println( second );
    
            LocalDateTime third = n.atTime( 10 , 20 , 30 , 100200300 );
            System.out.println( third );
    
        }
    
    }
    

    15.8.2、LocalTimeLocalDateTime

    在 LocalTime 实例中已经存在时、分、秒、纳秒等数值,因此将 LocalTime 转换到 LocalDateTime 时需要指定相应的年、月、日等数值,借助于 LocalTime 类中提供的 atDate 方法可以完成该操作。

    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.LocalTime;
    
    public class LocalTimeTest4 {
    
        public static void main(String[] args) {
    
            LocalTime time = LocalTime.now() ;
            System.out.println( time );
    
            LocalDate date = LocalDate.of( 2019 , 10 , 10 );
    
            LocalDateTime dateTime = time.atDate( date );
            System.out.println( dateTime );
    
        }
    
    }
    

    15.8.3、LocalDateTimeLocalDateLocalTime

    我们已经知道在 LocalDateTime 实例中封装了一个 LocalDate 实例和一个 LocalTime 实例,因此可以通过 LocalDateTime 提供的方法直接获取相应的 LocalDate 实例和 LocalTime 实例。

    
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.LocalTime;
    
    public class LocalDateTimeTest4 {
    
        public static void main(String[] args) {
    
            LocalDateTime datetime = LocalDateTime.now();
            System.out.println( datetime );
    
            LocalDate date = datetime.toLocalDate();
            System.out.println( date );
    
            LocalTime time = datetime.toLocalTime();
            System.out.println( time );
    
        }
    
    }
    

    15.8.4、DateLocalDateTime

    将 java.util.Date 类型的实例转换成 LocalDateTime 类型实例的方法不止一种,这里介绍其中一种实现方法,并通过举例,简单了解一下 InstantZoneIdZonedDateTime 三个类的作用。

    以下举例说明将 java.util.Date 类型的实例转换为 java.time.LocalDate 类型的实例:

    import java.time.*;
    
    public class TransformTest1 {
    
        public static void main(String[] args) {
    
            final long ms = 1000L * 60 * 60 * 24 * 365 * 30 ;
            java.util.Date date = new java.util.Date( ms );
            System.out.println( date );
    
            System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
    
            // 根据指定的 java.util.Date 实例获取与之对应的  java.time.Instant 实例
            Instant instant = date.toInstant(); 
    
            // 根据时区编号(ID)获取相应的 java.time.ZoneId 实例
            ZoneId zone = ZoneId.of( "Asia/Shanghai" ) ;
    
            // 根据 Instant 实例获取带有时区的日期时间对象( ZonedDateTime 实例 )
            ZonedDateTime zonedDateTime = instant.atZone( zone );
    
            // 根据 带有时区的日期时间对象 ( ZonedDateTime 实例 ) 获取 LocalDateTime 实例
            LocalDateTime datetime = zonedDateTime.toLocalDateTime() ;
            System.out.println( datetime );
    
            // 根据 带有时区的日期时间对象 ( ZonedDateTime 实例 ) 获取 LocalDate 实例
            LocalDate d = zonedDateTime.toLocalDate();
            System.out.println( d );
    
            // 根据 带有时区的日期时间对象 ( ZonedDateTime 实例 ) 获取 LocalTime 实例
            LocalTime t = zonedDateTime.toLocalTime();
            System.out.println( t );
    
        }
    
    }
    

    以上举例,实际上完成了以下几种转换:

    • 将 java.util.Date 实例 转换为 java.time.LocalDateTime 实例
    • 将 java.util.Date 实例 转换为 java.time.LocalDate 实例
    • 将 java.util.Date 实例 转换为 java.time.LocalTime 实例

    15.8.5、LocalDateTimeDate

    在了解将 java.util.Date 实例转换为 java.time.LocalDateTime 实例的基础上,我们可以实现将 java.time.LocalDateTime 实例转换为 java.util.Date 实例 ( 仅列举一种方法 )。

    import java.time.*;
    import java.util.Date;
    
    
    public class TransformTest2 {
    
        public static void main(String[] args) {
    
            LocalDateTime datetime = LocalDateTime.of( 1999 , 11 , 22 , 6 , 30 , 7 );
    
            // 获取系统平台默认的时区编号对应的 java.time.ZoneId 实例
            ZoneId zone = ZoneId.systemDefault() ;
    
            // 根据 LocalDateTime 实例获取带有时区的日期时间对象 ( ZonedDateTime 实例 )
            ZonedDateTime zonedDateTime = ZonedDateTime.of( datetime , zone ) ;
    
            // 根据 带有时区的日期时间对象 ( ZonedDateTime 实例 ) 获取与其相应的 Instant 实例
            Instant instant = Instant.from( zonedDateTime );
    
            // 使用 java.util.Date 类提供的 from 方法获取与指定 Instant 实例对应的 Date 实例
            java.util.Date date = Date.from( instant );
    
            System.out.println( date );
    
        }
    
    }
    

    相关文章

      网友评论

          本文标题:Java中的日期和时间

          本文链接:https://www.haomeiwen.com/subject/jvjqvctx.html