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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java 中的日期与时间

發布時間:2025/3/17 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 中的日期与时间 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java 日期時間

標簽 : Java基礎



Date

java.util.Date對象表示一個精確到毫秒的瞬間; 但由于Date從JDK1.0起就開始存在了,歷史悠久,而且功能強大(既包含日期,也包含時間),所以他的大部分構造器/方法都已Deprecated,因此就不再推薦使用(如果貿然使用的話,可能會出現性能/安全方面的問題);下面我僅介紹它還剩下的為數不多的幾個方法(這些方法的共同點是Date與毫秒值的轉換):

  • 構造器

    • Date(): 在底層調用System.currentTimeMillis()作為日期參數.
    • Date(long date): 根據指定的long整數(從1970-1-1 00:00:00以來經過的毫秒數)來生成Date對象.
  • 方法

    • boolean after(Date when): 測試this日期是否在指定日期when之后;
    • boolean before(Date when): 測試this日期是否在指定日期when之前;
    • long getTime(): 獲取從1979-01-01 00:00:00 到Date對象之間經過的毫秒值;
    • void setTime(long time): 設置時間,time含義上同.
/*** Created by jifang on 15/12/30.*/ public class DateTest {@Testpublic void test() {Date dateBefore = new Date();Date dateAfter = new Date(System.currentTimeMillis() + 1);System.out.println("before: " + dateBefore.getTime());System.out.println("after: " + dateAfter.getTime());System.out.println(dateBefore.before(dateAfter));System.out.println(dateAfter.after(dateBefore));dateBefore.setTime(System.currentTimeMillis());System.out.println(dateBefore.getTime());System.out.println(dateBefore.before(dateAfter));} }

Calendar

由于Date存在缺陷,所以JDK又提供了java.util.Calendar來處理日期和時間.Calendar是一個抽象類,是所有日歷類的模板,因此,我們可以繼承Calendar來實現其他的歷法(比如陰歷);

Java中提供了一種Calendar的默認實現java.util.GregorianCalendar格里高利日歷(其實JDK還默認提供了一款日本歷法java.util.JapaneseImperialCalendar),也就是我們所說的公歷. 使用Calendar.getInstance();獲取的就是默認的GregorianCalendar,getInstance()方法的內部會調用cal = new GregorianCalendar(zone, aLocale);來生成一個格里高利日歷實例.

  • Calendar還可以和Date自由轉換.
public class CalendarTest {@Testpublic void test() {Calendar calendar = Calendar.getInstance();Date date = calendar.getTime();Calendar newCalendar = Calendar.getInstance();newCalendar.setTime(date);System.out.println(calendar.get(Calendar.DATE));} }
  • Calendar類提供了大量訪問/修改日期/時間的方法, 常用的方法如下:
MethodDescription
void add(int field, int amount)Adds or subtracts the specified amount of time to the given calendar field, based on the calendar’s rules.
int get(int field)Returns the value of the given calendar field.
int getActualMaximum(int field)Returns the maximum value that the specified calendar field could have, given the time value of this Calendar.
int getActualMinimum(int field)Returns the minimum value that the specified calendar field could have, given the time value of this Calendar.
void roll(int field, int amount)Adds the specified (signed) amount to the specified calendar field without changing larger fields.
void set(int field, int value)Sets the given calendar field to the given value.
void set(int year, int month, int date)Sets the values for the calendar fields YEAR, MONTH, and DAY_OF_MONTH.
void set(int year, int month, int date, int hourOfDay, int minute, int second)Sets the values for the fields YEAR, MONTH, DAY_OF_MONTH, HOUR, MINUTE, and SECOND.
void setTimeInMillis(long millis)Sets this Calendar’s current time from the given long value.
long getTimeInMillis()Returns this Calendar’s time value in milliseconds.

上面的很多方法都需要一個int類型的field參數, field是Calendar類的類變量, 如:Calendar.DATE Calendar.MONTH Calendar.HOUR Calendar.DAY_OF_WEEK, 但需要指出的是Calendar.MONTH月份的起始值不是1, 而是0(一月:0, 二月:1 …), Calendar.DAY_OF_WEEK代表的星期, 起始值是周日(周日:1, 周一:2 …)(其他細節請參考JDK文檔).

注意:

  • 如果Calendar沒有設置相關的值, 就以當前系統時間來設置.
  • add(int field, int amount)的功能非常強大, 如果需要增加某字段, 則讓amount為正數, 如果要減少某字段的值, 讓amount為負數. 且當超出他的允許范圍時, 會發生進位.
  • roll()的含義與用法和add()的類似,但是當被修改的字段超出它允許的范圍時, 他不會進位.
  • set(int field, int value)方法具有延遲修改的功能:他內部設置了一個成員變量,以指示日歷字段field已經被修改,但是該Calendar所代表的時間不會立即修改, 他會直到下次調用get/getTime/getTimeInMillis/add/roll時才會重新計算日歷時間.
public int get(int field) {complete();return internalGet(field); } public long getTimeInMillis() {if (!isTimeSet) {updateTime();}return time; }
  • 測試
