日期与时间

时间:2019-01-11
本文章向大家介绍日期与时间,主要包括日期与时间使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、Date类

对象创建

可以通过Date的两个构造函数来实现

  1. Date( ) 获取当前日期和时间的Date对象
  2. Date(long millisec) 其中的参数是从1970年1月1日起的毫秒数

代码示例:

import java.util.Date;
  
public class DateDemo {
   public static void main(String args[]) {
       // 初始化 Date 对象
       Date date = new Date();
        
       // 使用 toString() 函数显示日期时间
       System.out.println(date.toString());
   }
}

常用API

boolean after(Date date);

若当调用此方法的Date对象在指定日期之后返回true,否则返回false。

boolean before(Date date)

若当调用此方法的Date对象在指定日期之前返回true,否则返回false。

int compareTo(Date date)

比较当调用此方法的Date对象和指定日期。两者相等时候返回0。调用对象在指定日期之前则返回负数。调用对象在指定日期之后则返回正数。

boolean equals(Object date)

当调用此方法的Date对象和指定日期相等时候返回true,否则返回false。

long getTime( )

返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。

void setTime(long time)

用自1970年1月1日00:00:00 GMT以后time毫秒数设置时间和日期。

String toString( )

把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。

日期比较

Java使用以下三种方法来比较两个日期:

  • 使用 getTime() 方法获取两个日期(自1970年1月1日经历的毫秒数值),然后比较这两个值。
  • 使用方法 before(),after() 和 equals()。
  • 使用 compareTo() 方法,它是由 Comparable 接口定义的,Date 类实现了这个接口。

代码示例:

package time;

import java.util.Date;

public class DateDemo {
	public static void main(String[] args) throws InterruptedException {
		Date d1 = new Date();
		Thread.sleep(20);
		Date d2 = new Date();
		//使用毫秒值来比较大小
		boolean flag = (d2.getTime() - d1.getTime())>0 ? true:false;
		System.out.println("d2比d1大吗?" + flag); //true
		//使用before来比较大小
		System.out.println("d2比d1大吗?" + d2.after(d1)); //true
		//使用compareTo方法来比较
		boolean cFlag = d2.compareTo(d1) > 0 ? true : false;
		System.out.println("d2比d1大吗?" + cFlag); //true
	}
}

格式化日期

使用DateFormat类来格式化日期

代码示例:

Date date = new Date();
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.FULL);
String dateStr = dateFormat.format(date);
System.out.println(dateStr);	//输出为	2019年1月10日 星期四

使用该类来格式化日期都是JDK自带的日期格式,DateFormat.FULL为其中一种格式化风格,其他风格可以查看API。

使用SimpleDateFormat类来格式化日期

SimpleDateFormat是DateFormat的子类,可以自定义日期的格式化风格

代码示例:

private static void simpleDateFormatDemo() {
	Date dNow = new Date( );
    SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
    System.out.println("当前时间为: " + ft.format(dNow));
    //输出为	当前时间为: 2019-01-10 10:12:06
}

其中 yyyy 是完整的公元年,MM 是月份,dd 是日期,HH:mm:ss 是时、分、秒。
注意:有的格式大写,有的格式小写,例如 MM 是月份,mm 是分;HH 是 24 小时制,而 hh 是 12 小时制。

具体的日期和时间的格式化编码如下示:

使用parse方法解析字符串为时间

SimpleDateFormat 类有一些附加的方法,特别是parse(),它试图按照给定的SimpleDateFormat 对象的格式化存储来解析字符串。

代码示例:

private static void strToDate() {
	try {
		//按指定格式将字符串转换为Date对象
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
		String strDate = "2019-01-11"; 
		Date date = simpleDateFormat.parse(strDate);
		//将Date对象转换其他格式的时间字符串
		DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.FULL);
		String newStrDate = dateFormat.format(date);
		System.out.println(newStrDate);
		
	} catch (ParseException e) {
		System.out.println("时间转换错误!");
	}
}

二、Calendar类

Date有许多弊端和不足之处,无法满足特定需求。相比于Date,Calendar则强大得多。我们可以使用Calendar类设置和获取日期数据的特定部分,比如说小时,日,或者分钟。

Calendar实例获取

