時間戳在Java中是long表示的毫秒數(shù)
獲取當(dāng)前時間戳:.()
標(biāo)準(zhǔn)庫API
處理時間和日期的API:
Date
import java.util.*;
public class Main {
public static void main(String[] args) {
//獲取當(dāng)前時間
Date date = new Date();
System.out.println(date.getYear()+1900);//必須+1900
System.out.println(date.getMonth()+1);//月份0~11,必須+1
System.out.println(date.getDate()); // 1~31,不能加1
// 轉(zhuǎn)換為String:
System.out.println(date.toString());
// 轉(zhuǎn)換為GMT時區(qū):
System.out.println(date.toGMTString());
// 轉(zhuǎn)換為本地時區(qū):
System.out.println(date.toLocaleString());
}
}
使用對一個Date進行轉(zhuǎn)換,控制日期和時間的格式:
Date date = new Date();
var sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//年-月-日 時:分:秒
System.out.println(sdf.format(date));
Date不能轉(zhuǎn)換時區(qū),除了()可以按照GMT+0:00輸出。Date總是按照當(dāng)前計算機系統(tǒng)默認時區(qū)為基礎(chǔ)進行輸出。
獲取年月日這些信息變成了get(int field),返回的年份不必轉(zhuǎn)換,返回的月份仍然要加1java獲取當(dāng)天零點的時間戳,返回的星期要特別注意,1~7分別表示周日,周一,……,周六。
只有一種方式獲取,即.(),而且一獲取到就是當(dāng)前時間。如果我們想給它設(shè)置成特定的一個日期和時間,就必須先清除所有字段(clear方法)。利用.()可以將一個對象轉(zhuǎn)換成Date對象,然后就可以用進行格式化了。
和Date相比,它提供了時區(qū)轉(zhuǎn)換的功能。時區(qū)用對象表示。
要列出系統(tǒng)支持的所有ID,請使用.()。
有了時區(qū)java獲取當(dāng)天零點的時間戳,我們就可以對指定時間進行轉(zhuǎn)換。例如,下面的例子演示了如何將北京時間2019-11-20 8:15:00轉(zhuǎn)換為紐約時間:
import java.text.*;
import java.util.*;
public class Main {
public static void main(String[] args) {
// 當(dāng)前時間:
Calendar c = Calendar.getInstance();
// 清除所有:
c.clear();
// 設(shè)置為北京時區(qū):
c.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
// 設(shè)置年月日時分秒:
c.set(2019, 10 /* 11月 */, 20, 8, 15, 0);
// 顯示時間:
var sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
System.out.println(sdf.format(c.getTime()));
// 2019-11-19 19:15:00
}
}
利用進行時區(qū)轉(zhuǎn)換的步驟是:
1、清除所有字段;
2、設(shè)定指定時區(qū);
3、設(shè)定日期和時間;
4、創(chuàng)建并設(shè)定目標(biāo)時區(qū);
5、格式化獲取的Date對象(注意Date對象無時區(qū)信息,時區(qū)信息存儲在中)。
因此,本質(zhì)上時區(qū)轉(zhuǎn)換只能通過在顯示的時候完成。
也可以對日期和時間進行簡單的加減:add()方法。
從Java 8開始,java.time包提供了新的日期和時間API,主要涉及的類型有:
以及一套新的用于取代的格式化類型
LocalDateTime dt = LocalDateTime.now(); // 當(dāng)前日期和時間
LocalDate d = dt.toLocalDate(); // 轉(zhuǎn)換到當(dāng)前日期
LocalTime t = dt.toLocalTime(); // 轉(zhuǎn)換到當(dāng)前時間
通過now()方法獲取到的本地日期和時間總是以當(dāng)前默認時區(qū)返回的。
通過指定的日期和時間創(chuàng)建可以通過of()方法。
通過parse()方法傳入標(biāo)準(zhǔn)格式 dt = .parse("2019-11-19T15:16:17");
日期和時間的分割符是T。
自定義輸出格式:
dtf = .("yyyy/MM/dd HH:mm:ss");//自定義格式化 .out.(dtf.(.now()));//用自定義格式解析
提供了對日期和時間進行加減的非常簡單的鏈?zhǔn)秸{(diào)用:() () ()方法等。
對日期和時間調(diào)整使用with()Xxx()方法。如(15)——將時設(shè)置成15
要判斷兩個的先后,可以使用()、()方法,對于和類似
無法與時間戳進行轉(zhuǎn)換,因為沒有時區(qū),無法確定某一時刻。
相當(dāng)于加時區(qū)的組合,它具有時區(qū),可以與long表示的時間戳進行轉(zhuǎn)換。
和
表示兩個時刻之間的時間間隔。表示兩個日期之間的天數(shù)。
d = .(start, end);//start和end都是類型
p = .of(2019, 11, 19).until(.of(2020, 1, 9));
可以表示帶時區(qū)的日期和時間,相當(dāng)于+。
//通過now()方法返回當(dāng)前時間
ZonedDateTime zbj = ZonedDateTime.now();//默認時區(qū)

ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York"));//用指定時區(qū)獲取當(dāng)前時間
通過給一個附加一個,就可以變成:它的日期和時間與相同,但附加的時區(qū)不同,因此是兩個不同的時刻.
LocalDateTime ldt = LocalDateTime.of(2019,9,15,15,16,17);
ZonedDateTime zbj = ldt.atZone(ZoneId.SystemDefault());
時區(qū)轉(zhuǎn)換
對象的()方法將關(guān)聯(lián)時區(qū)轉(zhuǎn)換到另一個時區(qū),轉(zhuǎn)換后日期和時間都會相應(yīng)調(diào)整。
//以中國時區(qū)獲取當(dāng)前時間
ZonedDateTime zbj = ZoneDateTime.now(ZoneId.of("Asia/Shanghai"));
//轉(zhuǎn)換為紐約時間
ZonedDateTime zny = zbj.withZoneSameInstant(ZoneId.of("America/New_York"));
有了,將其轉(zhuǎn)換為本地時間就非常簡單:
zdt = …
ldt = zdt.();
仍然提供了()等加減操作。
是不變對象,線程安全的,用于格式化顯示。
import java.time.*;
import java.time.format.*;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
ZonedDateTime zdt = ZonedDateTime.now();
var formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm ZZZZ");
System.out.println(formatter.format(zdt));
var zhFormatter = DateTimeFormatter.ofPattern("yyyy MMM dd EE HH:mm", Locale.CHINA);

System.out.println(zhFormatter.format(zdt));
var usFormatter = DateTimeFormatter.ofPattern("E, MMMM/dd/yyyy HH:mm", Locale.US);
System.out.println(usFormatter.format(zdt));
}
當(dāng)前時間戳在java.time中以類型表示,用.now()獲取當(dāng)前時間戳。
Instance now = Instance.now();
now.getEpochSecond();//秒
now.toEpochMilli();//毫秒
//給某一個時間戳關(guān)聯(lián)上ZoneId,就得到了ZonedDateTime,繼而可以獲取對應(yīng)時區(qū)的LocalDateTime
// 以指定時間戳創(chuàng)建Instant:
Instant ins = Instant.ofEpochSecond(1568568760);
ZonedDateTime zdt = ins.atZone(ZoneId.systemDefault());
System.out.println(zdt); // 2019-09-16T01:32:40+08:00[Asia/Shanghai]
最佳實踐 舊API轉(zhuǎn)新API
舊式的Date或轉(zhuǎn)換為新API對象,通過()方法轉(zhuǎn)換為對象,再繼續(xù)轉(zhuǎn)換為:
// Date -> Instant:
Instant ins1 = new Date().toInstant();
// Calendar -> Instant -> ZonedDateTime:
Calendar calendar = Calendar.getInstance();
Instant ins2 = Calendar.getInstance().toInstant();
ZonedDateTime zdt = ins2.atZone(calendar.getTimeZone().toZoneId());
新API轉(zhuǎn)舊API
轉(zhuǎn)換為舊的API對象,只能借助long型時間戳做一個“中轉(zhuǎn)”:
// ZonedDateTime -> long:

