Java基础之Java8的时间工具类Time

java.time包中的是类是不可变且线程安全的。新的时间及日期API位于java.time中,下面是一些关键类
●Instant——它代表的是时间戳
●LocalDate——不包含具体时间的日期,比如2014-01-14。它可以用来存储生日,周年纪念日,入职日期等。
●LocalTime——它代表的是不含日期的时间
●LocalDateTime——它包含了日期及时间,不过还是没有偏移信息或者说时区。
●ZonedDateTime——这是一个包含时区的完整的日期时间,偏移量是以UTC/格林威治时间为基准的。
这些类都是被final修饰的类

java8是如何处理时间及日期的

1、如何在java8中获取当天的日期
java8中有个叫LocalDate的类,能用来表示今天的日期。这个类与java.util.Date略有不同,因为它只包含日期,没有时间。
    
    import java.time.LocalDate;
    import java.util.Scanner;
    
    public class Test {
    	public static void main(String[] args) {
    		LocalDate localDate = LocalDate.now();
    		System.out.println(localDate);
    	}
    }

输出结果是

       2019-06-06

可以看到,他创建了今天的日期却不包含时间信息,并且格式化了日期

2、如何在java8中获取当前的年月日
LocalDate类中提供了一些很方便的方法可以用来提取年月日以及其他的日期属性,特别方便,只需要使用对应的getter方法就可以了,非常直观

   public class Test {
    	public static void main(String[] args) {
    		LocalDate localDate = LocalDate.now();
    		System.out.println(localDate.getDayOfMonth());//一个月的第几天
    		System.out.println(localDate.getDayOfYear());//一年的第几天
    		System.out.println(localDate.getMonthValue());//是哪一个月
    		System.out.println(localDate.getYear());//是哪一年
    		System.out.println(localDate.getDayOfWeek());//是周几
    	}
    }

输出结果

    6
    157
    6
    2019
    THURSDAY
3、在java8中如何获取某个指定的日期对象
通过另一个方法,可以创建出任意一个日期,它接受年月日的参数,然后返回一个等价的LocalDate实例。在这个方法里,需要的日期你填写什么就是什么,不想之前的API中月份必须从0开始
    public class Test {
    	public static void main(String[] args) {
    		LocalDate localDate = LocalDate.of(2019, 6, 6);
    		System.out.println(localDate);	
    	}
    }

输出结果是:

    2019-06-06
4、在java8中检查两个日期是否相等
LocalDate重写了equals方法来进行日期的比较,如下所示:
    public class Test {
    	public static void main(String[] args) {
    		LocalDate localDate = LocalDate.of(2019, 6, 6);
    		LocalDate localDate2 = localDate.now();
    		LocalDate localDate3 = LocalDate.of(2019, 6, 5);
    		System.out.println(localDate.equals(localDate2));	
    		System.out.println(localDate2.equals(localDate3));
    	}
    }

输出结果是

    true
    false
