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

ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York"));//用指定時區獲取當前時間
通過給一個附加一個,就可以變成:它的日期和時間與相同,但附加的時區不同,因此是兩個不同的時刻.
LocalDateTime ldt = LocalDateTime.of(2019,9,15,15,16,17);
ZonedDateTime zbj = ldt.atZone(ZoneId.SystemDefault());
時區轉換
對象的()方法將關聯時區轉換到另一個時區,轉換后日期和時間都會相應調整。
//以中國時區獲取當前時間
ZonedDateTime zbj = ZoneDateTime.now(ZoneId.of("Asia/Shanghai"));
//轉換為紐約時間
ZonedDateTime zny = zbj.withZoneSameInstant(ZoneId.of("America/New_York"));
有了,將其轉換為本地時間就非常簡單:
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));
}
當前時間戳在java.time中以類型表示,用.now()獲取當前時間戳。
Instance now = Instance.now();
now.getEpochSecond();//秒
now.toEpochMilli();//毫秒
//給某一個時間戳關聯上ZoneId,就得到了ZonedDateTime,繼而可以獲取對應時區的LocalDateTime
// 以指定時間戳創建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轉新API
舊式的Date或轉換為新API對象,通過()方法轉換為對象,再繼續轉換為:
// 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轉舊API
轉換為舊的API對象,只能借助long型時間戳做一個“中轉”:
// 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);
在數據庫中存儲時間和日期
在數據庫中,我們需要存儲的最常用的是時刻(),因為有了時刻信息,就可以根據用戶自己選擇的時區,顯示出正確的本地時間。所以,最好的方法是直接用長整數long表示,在數據庫中存儲為類型。
通過存儲一個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)));
}
}