可以使用getInstance方法。

//Calendar示例的获取
Calendar calendar = Calendar.getInstance();
String strDate = calendar.getTime().toString();
System.out.println(strDate); //Thu Jan 10 10:55:19 CST 2019

Calendar类对象字段类型

特别注意:MONTH月份是从0开始计算的,也就是说0代表一月份,1代表二月份,以此类推;DAY_OF_WEEK规定了一个星期是从星期日开始的,1代表星期日,2代表星期一,以此类推。

Calendar对象特定部分的获取

下面是Calendar对象的特定部分进行获取的代码示例:

Calendar c1 = Calendar.getInstance();
// 获得年份
int year = c1.get(Calendar.YEAR);
System.out.println("year:" + year);
// 获得月份
int month = c1.get(Calendar.MONTH) + 1;
System.out.println("month:" + month);
// 获得日期
int date = c1.get(Calendar.DATE);
System.out.println("date:" + date);
// 获得小时
int hour = c1.get(Calendar.HOUR_OF_DAY);
System.out.println("hour:" + hour);
// 获得分钟
int minute = c1.get(Calendar.MINUTE);
System.out.println("minute:" + minute);
// 获得秒
int second = c1.get(Calendar.SECOND);
System.out.println("second:" + second);
// 获得星期几(注意(这个与Date类是不同的):1代表星期日、2代表星期1、3代表星期二,以此类推)
int day = c1.get(Calendar.DAY_OF_WEEK);
System.out.println("day:" + day);

输出结果:

year:2019
month:1
date:10
hour:11
minute:9
second:7
day:5
Calendar类对象信息的设置

set设置:

public void setCalendarTime() {
	Calendar c1 = Calendar.getInstance();
	//使用set设置日期
	c1.set(2019, 5, 25);
	myPrintln(c1);//2019-06-25 11:32:01
	//使用set设置字段
	//设置年份
	c1.set(Calendar.YEAR, 2018); //2018-06-25 11:32:01
	myPrintln(c1);
	//设置月份
	c1.set(Calendar.MONTH, 10); //2018-11-25 11:32:01
	myPrintln(c1);
	//设置日期
	c1.set(Calendar.DATE, 31);	//2018年11月是没有31号的,时间会重新计算,变成12月1号
	myPrintln(c1);	//2018-12-01 11:33:32
}

public void myPrintln(Calendar c1) {
	Date time = c1.getTime();
	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
	System.out.println(format.format(time));
}

set方法有两种,一种是直接设置日期时间,另一种则是设置日期时间的某一特定部分。
注意:在设置月份的时候,如果设置的月份为负数或者大于12,则会对应的更改当前年份。日期和具体时间同理。

add设置:

public void addCalendarTime() {
	Calendar c1 = Calendar.getInstance();
	//当前日期时间
	myPrintln(c1); //2019-01-10 11:48:53
	//设置月份,月份加了13
	c1.add(Calendar.MONTH, 13); 
	myPrintln(c1);//2020-02-10 11:40:21
	//设置日期,天数加了23
	c1.add(Calendar.DATE, 23);
	myPrintln(c1);//2020-03-04 11:47:19
}

public void myPrintln(Calendar c1) {
	Date time = c1.getTime();
	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
	System.out.println(format.format(time));
}

其他字段属性的add的意义以此类推。

三、GregorianCalendar类

Calendar类实现了公历日历,GregorianCalendar是Calendar类的一个具体实现。

GregorianCalendar对象的创建
GregorianCalendar常用方法

GregorianCalendar类的常用方法主要是使用其父类Calendar的方法。

下面讲一下其比较特殊常用的方法:

boolean isLeapYear(int year);

确定给定的年份是否为闰年。如果给定的年份是闰年,则返回 true。如果要指定 BC 年份,必须给定 1 - 年份。例如,指定 -3 为 BC 4 年


Calendar的功能还不够给力,它的实现是易便的,并且它没有处理诸如闰秒这样的缺。所以Java SE 8中引入的java.time API,它修正了过去的缺陷。

下面开始讲述关于Java SE 8的一些关于时间日期的新特性,包括java.time.*;包里的Instant,LocalDate,LocalTime 和 LocalDateTime等类。

四、Instant类