5、在java8中如何检查重复事件对应的特殊日期,比如生日
在java中还有一个与时间日期相关的任务就是检查重复事件,比如每月的账单日 如何在java中判断是否是某个节日或者重复事件,使用MonthDay类。这个类由月日组合,不包含年信息,可以用来代表每年重复出现的一些日期或其他组合。他和新的日期库中的其他类一样也都是不可变且线程安全的,并且它还是一个值类(value class)。

    public class Test {
    	public static void main(String[] args) {
    		LocalDate localDate = LocalDate.of(1996, 02, 23);
    		MonthDay birthDay = MonthDay.of(localDate.getMonth(), localDate.getDayOfMonth());
    		LocalDate today = LocalDate.now();
    		MonthDay monthDayToDay= MonthDay.from(today);
    		if(monthDayToDay.equals(birthDay)) {
    			System.out.println("今天是你的生日");
    		}else {
    			System.out.println("今天不是你的生日");
    		}	
    	}
    	

输出结果

    今天不是你的生日

通过列子可以看到MonthDay只存储了月日,对比两个日期的月日即可知道是否是特定的某个日子

6、如何在java8中获取当前时间
这个与第一个例子获取当前日期非常相似,这里用的是LocalTime类,默认的格式是hh:mm:ss:nnn
    public class Test {
    	public static void main(String[] args) {
    		LocalTime localTime = LocalTime.now();
    		System.out.println(localTime);
    	}
    }

输出的结果

    11:21:54.738

可以看到,这个时间是不包含日期的

7、如何增加时间里面的小时数
很多时候需要对时间进行操作,比如加一个小时来计算之后的时间,java8提供了更方便的方法 如plusHours,这些方法返回的是一个新的LocalTime实例的引用,因为LocalTime是不可变的
    public class Test {
    	public static void main(String[] args) {
    		LocalTime localTime = LocalTime.now();
    		System.out.println("现在的时间是:"+localTime);
    		LocalTime loclaTime2 = localTime.plusHours(3);
    		System.out.println("三小时后的时间是:"+loclaTime2);
    	}
    }

输出结果是:

    现在的时间是:11:30:48.135
    三小时后的时间是:14:30:48.135
8、如何获取1周后的日期

这个与前一个获取2小时后的时间的例子很相似,这里我们获取的是1周后的日期。LocalDate是用来表示无时间的日期,他又一个plus()方法可以用来增加日,星期,月,ChronoUnit则用来表示时间单位,LocalDate也是不可变的,因此任何修改操作都会返回一个新的实例

    public class Test {
    	public static void main(String[] args) {
    		LocalDate localDate = LocalDate.now();
    		System.out.println("现在的日期是:"+localDate);
    		//一周后的日期
    		LocalDate localDate2 = localDate.plus(1, ChronoUnit.WEEKS);
    		System.out.println("一周后的日期:"+localDate2);
    		//一月后的日期
    		LocalDate localDate3 = localDate.plus(1, ChronoUnit.MONTHS);
    		System.out.println("一月后的日期:"+localDate3);		
    	}
    }

输出的结果:

    现在的日期是:2019-06-06
    一周后的日期:2019-06-13
    一月后的日期:2019-07-06

可以看到一周后的日期是什么,也可以用这个方法来增加一个月,一年,一小时,一分等等

9、一年前后的日期
在上个例子中我们使用了LocalDate的plus()方法来给日期增加日周月,现在我们用minus()方法来找出一年前的那天
    public class Test {
    	public static void main(String[] args) {
    		LocalDate localDate = LocalDate.now();
    		System.out.println("现在的日期是:"+localDate);
    		//一年后的日期
    		LocalDate localDate2 = localDate.plus(1, ChronoUnit.YEARS);
    		System.out.println("一年后的日期:"+localDate2);
    		//一年前的日期
    		LocalDate localDate3 = localDate.minus(1, ChronoUnit.YEARS);
    		System.out.println("一年前的日期:"+localDate3);		
    	}
    }

输出结果是:

现在的日期是:2019-06-06
一年后的日期:2020-06-06
一年前的日期:2018-06-06
10、在java8中使用时钟
    public class Test {
    	public static void main(String[] args) {
    		Clock clock= Clock.systemUTC();
    		//拿到当前的系统时间
    		System.out.println("当前的系统时间是:"+clock.millis());
    		System.out.println(System.currentTimeMillis());		
    		//拿到当前的时区
    		System.out.println("当前的时区是:"+clock.systemDefaultZone());
    	}
    }

输出结果是

    当前的系统时间是:1559822512542
    1559822512542
    当前的时区是;SystemClock[Asia/Shanghai]
11、在java8中如何判断某个日期在另一个日期的前面还是后面
如何判断某个日期在另一个日期的前面还是后面或者相等,在java8中,LocalDate类中使用isBefore()、isAfter()、equals()方法来比较两个日期。如果调用方法的那个日期比给定的日期要早的话,isBefore()方法会返回true。equals()方法在前面的例子中已经说明了,这里就不举例了
    public class Test {
    	public static void main(String[] args) {
    		LocalDate localDate = LocalDate.now();
    		LocalDate localDate2 = LocalDate.of(2019, 05, 23);
    		System.out.println("现在是否是给的日期之前:"+localDate.isBefore(localDate2));
    		System.out.println("现在是否是给的日期之后:"+localDate.isAfter(localDate2));
    	}
    }

输出结果是:

    现在是否是给的日期之前:false
    现在是否是给的日期之后:true
12、在java8中处理不同的时区
java8中不仅将日期和时间进行了分离,同时还有时区。比如ZonId代表的是某个特定时区,ZonedDateTime代表带时区的时间,等同于以前的GregorianCalendar类。使用该类,可以将本地时间转换成另一个时区中的对应时间。
      public class Test {
    	public static void main(String[] args) {
    		//使用一个准确的时间点来建立zonedDateTime,下面这段代码对生成UTC时间,会比北京时间早8个小时
    		ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(Instant.now(), ZoneId.of("UTC"));
    		System.out.println(zonedDateTime);
    		//指定时区
    		LocalDateTime localDateTime = zonedDateTime.toLocalDateTime();
    		//在UTC时区的基础上转化为上海时区
    		ZonedDateTime zonedDateTime2 = ZonedDateTime.of(localDateTime,ZoneId.of(ZoneId.SHORT_IDS.get("CTT")));
    		System.out.println(zonedDateTime2.plus(8,ChronoUnit.HOURS).toLocalDateTime());
    	}
    }

输出的结果是

转换成字符串的格式是2019-06-07 17:16:59
13、YearMonth
正如MonthDay表示的是某个重复出现的日子,YearMonth是另外一个组合,你可以用这个类找出这个月有多少天,LengthOfMonth()这个方法返回的是这个YearMonth实例对应的月有多少天,这对于检查2月是否润2月很有用
      public class Test {
        	public static void main(String[] args) {
        		YearMonth yearMonth = YearMonth.now();
        		int day = yearMonth.lengthOfMonth();
        		System.out.println("这个月共有" + day + "天");
        		YearMonth yearMonth2 = YearMonth.of(2019, 2);
        		int day2 = yearMonth2.lengthOfMonth();
        		if (day2 == 29) {
        			System.out.println("2019年的2月有29天,2019是瑞年");
        		} else if(day2==28){
        			System.out.println("2019年的2月有28天,2019年是平年");
        		}
        	}
        }

输出结果是

    这个月共有302019年的2月有28天,2019年是平年
14、如何在java8中检查闰年
    public class Test {
    	public static void main(String[] args) {
    		LocalDate localDate = LocalDate.now();
    		System.out.println(localDate.getYear()+"年是不是瑞年"+localDate.isLeapYear());
    	}
    }

输出的结果是:

    2019年是不是瑞年false
15、两个日期之间包含多少天,多少月,多少年(必须连起来)
计算两个日期之间对应相差多少天、月、年。可以用java.time.Period类完成该功能。
    public class Test {
    	public static void main(String[] args) {
    		LocalDate birthday = LocalDate.of(1996, 02, 23);
    		LocalDate localDate = LocalDate.now();
    		Period period = Period.between(birthday, localDate);
    		System.out.println("相差"+period.getYears()+"年,相差"+period.getMonths()+"月,相差"+period.getDays()+"天");
    		
    	}
    }

输出结果是

  相差23年,相差3月,相差14
16、在java8中获取当前时间戳
java8获取时间戳特别简单。Instant类由一个静态的工厂方法now()可以返回当前时间戳
    public class Test {
    	public static void main(String[] args) {
    		Instant instant = Instant.now();
    		System.out.println("当前的时间戳是:"+instant);
    		//Instant就是以前的java.util.Date
    		Date date = Date.from(instant);
    		System.out.println("date:"+date);
    		Instant instant2 = date.toInstant();
    		System.out.println("instant2:"+instant2);
    		
    	}
    }

输出的结果是:

    当前的时间戳是:2019-06-06T12:45:47.571Z
    date:Thu Jun 06 20:45:47 CST 2019
    instant2:2019-06-06T12:45:47.571Z

可以看到,当前时间戳是包含日期和时间的,与java.util.Date很类似,事实上Instant就是java8以前的Date,可以使用这个两个类中的方法在这两个类型之间进行转换,比如Date.from(Instant)就是用来把Instant转换成java.util.date的,而Date.toInstant()就是将Date转换成Instant的

17、如何在java8中使用预定义的格式器来将String转换为日期对象
在java8之前,时间日期的格式化非常麻烦,经常使用SimpleDateFormat来进行格式化,但是SimpleDateFormat并不是线程安全的。在java8中,引入了一个全新的线程安全的日期与时间格式器。并且预定义好了很多格式。比如,BASICISODATE格式会将字符串20160414格式化成2016-04-14格式的日期对象
    public class Test {
    	public static void main(String[] args) {
    		String date ="20190606";
    		LocalDate formate = LocalDate.parse(date,DateTimeFormatter.BASIC_ISO_DATE);
    		System.out.println("格式化后的时间是:"+formate);
    		
    	}
    }    

输出的结果是

 格式化后的时间是:2019-06-06

但是大多时候预置的不能满足需要,就只能自定义日期格式器了,下面的例子中的日期格式是"MM dd yyyy".你可以给DateTimeFormatter的ofPattern静态方法()传入任何的模式,它会返回一个实例,这个模式的字面量与前例中是相同的。比如M代表月,m仍代表分,无效的模式会抛异常DateTimeParseException。

    public class Test {
    	public static void main(String[] args) {
    		String date ="2019-06-06 10:20:00";
    		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss"); 
    		LocalDateTime date2 = LocalDateTime.parse(date,dateTimeFormatter);
    		System.out.println("格式化的日期是"+date2);
    		
    	}
    }

输出结果是:


 格式化的日期是2019-06-06T10:20

输出结果和预想的有一点差异,这个还没有没想到为什么,如果你看到我的博客,知道为什么,请留言告诉我
注意传入的字符串格式不对会报错

    Exception in thread "main" java.time.format.DateTimeParseException: Text '2019 06 06 10:20:00' could not be parsed at index 4
    	at java.time.format.DateTimeFormatter.parseResolved0(Unknown Source)
    	at java.time.format.DateTimeFormatter.parse(Unknown Source)
    	at java.time.LocalDateTime.parse(Unknown Source)
    	at cn.bzu.look.dao.Test.main(Test.java:25)
    	
18、如何在java8中对日期进行格式化,转换成字符串
前面的两个例子中,我们主要是对日期字符串来进行解析转换成日期,在这个例子我们相反,是把日期转换成字符。这里我们有个LocalDateTime类的实例,我们要把他转换成一个格式化好的日期串,与前例相同的是,我们仍需要制定模式串去创建一个DateTimeFormatter类的实例,但调用的是LocalDate.format()。这个方法会返回一个代表当前日期的字符串,对应的模式就是传入的DateTimeFormatter实例中定义好的。
    public class Test {
    	public static void main(String[] args) {    		
    		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss"); 
    		LocalDateTime localDateTime = LocalDateTime.now();
    		String date = localDateTime.format(dateTimeFormatter);
    		System.out.println("转换成字符串的格式是"+date);
    		
    	}
    }
 

输出结果是

 转换成字符串的格式是2019-06-06 21:10:14

java8中日期与时间API的几个关键点

经过上面的例子,我们已经对java8的时间日期有了一定的了解,现在回顾一下

●它提供了javax.time.ZoneId用来处理时区。
●它提供了LocalDate与LocalTime类
●Java 8中新的时间与日期API中的所有类都是不可变且线程安全的,这与之前的Date与Calendar API中的恰好相反,那里面像java.util.Date以及SimpleDateFormat这些关键的类都不是线程安全的。
●新的时间与日期API中很重要的一点是它定义清楚了基本的时间与日期的概念,比方说,瞬时时间,持续时间,日期,时间,时区以及时间段。它们都是基于ISO日历体系的。

每个Java开发人员都应该至少了解这套新的API中的这五个类:
●Instant 它代表的是时间戳,比如2016-04-14T14:20:13.592Z
●LocalDate 它表示的是不带时间的日期,比如2016-04-14。它可以用来存储生日,周年纪念日,入职日期等。
●LocalTime - 它表示的是不带日期的时间
●LocalDateTime - 它包含了时间与日期,不过没有带时区的偏移量
●ZonedDateTime - 这是一个带时区的完整时间,它根据UTC/格林威治时间来进行时区调整

时区的介绍,了解就行

GMT - 格林尼治标准时间,格林威治平均时间 Greenwich Mean Time 由于地球轨道并非圆形,其运行速度又随着地球与太阳的距离改变而出现变化,因此视太阳时欠缺均匀性。 视太阳日的长度同时亦受到地球自转轴相对轨道面的倾斜度所影响。 为着要纠正上述的不均匀性,天文学家计算地球非圆形轨迹与极轴倾斜对视太阳时的效应。 平太阳时就是指经修订后的视太阳时。在格林尼治子午线上的平太阳时称为世界时(UT0),又叫格林尼治平时(GMT)。

UTC - 协调世界时
Universal Time Coordinated
UTC是国际无线电咨询委员会制定和推荐的,UTC相当于本初子午线(即经度0度)上的平均太阳时。
它是经过平均太阳时(以格林威治标准时间GMT)、地轴运动修正后的新时标以及以「秒」为单位的国际原子时所综合精算而成的时间,
计算过程相当严谨精密,因此若以「世界标准时间」的角度来说,UTC比GMT来得更加精准。
其误差值必须保持在0.9秒以内,若大于0.9秒则由位于巴黎的国际地球自转事务中央局发布闰秒,使UTC与地球自转周期一致。
所以基本上UTC的本质强调的是比GMT更为精确的世界时间标准.它其实是个更精确的GMT.

我们一般认为GMT和UTC是一样的,都与英国伦敦的本地时相同。

CST(Central Standard Time ):却同时可以代表如下 4 个不同的时区:
Central Standard Time (USA) UT-6:00
Central Standard Time (Australia) UT+9:30
China Standard Time UT+8:00
Cuba Standard Time UT-4:00
CST可以同时表示美国,澳大利亚,中国,古巴四个国家的标准时间。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值