摘要:類(lèi)是一個(gè)抽象類(lèi),它為特定瞬間與一組諸如等日歷字段之間的轉(zhuǎn)換提供了一些方法,并為操作日歷字段例如獲得下星期的日期提供了一些方法。是不變的日期時(shí)間對(duì)象代表一個(gè)日期時(shí)間,往往被視為年月日時(shí)分秒。獲得實(shí)例的日期和時(shí)間。
時(shí)區(qū)
GMT(Greenwich Mean Time):格林尼治時(shí)間,格林尼治標(biāo)準(zhǔn)時(shí)間的正午是指當(dāng)太陽(yáng)橫穿格林尼治子午線時(shí)(也就是在格林尼治上空最高點(diǎn)時(shí))的時(shí)間。
UTC(Universal Time Coordinated):統(tǒng)一協(xié)調(diào)時(shí)間,其以原子時(shí)秒長(zhǎng)為基礎(chǔ),在時(shí)刻上盡量接近于格林尼治標(biāo)準(zhǔn)時(shí)間,標(biāo)準(zhǔn) UTC 時(shí)間格式 yyyy-MM-dd"T"HH:mm:ss.SSSXXX。
格林尼治時(shí)間已經(jīng)不再被作為標(biāo)準(zhǔn)時(shí)間使用,UTC 是最主要的世界時(shí)間標(biāo)準(zhǔn)。
Java提供了獲取當(dāng)前時(shí)間的方法
System.currentTimeMillis(),返回當(dāng)前時(shí)間,以毫秒為單位,表示的就是當(dāng)前時(shí)刻至 1970-01-01 00:00:00.000 的毫秒差值。返回的long值可以用來(lái)初始化java.util.Date, java.sql.Date, java.sql.Timestamp和java.util.GregorianCalendar對(duì)象。
System.nanoTime(),返回一個(gè)時(shí)間值(系統(tǒng)計(jì)時(shí)器的當(dāng)前值),精確到納秒。它是由 JVM 提供的一個(gè)時(shí)間,主要用來(lái)精確衡量?jī)蓚€(gè)時(shí)間段之間的時(shí)間
例如,要測(cè)量一些代碼需要執(zhí)行多長(zhǎng)時(shí)間,實(shí)現(xiàn)如下,
long startTime = System.nanoTime(); //...the code being measured long estimatedTime = System.nanoTime() - startTime;
時(shí)間粒度舊的時(shí)間API
事實(shí)上System.currentTimeMillis()方法的時(shí)間粒度是大于1毫秒的。如果你反復(fù)執(zhí)行這個(gè)方法,你會(huì)發(fā)現(xiàn)短時(shí)間內(nèi)得到的結(jié)果是相同的,隨后又突然在某一次結(jié)果增加了幾十毫秒(也可能更多)。這是很正常的,畢竟這個(gè)方法肯定不是世界上最精密的計(jì)時(shí)器。
舊的時(shí)間API存在諸多問(wèn)題,例如
Java的日期/時(shí)間類(lèi)的定義并不一致,在java.util和java.sql的包中都有日期類(lèi),此外用于格式化和解析的類(lèi)在java.text包中定義。
java.util.Date同時(shí)包含日期和時(shí)間,而java.sql.Date僅包含日期,將其納入java.sql包并不合理。另外這兩個(gè)類(lèi)都有相同的名字,這本身就是一個(gè)非常糟糕的設(shè)計(jì)。
對(duì)于時(shí)間、時(shí)間戳、格式化以及解析,并沒(méi)有一些明確定義的類(lèi)。對(duì)于格式化和解析的需求,我們有java.text.DateFormat抽象類(lèi),但通常情況下,SimpleDateFormat類(lèi)被用于此類(lèi)需求。
所有的日期類(lèi)都是可變的,因此他們都不是線程安全的,這是Java日期類(lèi)最大的問(wèn)題之一。
日期類(lèi)并不提供國(guó)際化,沒(méi)有時(shí)區(qū)支持,因此Java引入了java.util.Calendar和java.util.TimeZone類(lèi),但他們同樣存在上述所有的問(wèn)題。
java.util.Date類(lèi)java.util.Date類(lèi)用于封裝日期及時(shí)間信息,一般僅用它顯示某個(gè)日期,不對(duì)他作任何操作處理,作處理推薦用Calendar類(lèi),計(jì)算方便。以下已過(guò)時(shí)的方法沒(méi)有列出,可自行查看jdk文檔
構(gòu)造方法
Date() :分配 Date對(duì)象并初始化此對(duì)象,以表示分配它的時(shí)間(精確到毫秒)。
Date(long date):分配 Date對(duì)象并初始化此對(duì)象,以表示自從標(biāo)準(zhǔn)基準(zhǔn)時(shí)間(稱為“歷元(epoch)”,即 1970 年 1 月 1 日 00:00:00 GMT)以來(lái)的指定毫秒數(shù)。
//1、使用Date類(lèi)獲取當(dāng)前系統(tǒng)時(shí)間 Date date = new Date(); System.out.println(date); //由于Date類(lèi)覆蓋了toString()方法,所以可以直接輸出Date類(lèi)型的對(duì)象 //輸出結(jié)果為Fri May 31 10:51:18 GMT+08:00 2019 /*給Date設(shè)置年份需要減去 1900 *輸出結(jié)果Tue Jul 01 00:00:00 GMT+08:00 3919 *原來(lái)這里存在一個(gè)起始年份 1900,實(shí)際年份是要在你的年份參數(shù)上加上個(gè)起始年份。 */ Date date1 = new Date(2019,5,31); System.out.println(date1); //2.分配 Date 對(duì)象并初始化此對(duì)象,以表示自從標(biāo)準(zhǔn)基準(zhǔn)時(shí)間(稱為“歷元(epoch)”,即 1970 年 1 月 1 日 00:00:00 GMT)以來(lái)的指定毫秒數(shù)。 Date date2 = new Date(System.currentTimeMillis());//參數(shù)為19701月1日以來(lái)的毫秒數(shù) Date date3 = new Date(1559284293556l); //long類(lèi)型要加l System.out.println(date2); System.out.println(date3); //其他Date方法摘要可查看apiCalendar類(lèi)與GregorianCalendar
java.util.Calendar類(lèi)用于封裝日歷信息,其主作用在于其方法可以對(duì)時(shí)間分量進(jìn)行運(yùn)算。Calendar類(lèi)是一個(gè)抽象類(lèi),它為特定瞬間與一組諸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日歷字段之間的轉(zhuǎn)換提供了一些方法,并為操作日歷字段(例如獲得下星期的日期)提供了一些方法。
由于Calendar類(lèi)是抽象類(lèi),且Calendar類(lèi)的構(gòu)造方法是protected的,所以無(wú)法使用Calendar類(lèi)的構(gòu)造方法來(lái)創(chuàng)建對(duì)象,API中提供了getInstance方法用來(lái)創(chuàng)建對(duì)象。
Java只提供java.util.GregorianCalendar這一種java.util.Calendar的實(shí)現(xiàn)類(lèi),可以直接新建出來(lái)使用:
Calendar calendar = new GregorianCalendar();//新建出來(lái)的calendar默認(rèn)時(shí)間為當(dāng)前時(shí)間,或者說(shuō)創(chuàng)建出這個(gè)對(duì)象的時(shí)間。
通過(guò)Calendar的靜態(tài)方法獲取一個(gè)實(shí)例該方法會(huì)根據(jù)當(dāng)前系統(tǒng)所在地區(qū)來(lái)自行決定時(shí)區(qū),幫我們創(chuàng)建Calendar實(shí)例,這里要注意,實(shí)際上根據(jù)不同的地區(qū),Calendar有若干個(gè)子類(lèi)實(shí)現(xiàn)。而Calendar本身是抽象類(lèi),不能被實(shí)例化!我們不需要關(guān)心創(chuàng)建的具體實(shí)例為哪個(gè)子類(lèi),我們只需要根據(jù)Calendar規(guī)定的方法來(lái)使用就可以了。
日歷類(lèi)所解決的根本問(wèn)題是簡(jiǎn)化日期的計(jì)算,要想表示某個(gè)日期還應(yīng)該使用Date類(lèi)描述。Calendar是可以將其描述的時(shí)間轉(zhuǎn)化為Date的,我們只需要調(diào)用其getTime()方法就可以獲取描述的日期的Date對(duì)象了。
通過(guò)日歷類(lèi)計(jì)算時(shí)間:為日歷類(lèi)設(shè)置時(shí)間,日歷類(lèi)設(shè)置時(shí)間使用通用方法set。set(int field,int value),field為時(shí)間分量,Calendar提供了相應(yīng)的常量值,value為對(duì)應(yīng)的值。
只有月份從0開(kāi)始:0為1月,以此類(lèi)推,11為12月,其他時(shí)間是正常的從1開(kāi)始。也可以使用Calendar的常量 calendar.NOVEMBER……等。
Calendar.DAY_OF_MONTH 月里邊的天---號(hào); Calendar.DAY_OF_WEEK 星期里的天---星期幾 Calendar.DAY_OF_YEAR 年里的天 Calendar calendar=Calendar.getInstance();//構(gòu)造出來(lái)表示當(dāng)前時(shí)間的日歷類(lèi) Date now=calendar.getTime();//獲取日歷所描述的日期 calendar.set(Calendar.YEAR, 2019);//設(shè)置日歷表示2019年 calendar.set(Calendar.DAY_OF_MONTH,15);//設(shè)置日歷表示15號(hào) calendar.add(Calendar.DAY_OF_YEAR, 22);//想得到22天以后是哪天 calendar.add(Calendar.DAY_OF_YEAR, -5);//5天以前是哪天 calendar.add(Calendar.MONTH, 1);得到1個(gè)月后是哪天 System.out.println(calendar.getTime());
獲取當(dāng)前日歷表示的日期中的某個(gè)時(shí)間單位可以使用get方法。
int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH) int day = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(year+"年"+(month+1)+"月"+day+"日");//month要處理SimpleDateFormat類(lèi)
常用構(gòu)造方法
SimpleDateFormat(String pattern),pattern -為描述日期和時(shí)間格式的模式
用給定的模式和默認(rèn)語(yǔ)言環(huán)境的日期格式符號(hào)構(gòu)造 SimpleDateFormat。 注:此構(gòu)造方法可能不支持所有語(yǔ)言環(huán)境。要覆蓋所有語(yǔ)言環(huán)境,請(qǐng)使用 DateFormat 類(lèi)中的工廠方法。
常用方法
public final String format(Date date)將一個(gè) Date 格式化為日期/時(shí)間字符串 public Date parse(String source)throws ParseException從給定字符串的開(kāi)始解析文本,以生成一個(gè)日期。
字符串轉(zhuǎn)成Date對(duì)象
//創(chuàng)建一個(gè)SimpleDateFormat并且告知它要讀取的字符串格式 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String dateFormat = "2019-05-31";//創(chuàng)建一個(gè)日期格式字符串 //將一個(gè)字符串轉(zhuǎn)換為相應(yīng)的Date對(duì)象 Date date = sdf.parse(dateFormat);//要先捕獲異常 System.out.println(date);//輸出這個(gè)Date對(duì)象
Date對(duì)象轉(zhuǎn)成字符串
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date date = new Date(); String dateStr = sdf.format(date);//把日期對(duì)象傳進(jìn)去,繼承自DateFormat類(lèi)的方法。將一個(gè)Date格式化為日期/時(shí)間字符串
在日期格式中,-和空格無(wú)特殊意義。無(wú)特殊含義的都原樣輸出
//將當(dāng)前系統(tǒng)時(shí)間轉(zhuǎn)換為2012/05/14 17:05:22的效果 SimpleDateFormat format1 = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss"); dateStr=format1.format(date); System.out.println(dateStr);DateFormat類(lèi)
java.text.DateFormat類(lèi)(抽象類(lèi))是SimpleDateFormat類(lèi)的父類(lèi),用的少,沒(méi)SimpleDateFormat靈活。
java.sql.Datejava.sql.Date繼承java.util.Date,為了把前者轉(zhuǎn)為后者,需要以下代碼
Date date = new Date(); //java.sql.Date 不支持Date參數(shù)的構(gòu)造器,傳入long類(lèi)型的時(shí)間 java.sql.Date d = new java.sql.Date(date.getTime()); System.out.println(d); System.out.println(d.getHours());
輸出結(jié)果
2019-05-31 Exception in thread "main" java.lang.IllegalArgumentException at java.sql.Date.getHours(Unknown Source) at DateTest.DateTest1.main(DateTest1.java:40)
這是由于java.sql.Date是SQL中的單純的日期類(lèi)型,沒(méi)有時(shí)分秒。故一般通過(guò)JDBC插入java.sql.Date數(shù)據(jù)時(shí),會(huì)發(fā)現(xiàn)時(shí)分秒都沒(méi)有。因此,如果同時(shí)需要日期和時(shí)間,應(yīng)該使用Timestamp。它也是 java.util.Date 的子類(lèi),Timestamp 則包含時(shí)間戳的完整信息。
java.sql.Timestamp是java.util.Date的派生類(lèi)(繼承),所以在java.util.Date上能做的事,也可以在java.sql.Timestamp上做。
如果當(dāng)前是2019-06-01 14:35,你創(chuàng)建一個(gè)java.sql.Date 將只記下2019-06-01這個(gè)信息。若你需要保留時(shí)間進(jìn)行JDBC操作,請(qǐng)使用java.sql.Timestamp代替。
long time = System.currentTimeMillis(); java.sql.Timestamp timestamp = new java.sql.Timestamp(time); timestamp.setNanos(123456); int nanos = timestamp.getNanos(); // nanos = 123456
現(xiàn)在的Date類(lèi)中大部分方法已經(jīng)棄用,現(xiàn)在一般使用舊的API,Date只負(fù)責(zé)存儲(chǔ)一個(gè)時(shí)間,并對(duì)Calendar和DateFormat提供操作接口。Calendar獲取Date中特定的信息,對(duì)日期時(shí)間進(jìn)行操作,SimpleDateFormat對(duì)日期時(shí)間進(jìn)行格式化輸入輸出。
總的來(lái)說(shuō),Date、Calendar 和 DateFormat 已經(jīng)能夠處理一般的時(shí)間日期問(wèn)題了。但是不可避免的是,它們依然很繁瑣,不好用并且這些日期類(lèi)都是可變且線程不安全的Joda-Time
詳情請(qǐng)查看https://www.ibm.com/developer...
Java 8 時(shí)間日期API 特性不變性:新的日期/時(shí)間API中,所有的類(lèi)都是不可變的,這對(duì)多線程很有好處。
關(guān)注點(diǎn)分離:借鑒了Joda庫(kù)的一些優(yōu)點(diǎn),新的API將人可讀的日期時(shí)間和機(jī)器時(shí)間(unix timestamp)明確分離,它為日期(Date)、時(shí)間(Time)、日期時(shí)間(DateTime)、時(shí)間戳(unix timestamp)以及時(shí)區(qū)定義了不同的類(lèi)。
清晰:在所有的類(lèi)中,方法都被明確定義用以完成相同的行為。例如要拿到當(dāng)前實(shí)例我們可以使用now()方法,在所有的類(lèi)中都定義了format()和parse()方法,而不是像以前那樣專(zhuān)門(mén)有一個(gè)獨(dú)立的類(lèi)。為了更好的處理問(wèn)題,所有的類(lèi)都使用了工廠模式和策略模式,一旦你使用了其中某個(gè)類(lèi)的方法,與其他類(lèi)協(xié)同工作并不困難。
實(shí)用操作:所有新的日期/時(shí)間API類(lèi)都實(shí)現(xiàn)了一系列方法用以完成通用的任務(wù),如:加、減、格式化、解析、從日期/時(shí)間中提取多帶帶部分,等等。
可擴(kuò)展性:新的日期/時(shí)間API是工作在ISO-8601日歷系統(tǒng)上的,但我們也可以將其應(yīng)用在非IOS的日歷上。
Java8日期時(shí)間的默認(rèn)格式如下:yyyy-MM-dd-HH-mm-ss.zzz
幾個(gè)主要的核心類(lèi):
LocalDate:日期類(lèi),不帶時(shí)間
LocalTime:時(shí)間類(lèi),不帶日期
LocalDateTime:日期和時(shí)間類(lèi)
ZonedDateTime:時(shí)區(qū)日期時(shí)間類(lèi)
OffsetDateTime:按UTC時(shí)間偏移來(lái)得到日期時(shí)間
Clock:獲取某個(gè)時(shí)區(qū)下當(dāng)前的瞬時(shí)時(shí)間,日期或者時(shí)間
Instant:Unix時(shí)間,代表時(shí)間戳,比如 2018-01-14T02:20:13.592Z
Duration:兩個(gè)時(shí)間之間,表示一個(gè)絕對(duì)的精確跨度,使用毫秒為單位
Period:兩個(gè)日期之間
ZoneId:時(shí)區(qū)
DateTimeFormatter:格式化輸出
TemporalAdjusters:獲得指定日期時(shí)間等,如當(dāng)月的第一天、今年的最后一天等等
下面看看這些類(lèi)具體如何使用
LocalDate、LocalTime、LocalDateTimeLocalDate是不變的日期時(shí)間對(duì)象代表一個(gè)日期,往往被視為年月日。其他日期字段,如一年中的一天,一周和一周的一天,也可以訪問(wèn)。例如,“2007年10月2日”的值可以被存儲(chǔ)在一個(gè)LocalDate。
LocalTime是不變的日期時(shí)間對(duì)象代表一個(gè)時(shí)間,往往被視為小時(shí)分鐘秒。時(shí)間為代表的納秒級(jí)精度。例如,值“13:45.30.123456789”可以存儲(chǔ)在一個(gè)LocalTime。
LocalDateTime是不變的日期時(shí)間對(duì)象代表一個(gè)日期時(shí)間,往往被視為年、月、日、時(shí)、分、秒。其他日期和時(shí)間字段,如一年中的一天,一周和一周的一天,也可以訪問(wèn)。時(shí)間為代表的納秒級(jí)精度。例如,值“2007年10月2日在13:45.30.123456789”可以存儲(chǔ)在一個(gè)LocalDateTime。
//now()在默認(rèn)時(shí)區(qū)中從系統(tǒng)時(shí)鐘獲取當(dāng)前日期。 LocalDate today = LocalDate.now(); LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS); //等價(jià)于 today.plusWeeks(1) //of(int year, int month, int dayOfMonth) 獲得 LocalDate實(shí)例從一年、月、日。 LocalDate date = LocalDate.of(2019,5,31); LocalTime time = LocalTime.of(20,31,20); //of(LocalDate date, LocalTime time) 獲得 LocalDateTime實(shí)例的日期和時(shí)間。 LocalDateTime dateTime = LocalDateTime.of(date,time); System.out.println(dateTime); //LocalDate結(jié)合LocalTime成一個(gè)LocalDateTime LocalDateTime dateTime2 = date.atTime(time); System.out.println(dateTime2); //2019-05-31T20:31:20DateTimeFormatter
格式器用于解析日期字符串和格式化日期輸出,創(chuàng)建格式器最簡(jiǎn)單的方法是通過(guò) DateTimeFormatter 的靜態(tài)工廠方法以及常量。創(chuàng)建格式器一般有如下三種方式:
常用 ISO 格式常量,如 ISO_LOCAL_DATE
字母模式,如 ofPattern("yyyy/MM/dd")
本地化樣式,如 ofLocalizedDate(FormatStyle.MEDIUM)
和舊的 java.util.DateFormat 相比較,所有的 DateTimeFormatter 實(shí)例都是線程安全的。
使用DateTimeFormatter完成格式化
//獲取默認(rèn)時(shí)區(qū)中從系統(tǒng)時(shí)鐘獲取當(dāng)前日期時(shí)間。 LocalDateTime localDateTime = LocalDateTime.now(); //創(chuàng)建一個(gè)格式化程序使用指定的模式。 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String formatDateTime = localDateTime.format(formatter); System.out.println(formatDateTime); //DateTimeFormatter提供了一些默認(rèn)的格式化器,DateTimeFormatter.ISO_LOCAL_DATE_TIME 格式 yyyy-MM-ddTHH:mm:ss.SSS String dateTime2 = localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); System.out.println(dateTime2);
使用DateTimeFormatter完成解析字符串
//獲得 LocalDate實(shí)例,從使用特定格式的文本字符串解析,文字使用格式化程序解析,返回一個(gè)日期。 LocalDate localDate = LocalDate.parse("2018/11/11",DateTimeFormatter.ofPattern("yyyy/MM/dd")); System.out.println(localDate); //2018-11-11Instant
Instant 表示時(shí)間線上的一點(diǎn)(與 Date 類(lèi)似),它只是簡(jiǎn)單地表示自 1970 年 1 月 1 日 0 時(shí) 0 分 0 秒(UTC)開(kāi)始的秒數(shù)。
Instant 由兩部分組成,一是從原點(diǎn)開(kāi)始到指定時(shí)間點(diǎn)的秒數(shù) s, 二是距離該秒數(shù) s 的納秒數(shù)。它以 Unix 時(shí)間戳的形式存儲(chǔ)日期時(shí)間,不提供處理人類(lèi)意義上的時(shí)間單位(年月日等)。
你可以通過(guò)Instant類(lèi)的工廠方法創(chuàng)建一個(gè)Instant實(shí)例
//調(diào)用instant.now()來(lái)創(chuàng)建一個(gè)確切的表達(dá)當(dāng)前時(shí)間的Instant對(duì)象.另外也有一些其它方法能創(chuàng)建Instant,具體請(qǐng)查閱Java官方文檔。 Instant now = Instant.now(); Instant later = now.plusSeconds(3); Instant earlier = now.minusSeconds(3); //第一個(gè)參數(shù)是秒,第二個(gè)是納秒?yún)?shù),納秒的存儲(chǔ)范圍是0至999,999,999 //2s之后的在加上100萬(wàn)納秒(1s) Instant instant = Instant.ofEpochSecond(2,1000000000); System.out.println(instant); //1970-01-01T00:00:03Z Instant instant1 = Instant.now(); System.out.println(instant1); //2019-05-31T16:19:28.719Z Instant instant2 = Instant.parse("2018-11-11T10:12:35.342Z"); System.out.println(instant2); //2018-11-11T10:12:35.342Z //java.util.Date與Instant可相互轉(zhuǎn)換 Instant timestamp = new Date().toInstant(); Date.from(Instant.now()); //為了更好的顯示,代碼改寫(xiě)為 Date date = new Date(); Instant timestamp = date.toInstant(); System.out.println(date); System.out.println(timestamp); Instant now1 = Instant.now(); Date date1 = Date.from(now1); System.out.println(now1); System.out.println(date1); //輸出結(jié)果 Sat Jun 01 00:29:42 GMT+08:00 2019 2019-05-31T16:29:42.566Z 2019-05-31T16:29:42.588Z Sat Jun 01 00:29:42 GMT+08:00 2019Clock
Clock用于查找當(dāng)前時(shí)刻,可以用來(lái)獲取某個(gè)時(shí)區(qū)下當(dāng)前的日期和時(shí)間,也可以用來(lái)代替舊的System.currentTimeMillis()方法和TimeZone.getDefault()方法。
//返回系統(tǒng)默認(rèn)時(shí)間 Clock clock = Clock.systemDefaultZone(); System.out.println(clock.instant().toString()); //世界協(xié)調(diào)時(shí)UTC Clock clock = Clock.systemUTC(); //通過(guò)Clock獲取當(dāng)前時(shí)刻 System.out.println("當(dāng)前時(shí)刻為:" + clock.instant()); //獲取clock對(duì)應(yīng)的毫秒數(shù),與System.currentTimeMillis()輸出相同 System.out.println(clock.millis()); System.out.println(System.currentTimeMillis());Duration
一個(gè)Duration實(shí)例是不可變的,當(dāng)創(chuàng)建出對(duì)象后就不能改變它的值了。你只能通過(guò)Duration的計(jì)算方法,來(lái)創(chuàng)建出一個(gè)新的Durtaion對(duì)象。你會(huì)在之后的教程中見(jiàn)到的。一個(gè)Duration對(duì)象表示兩個(gè)Instant間的一段時(shí)間。
創(chuàng)建Duration實(shí)例,使用Duration類(lèi)的工廠方法來(lái)創(chuàng)建一個(gè)Duration對(duì)象
Instant first = Instant.now(); // wait some time while something happens Instant second = Instant.now(); Duration duration = Duration.between(first, second); //獲得Duration表示秒數(shù),然后獲得在此期間的分鐘數(shù)、小時(shí)數(shù)、天數(shù) Duration d = Duration.ofSeconds(6000); System.out.println("6000秒相當(dāng)于" + d.toMinutes() + "分"); System.out.println("6000秒相當(dāng)于" + d.toHours() + "小時(shí)"); System.out.println("6000秒相當(dāng)于" + d.toDays() + "天");
訪問(wèn)Duration的時(shí)間
一個(gè)Duration對(duì)象里有兩個(gè)域:納秒值(小于一秒的部分),秒鐘值(一共有幾秒),他們的組合表達(dá)了時(shí)間長(zhǎng)度。注意與使用System.getCurrentTimeMillis()時(shí)不同,Duration不包含毫秒這個(gè)屬性。
你可以通過(guò)以下兩個(gè)方法得到它們的值:getSeconds()和getNano()
Period 是以年月日來(lái)衡量一個(gè)時(shí)間段,用于計(jì)算兩個(gè)日期間隔,所以 between() 方法只能接收 LocalDate 類(lèi)型的參數(shù)。
LocalDate start = LocalDate.of(2018, Month.JANUARY, 1); LocalDate end = LocalDate.of(2020, Month.NOVEMBER, 11); System.out.println("相隔月數(shù):"+Period.between(start, end).getMonths()); System.out.println("相隔天數(shù):"+Period.between(start, end).getDays()); //輸出結(jié)果 相隔月數(shù):10 相隔天數(shù):10
值得注意的是,Period 得到的是差值的絕對(duì)值(對(duì)應(yīng)年月日直接計(jì)算數(shù)學(xué)上的差值),而并不表示真正的區(qū)間距離。
long distanceMonth = start.until(end, ChronoUnit.MONTHS); long distanceDay= start.until(end, ChronoUnit.DAYS); System.out.println("相隔月數(shù)"+distanceMonth); System.out.println("相隔天數(shù)"+distanceDay); //輸出結(jié)果 相隔月數(shù):34 相隔天數(shù):1045ZonedDateTime和ZonedId
ZonedDateTime類(lèi)是Java 8中日期時(shí)間功能里,用于表示帶時(shí)區(qū)的日期與時(shí)間信息的類(lèi)。ZonedDateTime 類(lèi)的值是不可變的,所以其計(jì)算方法會(huì)返回一個(gè)新的ZonedDateTime 實(shí)例。
Java 使用 ZoneId 來(lái)標(biāo)識(shí)不同的時(shí)區(qū),從基準(zhǔn) UTC 開(kāi)始的一個(gè)固定偏移。
創(chuàng)建一個(gè)ZonedDateTime實(shí)例
//使用當(dāng)前時(shí)間作為值新建對(duì)象 ZonedDateTime dateTime = ZonedDateTime.now(); //使用指定的年月日、時(shí)分、納秒以及時(shí)區(qū)ID來(lái)新建對(duì)象 //時(shí)區(qū)是用ZoneId類(lèi)表示的,可以使用ZoneId.now()或ZoneId.of(“xxx”)來(lái)實(shí)例化: //傳給of()方法的參數(shù)是時(shí)區(qū)的ID,如“UTC+1”指距離UTC(格林威治時(shí)間)有一小時(shí)的時(shí)差 ZoneId zoneId = ZoneId.of("UTC+1"); ZonedDateTime dateTime2 = ZonedDateTime.of(2019, 6, 1, 14, 40, 48, 1234, zoneId); //也可以使用另一種方式表示zone id,即使用地區(qū)名字 ZoneId zoneId2 = ZoneId.of("Europe/Copenhagen"); //GregorianCalendar與ZonedDateTime相互轉(zhuǎn)換 ZonedDateTime zonedDateTime = new GregorianCalendar().toZonedDateTime(); GregorianCalendar.from(zonedDateTime);TemporalAdjusters
有的時(shí)候,你需要進(jìn)行一些更加復(fù)雜的操作,比如,將日期調(diào)整到下個(gè)周日、下個(gè)工作日,或者是本月的最后一天。
簡(jiǎn)單應(yīng)用例子
LocalDate localDate = LocalDate.now(); // 1. 本月第一天 LocalDate firstDayOfMonth = localDate.with(TemporalAdjusters.firstDayOfMonth()); // 2. 本月最后一天 LocalDate lastDayOfMonth = localDate.with(TemporalAdjusters.lastDayOfMonth()); // 3. 本年第一天 LocalDate firstDayOfYear = localDate.with(TemporalAdjusters.firstDayOfYear()); // 4. 下個(gè)月第一天 LocalDate firstDayOfNextMonth = localDate.with(TemporalAdjusters.firstDayOfNextMonth()); // 5. 本年度最后一天 LocalDate lastDayOfYear = localDate.with(TemporalAdjusters.lastDayOfYear()); System.out.println(firstDayOfMonth); System.out.println(lastDayOfMonth); System.out.println(firstDayOfYear); System.out.println(firstDayOfNextMonth); System.out.println(lastDayOfYear);
這時(shí),你可以使用重載版本的with方法,向其傳遞一個(gè)提供了更多定制化選擇的TemporalAdjuster對(duì)象,更加靈活地處理日期。TemporalAdjusters類(lèi)通過(guò)靜態(tài)方法提供了大量的常用的TemporalAdjuster的實(shí)現(xiàn)供我們使用。
/** * 時(shí)間校正器TemporalAdjuster */ @Test public void Test() { LocalDateTime now1 = LocalDateTime.now(); //獲取月中的第一天 now1.with(TemporalAdjusters.firstDayOfMonth()); //獲取下一年的第一天 now1.with(TemporalAdjusters.firstDayOfNextYear()); //獲取年中第一天 now1.with(TemporalAdjusters.lastDayOfYear()); //獲取月中最后一天 now1.with(TemporalAdjusters.lastDayOfMonth()); //獲取下個(gè)星期一 now1.with(TemporalAdjusters.next(DayOfWeek.MONDAY)); //自定時(shí)時(shí)間:下一個(gè)工作日,因?yàn)檫@里需要一個(gè)接口,所以完全可以自定義方法 now1.with((e) -> { LocalDateTime now = (LocalDateTime)e; DayOfWeek dow = now.getDayOfWeek(); if (dow.equals(DayOfWeek.FRIDAY)) return now.plusDays(3); else if (dow.equals(DayOfWeek.SATURDAY)) return now.plusDays(2); return now.plusDays(1); }); }轉(zhuǎn)換 java.util.Date 與 LocalDate、LocalTime、LocalDateTime 轉(zhuǎn)換
將Date轉(zhuǎn)換為L(zhǎng)ocalDate,LocalTime,LocalDateTime可以借助于ZonedDateTime和Instant,實(shí)現(xiàn)如下:
Date date = new Date(); System.out.println("current date: " + date); // Date -> LocalDateTime LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); System.out.println("localDateTime by Instant: " + localDateTime); // Date -> LocalDate LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); System.out.println("localDate by Instant: " + localDate); // Date -> LocalTime LocalTime localTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalTime(); System.out.println("localTime by Instant: " + localTime); //2. Date -> LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); System.out.println("localDateTime by ofInstant: " + localDateTime);
由于JDK8實(shí)現(xiàn)了向下兼容,所以Date里在JDK8版本引入了2個(gè)方法,from和
toInstant,所以我們可以借助這兩個(gè)方法來(lái)實(shí)現(xiàn)LocalDateTime到Date的轉(zhuǎn)換。將LocalDateTime轉(zhuǎn)為Date如下:
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("localDateTime: " + localDateTime); // LocalDateTime -> Date Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); System.out.println("LocalDateTime -> current date: " + date); // LocalDate -> Date,時(shí)間默認(rèn)都是00 LocalDate localDate = LocalDate.now(); date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); System.out.println("LocalDate -> current date: " + date);日期與字符串的轉(zhuǎn)換
通過(guò)LocalDate,LocalTime,LocalDateTime的parse方法和DateTimeFormatter來(lái)實(shí)現(xiàn):
//字符串->日期 LocalDate localDate = LocalDate.parse("2018-09-09", DateTimeFormatter.ofPattern("yyyy-MM-dd")); LocalDateTime localDateTime = LocalDateTime.parse("2018-09-10 12:12:12", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); //日期->字符串 String localDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); String localDateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); // 也可以通過(guò)DateTimeFormatter的format方法 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); localDateTime = dateTimeFormatter.format(LocalDateTime.now());時(shí)間戳與LocalDateTime轉(zhuǎn)換
具體實(shí)現(xiàn)如下:
//時(shí)間戳->LocalDateTime public static LocalDateTime convertToDate(long timestamp) { // ofEpochSecond 以秒為單位, ofEpochMilli 以毫秒為單位 // Instant.ofEpochSecond(timestamp); Instant instant = Instant.ofEpochMilli(timestamp); return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); } //LocalDateTime->時(shí)間戳 public static long convertToTimestamp() { LocalDateTime localDateTime = LocalDateTime.now(); return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); }總結(jié)
所有新的日期時(shí)間 API 類(lèi)都實(shí)現(xiàn)了一系列方法用以完成通用的任務(wù),如:加、減、格式化、解析、從日期/時(shí)間中提取多帶帶部分。
Java 8 中新的時(shí)間與日期 API 中的所有類(lèi)都是不可變且線程安全的,任何修改操作都會(huì)返回一個(gè)新的實(shí)例。
新的 API 區(qū)分各種日期時(shí)間概念并且各個(gè)概念使用相似的方法定義模式,這種相似性非常有利于 API 的學(xué)習(xí)??偨Y(jié)一下一般的方法或者方法前綴:
of:靜態(tài)工廠方法,用于創(chuàng)建實(shí)例
now:靜態(tài)工廠方法,用當(dāng)前時(shí)間創(chuàng)建實(shí)例
parse:靜態(tài)工廠方法,從字符串解析得到對(duì)象實(shí)例
get:獲取時(shí)間日期對(duì)象的部分狀態(tài)。
is:檢查某些東西的是否是 true,例如比較時(shí)間前后
with:返回一個(gè)部分狀態(tài)改變了的時(shí)間日期對(duì)象拷貝
plus:返回一個(gè)時(shí)間增加了的、時(shí)間日期對(duì)象拷貝
minus:返回一個(gè)時(shí)間減少了的、時(shí)間日期對(duì)象拷貝
to:轉(zhuǎn)換到另一個(gè)類(lèi)型
at:把這個(gè)對(duì)象與另一個(gè)對(duì)象組合起來(lái),例如 date.atTime(time)
format:提供格式化時(shí)間日期對(duì)象的能力
更多方法使用請(qǐng)參考Java api文檔
參考文章:
http://www.importnew.com/1414...
https://docs.oracle.com/javas...
https://www.jianshu.com/p/f4a...
文章同步發(fā)表在個(gè)人博客kiwen的博客
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/74736.html
Date-Time Java SE 8發(fā)行版中引入的Date-Time包java.time提供了全面的日期和時(shí)間模型,是在JSR 310:Date and Time API下開(kāi)發(fā)的,盡管java.time基于國(guó)際標(biāo)準(zhǔn)化組織(ISO)日歷系統(tǒng),但也支持常用的全球日歷。 此課程介紹了使用基于ISO的類(lèi)來(lái)表示日期和時(shí)間以及操作日期和時(shí)間值的基本原理。 概述 時(shí)間似乎是一個(gè)簡(jiǎn)單的主題,即便是便宜的手表也能...
Java? 教程 Java教程是為JDK 8編寫(xiě)的,本頁(yè)面中描述的示例和實(shí)踐沒(méi)有利用在后續(xù)版本中引入的改進(jìn)。 Java教程是希望使用Java編程語(yǔ)言創(chuàng)建應(yīng)用程序的程序員的實(shí)用指南,其中包括數(shù)百個(gè)完整的工作示例和數(shù)十個(gè)課程,相關(guān)課程組被組織成教程。 覆蓋基礎(chǔ)知識(shí)的路徑 這些教程以書(shū)籍的形式提供,如Java教程,第六版,前往Amazon.com購(gòu)買(mǎi)。 入門(mén) 介紹Java技術(shù)和安裝Java開(kāi)發(fā)軟件并使用...
摘要:合并日期和時(shí)間這個(gè)復(fù)合類(lèi)名叫,是和的合體。截至目前,我們介紹的這些日期時(shí)間對(duì)象都是不可修改的,這是為了更好地支持函數(shù)式編程,確保線程安全,保持領(lǐng)域模式一致性而做出的重大設(shè)計(jì)決定。 新的日期和時(shí)間API Java的API提供了很多有用的組件,能幫助你構(gòu)建復(fù)雜的應(yīng)用。不過(guò),Java API也不總是完美的。我們相信大多數(shù)有經(jīng)驗(yàn)的程序員都會(huì)贊同Java 8之前的庫(kù)對(duì)日期和時(shí)間的支持就非常不理想...
摘要:前言前面一篇文章寫(xiě)了如何安全的使用里面介紹了如何處理日期時(shí)間,以及如何保證線程安全,及其介紹了在中的處理時(shí)間日期默認(rèn)就線程安全的類(lèi)。引入了全新的日期時(shí)間格式工具,線程安全而且使用方便。 前言 前面一篇文章寫(xiě)了《SimpleDateFormat 如何安全的使用?》, 里面介紹了 SimpleDateFormat 如何處理日期/時(shí)間,以及如何保證線程安全,及其介紹了在 Java 8 中的處...
摘要:處理日期日歷和時(shí)間的不足之處將設(shè)定為可變類(lèi)型,以及的非線程安全使其應(yīng)用非常受限。最完整的日期時(shí)間,包含時(shí)區(qū)和相對(duì)或格林威治的時(shí)差。獲取當(dāng)前的日期中的用于表示當(dāng)天日期。 簡(jiǎn)介 伴隨 lambda表達(dá)式、streams 以及一系列小優(yōu)化,Java 8 推出了全新的日期時(shí)間API。 Java處理日期、日歷和時(shí)間的不足之處:將 java.util.Date 設(shè)定為可變類(lèi)型,以及 SimpleD...
閱讀 2592·2021-09-22 15:15
閱讀 724·2021-09-02 15:11
閱讀 1907·2021-08-30 09:48
閱讀 1964·2019-08-30 15:56
閱讀 1603·2019-08-30 15:52
閱讀 2146·2019-08-30 15:44
閱讀 506·2019-08-29 16:29
閱讀 1605·2019-08-29 11:06