日期與時間

雖然運用人腦來計算時間並不精確且過程稍有不慎就會出錯,但過去的經驗讓人覺得是可行的。若將人腦計算時間的方法套用在程式上,會讓初學者產生極大的挑戰。因為時間計算包括10進位、60進位、24進位,還有28、30、31甚至32進位的判斷。在Java程式設計中只需要熟悉3樣工具「Date」、「Calendar」、「SimpleDateFormat」,就能將絕大多數的日期與時間的計算解決。

嚴格來說包括「String」也是時間日期運算的必要工具,因為字串是資料最基本的型態與工具。


Date

日期時間最基本的用法,雖然舊版的功能大多被別的物件方法取代但仍是快速處理日期時間的好方法。若有進一步的需求如: 格式化、分時日月年計算,以及條件判斷等,需要搭配到「SimpleDateFormat」、「Calendar」工具。更進一步的需求如: 閏年、農曆、世界末日的用法,其實都仍是在「Date」的基礎之上來完成的。

import java.util.Date;

public class Date01 {

 public static void main(String[] args) {
  
  Date d1=new Date(); //建立名為d1的時間點
  
  System.out.println(d1); //印出d1時間點
  
  System.out.println(d1.getTime());// 1970/1/1 早上8點整至今的毫秒數
  
  Date d2=new Date(); //建立名為d2的時間點
  
  System.out.println(d2.getTime() - d1.getTime()); //2個時間點相滅得到的時間差
 }

}


Calendar

要做到口語化的日期加減,如: 三日後必有大霧、君子報仇十年不晚、選課從昨天上午8點開始到下禮拜三下午4點半。單靠「Date」的1970年早上八點整一天一天加86400000毫秒是不可行的,遇到大小月或閏年或日光節約都會影響結果。「Calendar」可以透過年月週日時分秒豪秒等不同單位計算,Java內建的萬年曆能分毫不差的計算出精確的時間點。
import java.util.Calendar;

public class Calendar01 {

 public static void main(String[] args) {  
  
  Calendar c=Calendar.getInstance();// 現在時間  
  System.out.println("現在時間: "+c.getTime());
  
  c.add(Calendar.DATE, 3); // 將時間設為3天後  
  System.out.println("這個時候會有大霧: "+c.getTime());
  
  c=Calendar.getInstance(); // 重新取得現在時間  
  c.add(Calendar.YEAR, 10); // 將時間設為十年後
  System.out.println("這個時候要報仇: "+c.getTime());
  
  c=Calendar.getInstance(); // 重新取得現在時間  
  c.add(Calendar.DAY_OF_YEAR, -1); // 將時間設為昨天
  c.set(Calendar.HOUR_OF_DAY, 8); //將時間設為8點
  c.set(Calendar.MINUTE, 0); //將時間設為0分
  c.set(Calendar.SECOND, 0); //將時間設為0秒  
  System.out.println("開始選課的時間: "+c.getTime());
  
  c=Calendar.getInstance(); // 重新取得現在時間
  c.add(Calendar.WEEK_OF_YEAR, 1); // 將時間設為下周
  c.set(Calendar.DAY_OF_WEEK, 4); // 將時間設為下周三
  c.set(Calendar.HOUR_OF_DAY, 16); //將時間設為16點
  c.set(Calendar.MINUTE, 30); //將時間設為30分
  c.set(Calendar.SECOND, 0); //將時間設為0秒  
  System.out.println("選課結束的時間: "+c.getTime());// 選課結束的時間  
  
 }

}

Calendar的屬性和方法可以自由變化,不侷限在例子中的少數幾種用法。重點在於如何活用在不同條件下,執行出準確的的日期資訊。


SimpleDateFormat

日期格式的字串讀入和輸出都非常簡單,只要在字串中明確將「yyyy/yy」、「MM/M」、「dd/d」、「HH/h」、「mm/m」等文字以「SimpleDateFormat」建立字串,就可以套用在文字或數值表示的日期。不正確的使用會導致非常微妙和難以捉摸的問題,因為DateFormat和SimpleDateFormat都沒有同步機制的,在多執行緒環境下使用應該使用「synchronized」來避免問題,另外還要留意執行時發生的輸出/入問題。
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class DateFormat01 {

 public static void main(String[] args) { 
  
  SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH點mm分ss秒");  
  
  Calendar c=Calendar.getInstance();// 現在時間  
  System.out.println("現在時間: "+sdf.format(c.getTime()));
  
  c.add(Calendar.DATE, 3); // 將時間設為3天後  
  System.out.println("這個時候會有大霧: "+sdf.format(c.getTime()));
  
  c=Calendar.getInstance(); // 重新取得現在時間  
  c.add(Calendar.YEAR, 10); // 將時間設為十年後
  System.out.println("這個時候要報仇: "+sdf.format(c.getTime()));
  
  c=Calendar.getInstance(); // 重新取得現在時間  
  c.add(Calendar.DATE, -1); // 將時間設為昨天
  c.set(Calendar.HOUR_OF_DAY, 8); //將時間設為8點
  c.set(Calendar.MINUTE, 0); //將時間設為0分
  c.set(Calendar.SECOND, 0); //將時間設為0秒  
  System.out.println("開始選課的時間: "+sdf.format(c.getTime()));
  
  c=Calendar.getInstance(); // 重新取得現在時間
  c.add(Calendar.WEEK_OF_YEAR, 1); // 將時間設為下周
  c.set(Calendar.DAY_OF_WEEK, 4); // 將時間設為下周三
  c.set(Calendar.HOUR_OF_DAY, 16); //將時間設為16點
  c.set(Calendar.MINUTE, 30); //將時間設為30分
  c.set(Calendar.SECOND, 0); //將時間設為0秒  
  System.out.println("選課結束的時間: "+sdf.format(c.getTime()));// 選課結束的時間  
  
 }

}


星期日為每周的第1天 SUN MON TUE WED THU FRI SAT
DAY_OF_WEEK返回值 1 2 3 4 5 6 7


在獲取星期幾Calendar.DAY_OF_WEEK - 1的原因 Java中Calendar.DAY_OF_WEEK其實表示:一周中的第幾天,所以他會受到第一天是星期幾的影響。 有些地區以星期日作為一周的第一天,而有些地區以星期一作為一周的第一天,這2種情況是需要區分的。


在獲取月份時,Calendar.MONTH + 1 的原因 Java中的月份遵循了羅馬歷中的規則:當時一年中的月份數量是不固定的,第一個月是JANUARY。而Java中Calendar.MONTH返回的數值其實是當前月距離第一個月有多少個月份的數值,JANUARY在Java中返回“0”,所以我們需要+1。
請嘗試變更每週第1天的起始值,觀察輸出結果。
星期一為每週的第1天 MON TUE WED THU FRI SAT SUN
DAY_OF_WEEK返回值 1 2 3 4 5 6 7

下一步 陣列

沒有留言:

張貼留言