所谓的 Instant 类代表的是时间线上的某个时间点(有点像 java.util.Date),它是精确到纳秒(而不是像旧版本的Date精确到毫秒)。
起点是格林威治时间(GMT)1970-01-01:00:00(实际上Instant 取代原有的 Date 类)。
时间从起点开始向前移动,每天为86,400秒。

对象创建
//获取当前时间 默认获取 UTC 时区
Instant instant = Instant.now();	//2019-01-10T05:41:33.411Z
//给定秒值或毫秒值构建Instant对象
Instant instant = Instant.ofEpochSecond(1547102726);
Instant instant = Instant.ofEpochMilli(1564564121354544);

注意:Instant表示的时间是UTC时区的时间,即世界标准时间(比中国时差为-8个小时)

获取时间

Instant 对象中包含两个内部属性用于表示当前的时间:即距离初始时间的秒钟数+在当前一秒内的第几纳秒,他们的组合表达了当前时间点。

Instant instant = Instant.now();
long second = instant.getEpochSecond();//获取秒值
int nano = instant.getNano();	//获取纳秒值
Instant的操作

Instant类与许多用于时间的算术运算方法,比如plusNanos,plusMillis等等。下面仅仅演示plusMillis(long millisToAdd)方法。其他方法可以查看API文档。

Instant startInstant = Instant.now();
Thread.sleep(200);
Instant endInstant = Instant.now();

Instant plusMillis = startInstant.plusMillis(200);

System.out.println(plusMillis);
System.out.println(endInstant);

输出结果:

2019-01-10T07:09:00.763Z
2019-01-10T07:09:00.764Z

五、Duration类

Duration类用来计算两个时刻之间的时间量

常用方法

static Duration between(Temporal startInclusive,Temporal endExclusive);

计算两个时间的间隔,默认的单位是秒

示例:

Instant startInstant = Instant.now();
Thread.sleep(200);
Instant endInstant = Instant.now();
//两次时间戳之间的时间量
Duration duration = Duration.between(startInstant, endInstant);
System.out.println(duration.toMillis());	//输出200毫秒

其他常用方法基本与Instant类一样。

注意:Instant和Duration类都是不可修改类,所以诸如multipliedBy和munus这样的方法都会返回一个新的实例。

六、LocalDate类

LocalDate类指的是本地时间,它包含年、月、日的日期,也就是说它不包含时间,只是单纯的年月日。

对象的创建

主要使用now方法和of方法

//获取当前的日期
LocalDate today = LocalDate.now();//2019-01-11

//根据年月日取日期
//注意:日期不存在时会发生 java.time.DateTimeException
LocalDate crischristmas = LocalDate.of(2017, 12, 25);//2017-12-25

// 根据字符串取:
// 严格按照ISO yyyy-MM-dd验证,02写成2都不行,当然也有一个重载方法允许自己定义格式
LocalDate endOfFeb = LocalDate.parse("2014-02-28"); //2014-02-28

//	LocalDate.parse("2014-02-29"); // 无效日期无法通过:DateTimeParseException: Invalid date
常用日期操作
加法运算

plusDays,plusWeeks,plusMonths,plusYears,plus等方法
即在当前的LocalDate上加上一定量的天、星期、月或年等。

代码示例:

public void dateCalculate() {
	//使用加法运算
	//程序员日是每年的第256天,可以通过加上255天来求得当天的日期
	LocalDate programmingDay = LocalDate.of(2014, 1, 1).plusDays(255);
	System.out.println(programmingDay);	//2014-09-13
	
	//年份加5
	LocalDate newYearDay = programmingDay.plusYears(5);
	System.out.println(newYearDay);	//2019-09-13
	
	//月份加6
	LocalDate newMonthDay = newYearDay.plusMonths(6);
	System.out.println(newMonthDay);	//2020-03-13
	
}

我们知道在两个Insatnt之间的时长是Duration,而用于本地时期的等价物是Period,它表示的是流逝的年、月或日的数量。plus方法涉及到该类,下面以代码的方式说明。

LocalDate birthday = LocalDate.of(1997, 4, 19);
//得到下一年的生日
LocalDate nextYearBirthday = birthday.plus(Period.ofYears(1));	//和plusYears(1)一样的
System.out.println(nextYearBirthday);	//1998-04-19

