日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Date和Calendar

發布時間:2025/3/15 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Date和Calendar 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

此文章來源于廖雪峰博客:https://www.liaoxuefeng.com/wiki/1252599548343744/1303791989162017

在計算機中,應該如何表示日期和時間呢?

我們經常看到的日期和時間表示方式如下:

  • 2019-11-20 0:15:01 GMT+00:00
  • 2019年11月20日8:15:01
  • 11/19/2019 19:15:01 America/New_York

如果直接以字符串的形式存儲,那么不同的格式,不同的語言會讓表示方式非常繁瑣。

在理解日期和時間的表示方式之前,我們先要理解數據的存儲和展示。

當我們定義一個整型變量并賦值時:

int n = 123400;

編譯器會把上述字符串(程序源碼就是一個字符串)編譯成字節碼。在程序的運行期,變量n指向的內存實際上是一個4字節區域:

┌──┬──┬──┬──┐ │00│01│e2│08│ └──┴──┴──┴──┘

注意到計算機內存除了二進制的0/1外沒有其他任何格式。上述十六機制是為了簡化表示。

當我們用System.out.println(n)打印這個整數的時候,實際上println()這個方法在內部把int類型轉換成String類型,然后打印出字符串123400。

類似的,我們也可以以十六進制的形式打印這個整數,或者,如果n表示一個價格,我們就以$123,400.00的形式來打印它:

import java.text.*; import java.util.*;public class Main {public static void main(String[] args) {int n = 123400;// 123400System.out.println(n);// 1e208System.out.println(Integer.toHexString(n));// $123,400.00System.out.println(NumberFormat.getCurrencyInstance(Locale.US).format(n));} }

?Run

123400 1e208 $123,400.00

可見,整數123400是數據的存儲格式,它的存儲格式非常簡單。而我們打印的各種各樣的字符串,則是數據的展示格式。展示格式有多種形式,但本質上它就是一個轉換方法:

String toDisplay(int n) { ... }

理解了數據的存儲和展示,我們回頭看看以下幾種日期和時間:

  • 2019-11-20 0:15:01 GMT+00:00
  • 2019年11月20日8:15:01
  • 11/19/2019 19:15:01 America/New_York

它們實際上是數據的展示格式,分別按英國時區、中國時區、紐約時區對同一個時刻進行展示。而這個“同一個時刻”在計算機中存儲的本質上只是一個整數,我們稱它為Epoch Time。

Epoch Time是計算從1970年1月1日零點(格林威治時區/GMT+00:00)到現在所經歷的秒數,例如:

1574208900表示從從1970年1月1日零點GMT時區到該時刻一共經歷了1574208900秒,換算成倫敦、北京和紐約時間分別是:

1574208900 = 北京時間2019-11-20 8:15:00= 倫敦時間2019-11-20 0:15:00= 紐約時間2019-11-19 19:15:00

?

因此,在計算機中,只需要存儲一個整數1574208900表示某一時刻。當需要顯示為某一地區的當地時間時,我們就把它格式化為一個字符串:

String displayDateTime(int n, String timezone) { ... }

Epoch Time又稱為時間戳,在不同的編程語言中,會有幾種存儲方式:

  • 以秒為單位的整數:1574208900,缺點是精度只能到秒;
  • 以毫秒為單位的整數:1574208900123,最后3位表示毫秒數;
  • 以秒為單位的浮點數:1574208900.123,小數點后面表示零點幾秒。

它們之間轉換非常簡單。而在Java程序中,時間戳通常是用long表示的毫秒數,即:

long t = 1574208900123L;

轉換成北京時間就是2019-11-20T8:15:00.123。要獲取當前時間戳,可以使用System.currentTimeMillis(),這是Java程序獲取時間戳最常用的方法。

標準庫API

我們再來看一下Java標準庫提供的API。Java標準庫有兩套處理日期和時間的API:

  • 一套定義在java.util這個包里面,主要包括Date、Calendar和TimeZone這幾個類;
  • 一套新的API是在Java 8引入的,定義在java.time這個包里面,主要包括LocalDateTime、ZonedDateTime、ZoneId等。

為什么會有新舊兩套API呢?因為歷史遺留原因,舊的API存在很多問題,所以引入了新的API。

那么我們能不能跳過舊的API直接用新的API呢?如果涉及到遺留代碼就不行,因為很多遺留代碼仍然使用舊的API,所以目前仍然需要對舊的API有一定了解,很多時候還需要在新舊兩種對象之間進行轉換。

本節我們快速講解舊API的常用類型和方法。

Date

java.util.Date是用于表示一個日期和時間的對象,注意與java.sql.Date區分,后者用在數據庫中。如果觀察Date的源碼,可以發現它實際上存儲了一個long類型的以毫秒表示的時間戳:

public class Date implements Serializable, Cloneable, Comparable<Date> {private transient long fastTime;... }

我們來看Date的基本用法:

import java.util.*;public class Main {public static void main(String[] args) {// 獲取當前時間:Date date = new Date();System.out.println(date.getYear() + 1900); // 必須加上1900System.out.println(date.getMonth() + 1); // 0~11,必須加上1System.out.println(date.getDate()); // 1~31,不能加1// 轉換為String:System.out.println(date.toString());// 轉換為GMT時區:System.out.println(date.toGMTString());// 轉換為本地時區:System.out.println(date.toLocaleString());} }

?Run

Note:?Main.java?uses?or?overrides?a?deprecated?API. Note:?Recompile?with?-Xlint:deprecation?for?details. 2021 1 1 Fri?Jan?01?02:25:18?UTC?2021 1?Jan?2021?02:25:18?GMT Jan?1,?2021,?2:25:18?AM

注意getYear()返回的年份必須加上1900,getMonth()返回的月份是0~11分別表示1~12月,所以要加1,而getDate()返回的日期范圍是1~31,又不能加1。

打印本地時區表示的日期和時間時,不同的計算機可能會有不同的結果。如果我們想要針對用戶的偏好精確地控制日期和時間的格式,就可以使用SimpleDateFormat對一個Date進行轉換。它用預定義的字符串表示格式化:

  • yyyy:年
  • MM:月
  • dd: 日
  • HH: 小時
  • mm: 分鐘
  • ss: 秒

我們來看如何以自定義的格式輸出:

import java.text.*; import java.util.*;public class Main {public static void main(String[] args) {// 獲取當前時間:Date date = new Date();var sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println(sdf.format(date));} }

?Run

2021-01-01 02:26:36

Java的格式化預定義了許多不同的格式,我們以MMM和E為例:

import java.text.*; import java.util.*;public class Main {public static void main(String[] args) {// 獲取當前時間:Date date = new Date();var sdf = new SimpleDateFormat("E MMM dd, yyyy");System.out.println(sdf.format(date));} }

?Run

Fri?Jan?01,?2021

上述代碼在不同的語言環境會打印出類似Sun Sep 15, 2019這樣的日期。可以從JDK文檔查看詳細的格式說明。一般來說,字母越長,輸出越長。以M為例,假設當前月份是9月:

  • M:輸出9
  • MM:輸出09
  • MMM:輸出Sep
  • MMMM:輸出September

Date對象有幾個嚴重的問題:它不能轉換時區,除了toGMTString()可以按GMT+0:00輸出外,Date總是以當前計算機系統的默認時區為基礎進行輸出。此外,我們也很難對日期和時間進行加減,計算兩個日期相差多少天,計算某個月第一個星期一的日期等。

Calendar

Calendar可以用于獲取并設置年、月、日、時、分、秒,它和Date比,主要多了一個可以做簡單的日期和時間運算的功能。

我們來看Calendar的基本用法:

import java.util.*;public class Main {public static void main(String[] args) {// 獲取當前時間:Calendar c = Calendar.getInstance();int y = c.get(Calendar.YEAR);int m = 1 + c.get(Calendar.MONTH);int d = c.get(Calendar.DAY_OF_MONTH);int w = c.get(Calendar.DAY_OF_WEEK);int hh = c.get(Calendar.HOUR_OF_DAY);int mm = c.get(Calendar.MINUTE);int ss = c.get(Calendar.SECOND);int ms = c.get(Calendar.MILLISECOND);System.out.println(y + "-" + m + "-" + d + " " + w + " " + hh + ":" + mm + ":" + ss + "." + ms);} }

?Run

2021-1-1?6?2:28:26.25

注意到Calendar獲取年月日這些信息變成了get(int field),返回的年份不必轉換,返回的月份仍然要加1,返回的星期要特別注意,1~7分別表示周日,周一,……,周六。

Calendar只有一種方式獲取,即Calendar.getInstance(),而且一獲取到就是當前時間。如果我們想給它設置成特定的一個日期和時間,就必須先清除所有字段:

import java.text.*; import java.util.*;public class Main {public static void main(String[] args) {// 當前時間:Calendar c = Calendar.getInstance();// 清除所有:c.clear();// 設置2019年:c.set(Calendar.YEAR, 2019);// 設置9月:注意8表示9月:c.set(Calendar.MONTH, 8);// 設置2日:c.set(Calendar.DATE, 2);// 設置時間:c.set(Calendar.HOUR_OF_DAY, 21);c.set(Calendar.MINUTE, 22);c.set(Calendar.SECOND, 23);System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(c.getTime()));// 2019-09-02 21:22:23} }

?Run

2019-09-02?21:22:23

利用Calendar.getTime()可以將一個Calendar對象轉換成Date對象,然后就可以用SimpleDateFormat進行格式化了。

TimeZone

Calendar和Date相比,它提供了時區轉換的功能。時區用TimeZone對象表示:

import java.util.*;public class Main {public static void main(String[] args) {TimeZone tzDefault = TimeZone.getDefault(); // 當前時區TimeZone tzGMT9 = TimeZone.getTimeZone("GMT+09:00"); // GMT+9:00時區TimeZone tzNY = TimeZone.getTimeZone("America/New_York"); // 紐約時區System.out.println(tzDefault.getID()); // Asia/ShanghaiSystem.out.println(tzGMT9.getID()); // GMT+09:00System.out.println(tzNY.getID()); // America/New_York} }

?Run

Etc/UTC GMT+09:00 America/New_York

時區的唯一標識是以字符串表示的ID,我們獲取指定TimeZone對象也是以這個ID為參數獲取,GMT+09:00、Asia/Shanghai都是有效的時區ID。要列出系統支持的所有ID,請使用TimeZone.getAvailableIDs()。

有了時區,我們就可以對指定時間進行轉換。例如,下面的例子演示了如何將北京時間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} }

?Run

2019-11-19?19:15:00

可見,利用Calendar進行時區轉換的步驟是:

  • 清除所有字段;
  • 設定指定時區;
  • 設定日期和時間;
  • 創建SimpleDateFormat并設定目標時區;
  • 格式化獲取的Date對象(注意Date對象無時區信息,時區信息存儲在SimpleDateFormat中)。
  • 因此,本質上時區轉換只能通過SimpleDateFormat在顯示的時候完成。

    Calendar也可以對日期和時間進行簡單的加減:

    import java.text.*; import java.util.*;public class Main {public static void main(String[] args) {// 當前時間:Calendar c = Calendar.getInstance();// 清除所有:c.clear();// 設置年月日時分秒:c.set(2019, 10 /* 11月 */, 20, 8, 15, 0);// 加5天并減去2小時:c.add(Calendar.DAY_OF_MONTH, 5);c.add(Calendar.HOUR_OF_DAY, -2);// 顯示時間:var sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date d = c.getTime();System.out.println(sdf.format(d));// 2019-11-25 6:15:00} }

    ?Run

    2019-11-25?06:15:00

    小結

    計算機表示的時間是以整數表示的時間戳存儲的,即Epoch Time,Java使用long型來表示以毫秒為單位的時間戳,通過System.currentTimeMillis()獲取當前時間戳。

    Java有兩套日期和時間的API:

    • 舊的Date、Calendar和TimeZone;
    • 新的LocalDateTime、ZonedDateTime、ZoneId等。

    分別位于java.util和java.time包中。

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    總結

    以上是生活随笔為你收集整理的Date和Calendar的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。