ZonedDateTime zdt = ZonedDateTime.now();
long ts = zdt.toEpochSecond() * 1000;
// long -> Date:
Date date = new Date(ts);
// long -> Calendar:
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.setTimeZone(TimeZone.getTimeZone(zdt.getZone().getId()));
calendar.setTimeInMillis(zdt.toEpochSecond() * 1000);
在數(shù)據(jù)庫中存儲時間和日期
在數(shù)據(jù)庫中,我們需要存儲的最常用的是時刻(),因為有了時刻信息,就可以根據(jù)用戶自己選擇的時區(qū),顯示出正確的本地時間。所以,最好的方法是直接用長整數(shù)long表示,在數(shù)據(jù)庫中存儲為類型。
通過存儲一個long型時間戳,我們可以編寫一個()的方法,非常簡單地為不同用戶以不同的偏好來顯示不同的本地時間:
import java.time.*;
import java.time.format.*;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
long ts = 1574208900000L;
System.out.println(timestampToString(ts, Locale.CHINA, "Asia/Shanghai"));
System.out.println(timestampToString(ts, Locale.US, "America/New_York"));
}
static String timestampToString(long epochMilli, Locale lo, String zoneId) {
Instant ins = Instant.ofEpochMilli(epochMilli);
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT);
return f.withLocale(lo).format(ZonedDateTime.ofInstant(ins, ZoneId.of(zoneId)));
}
}