日期的减法运算和加法运算基本运算,不过多说明。

util方法

代码示例:

//获取今天具体我出生日期的时长
LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.of(1997, 4, 19);

System.out.println("距离出生日期的日期时长为:" + birthday.until(today));	

//获取天数
System.out.println("距离出生日期的天数为:" + birthday.until(today, ChronoUnit.DAYS));

运行结果:

距离出生日期的日期时长为:P21Y8M23D
距离出生日期的天数为:7937
其他方法
  • withDayOfMonth,WithDayOfYear,withMonth,withYear

返回一个新的LocalDate,其月的日期、年的日期、月或年修改为给定的值,相当于设置日期。

  • getMonth,getMonthValue

获取月份的枚举值,或者是1 ~ 12之间的数字 。注意,不同于Calendar类那样月份从0开始。

  • getDayOfWeek

获取星期的日期,返回DayOfWeek枚举值。

注意:DayOfWeek.MONDAY的枚举值为1,而DayOfWeek.SUNDAY的枚举值为7。这与Calendar类周日为1,周一为2有所不同。

代码示例:

private void weekDayDemo() {
	LocalDate today = LocalDate.now();
	System.out.println(today);	//2019-01-11
	
	DayOfWeek dayOfWeek = today.getDayOfWeek();
	//输出枚举值
	System.out.println(dayOfWeek);	//FRIDAY
	
	//输出枚举值对应的数
	System.out.println(dayOfWeek.getValue()); //5
}

其他方法查看API文档。

七、TemporalAdjusters类

该类为日期调整器,提供大量的用于常见调整的静态方法。

代码示例:

public  void temporalAdjustersDemo() {
	LocalDate today = LocalDate.now();	//201901-11
	// 取本月第1天:
	LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth()); 
	System.out.println(firstDayOfThisMonth);  //2019-01-01
	
	// 取本月最后一天,再也不用计算是28,29,30还是31:
	LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth());
	System.out.println(lastDayOfThisMonth);	//2019-01-31
	
	// 取2017年1月第一个周一
	LocalDate firstMondayOf2017 = LocalDate.parse("2017-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
	System.out.println(firstMondayOf2017);  //2017-01-02
	
	//取下个周一
	LocalDate nextMonday = today.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
	System.out.println(nextMonday);	//2019-01-14
	
	//取这个月的第三个周一
	LocalDate theThirdMonday = today.with(TemporalAdjusters.dayOfWeekInMonth(3, DayOfWeek.MONDAY));
	System.out.println(theThirdMonday);	//2019-01-21
}

八、LocalTime类

与LocalDate仅仅包含日期不同是,LocalTime仅包含时间部分。LocalTime表示当前时刻,例如 15:30:21。

对象的创建
  • 使用now方法创建当前时间的实例
LocalTime rightTime = LocalTime.now();
System.out.println("当前时间为:" + rightTime); //当前时间为:10:41:22.334

LocalTime bedTime = LocalTime.of(23, 12, 30, 4560 << 9);
System.out.println("睡觉时间为:" + bedTime);	//睡觉时间为:23:12:30.002334720
常见操作

LocalTime的许多时间的操作方法基本与LocalDate相同,这里不再赘述。详细参见API文档。

九、LocalDateTime类

LocalDateTime类相当于LocalDate类与LocalTime的结合,它可以表示日期和时间,适合存储固定时区的时间点。

对象的创建
LocalDateTime dateTime = LocalDateTime.now();
System.out.println(dateTime);	//2019-01-11T10:52:13.434

LocalDateTime myDateTime = LocalDateTime.of(2018, 9, 23, 12, 45);
System.out.println(myDateTime);	//2018-09-23T12:45
常见操作
间隔运算

使用Duration进行 day,hour,minute,second等的计算
使用Period进行Year,Month的计算

代码示例:

public void tiemCalculate() {
	LocalDateTime dateTime = LocalDateTime.now();
	LocalDateTime birthdateTime = LocalDateTime.of(1997, 4, 19, 4, 21);
	
	//使用Duration进行 day,hour,minute,second等的计算 
	Duration duration = Duration.between(birthdateTime,dateTime);