public class CalendarTest {@Testpublic void test() {Calendar calendar = Calendar.getInstance();calendar.set(2011, Calendar.JULY, 31);calendar.set(Calendar.MONTH, Calendar.SEPTEMBER);// 將下面注釋放開, 再測試// System.out.println(calendar.get(Calendar.MONTH) + 1 + "月" + calendar.get(Calendar.DATE) + "日");calendar.set(Calendar.DATE, 5);System.out.println(calendar.get(Calendar.MONTH) + 1 + "月" + calendar.get(Calendar.DATE) + "日");} }

日期格式化

完成字符串與日期對象的轉化(format/parse)

DateFormat

java.text.DateFormat是一個抽象類, 他提供了如下幾個方法獲取DateFormat對象.

方法描述
static DateFormat getDateInstance()Gets the date formatter with the default formatting style for the default locale.
static DateFormat getDateTimeInstance()Gets the date/time formatter with the default formatting style for the default locale.
static DateFormat getTimeInstance()Gets the time formatter with the default formatting style for the default locale.

其實上面三個方法還可以指定日期/時間的樣式, 如FULL/LONG/MEDIUM/SHOT, 通過這四個樣式參數可以控制生成的格式化字符串. 但由于在我們的實際開發中很少直接用DateFormat類,因此就不對其做過多的介紹.而我們比較常用的是其子類SimpleDateFormat(其實上面幾個getXxxInstance方法返回的也是SimpleDateFormat實例)

DateFormat dateFormat = DateFormat.getTimeInstance(); System.out.println(dateFormat.getClass().getName());

SimpleDateFormat

java.text.SimpleDateFormat可以非常靈活的格式化Date, 也可以用于解析各種格式的日期字符串.創建SimpleDateFormat對象時需要傳入一個pattern字符串,這個pattern不是正則表達式,而是一個日期模板字符串.

/*** Created by jifang on 15/12/30.*/ public class FormatTest {@Testpublic void client() throws ParseException {DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");// Date -> StringDate date = new Date(System.currentTimeMillis());System.out.println(format.format(date));// String -> DateString timeString = "2015-12-30 08:53:21";Date newDate = format.parse(timeString);System.out.println(newDate);} }

在時間日期格式化時, 有下面幾個方法是最常用的:

方法描述小結
String format(Date date)Formats a Date into a date/time string.Date -> String
Date parse(String source)Parses text from the beginning of the given string to produce a date.String -> Date

當然, pattern我們還可以根據我們的需求有其他的定制形式:

@Testpublic void client() throws ParseException {DateFormat format = new SimpleDateFormat("yy年MM月dd日 hh時mm分ss秒");// Date -> StringDate date = new Date(System.currentTimeMillis());System.out.println(format.format(date));// String -> DateString timeString = "15年12月30日 09時00分29秒";Date newDate = format.parse(timeString);System.out.println(newDate);}

可以看出SimpleDateFormat把日期格式化成怎樣的字符串以及能把怎樣的字符串解析成Date, 完全取決于創建對象時指定的pattern參數,其他的pattern參數以及SimpleDateFormat的方法可以參考JDK文檔.


實戰

時間存儲

將時間存入DB會涉及到跨時區的問題(同一個UTC時間在各個時區顯示不同的數值).因此,在設計數據庫表結構時需要小心謹慎,不能簡單使用數據庫提供的TIMESTAMP或DATETIME(詳見:廖雪峰博客-如何正確地處理時間),比較推薦的是選用一個整數類型(如BIGINT64位)來存儲從1970-01-01 00:00:00到當前時間所經過毫秒數的一個絕對數值.

  • 優點:
    讀取的時間(Long整數)只需要按照用戶所在的時區格式化為字符串就能正確地顯示出來.
  • 缺點
    當開發人員、DBA直接查看DB時,只能看到一串數字.

線程安全formatter

時間的格式化和解析格式在一個項目中往往只用一種,因此沒有必要每次使用時都new出一個Formatter來. 但SimpleDateFormat的format()與parse()并非線程安全(詳見: 關于SimpleDateFormat的非線程安全問題及其解決方案), 因此在并發環境中要注意同步或使用ThreadLocal控制:

  • DateUtil
public class DateUtils {// Each thread will have its own copy of the SimpleDateFormatprivate static final ThreadLocal<SimpleDateFormat> formatterMap = new ThreadLocal<SimpleDateFormat>() {protected SimpleDateFormat initialValue() {return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");}};public static String format(Object obj) {return formatterMap.get().format(obj);}public static Date parse(String source) throws ParseException {return formatterMap.get().parse(source);}public static void main(String[] args) {long start = System.currentTimeMillis();final String[] data = {"1999-11-01 11:11:11","2001-07-08 06:06:06","2007-01-31 02:28:31","1999-11-01 11:11:11","2001-07-08 06:06:06","2007-01-31 02:28:31"};List<Thread> threads = new ArrayList<>(data.length);for (int i = 0; i < data.length; ++i) {final int i2 = i;Thread thread = new Thread(new Runnable() {@Overridepublic void run() {try {for (int j = 0; j < 10_000; j++) {String from = data[i2];Date d = parse(from);String to = format(d);System.out.println("i: " + i2 + "\tj: " + j + "\tThreadID: "+ Thread.currentThread().getId() + "\tThreadName: "+ Thread.currentThread().getName() + "\t" + from + "\t" + to);if (!from.equals(to)) {throw new RuntimeException("date conversion failed after " + j+ " iterations. Expected " + from + " but got " + to);}}} catch (ParseException e) {throw new RuntimeException("parse failed");}}}, "formatter_test_thread_" + i);threads.add(thread);thread.start();}for (Thread thread : threads) {try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("total consume [" + (System.currentTimeMillis() - start) + "] ms.");} }

總結

以上是生活随笔為你收集整理的Java 中的日期与时间的全部內容,希望文章能夠幫你解決所遇到的問題。

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