Java的日期類都是怎麼用的

ivanlee717發表於2024-09-30

Java中的Date

為什麼用類表示日期,而不是像其他語言中那樣用一個內建(built-in)型別來表示?例如,Visual Basic 中有一個內建的 date 型別,程式設計師可以採用#12/31/1999格式指定日期。看起來這似乎很方便,程式設計師只需要使用內建的 date 型別而不用考慮類。但實際上,VisualBasic 這樣設計合適嗎?在有些地區,日期表示為月日/年,而另外一些地區則表示為日1月/年。語言設計者是否能夠預見這些問題呢?如果沒有處理好這類問題,語言就有可能陷入混亂,對此感到不滿的程式設計師也會喪失使用這種語言的熱情。如果使用類,這些設計任務就交給了類庫的設計者。如果類設計得不完善,那麼其他程式設計師可以很容易地編寫自己的類,改進或替代(replace)這些系統類(作為印證:Java的日期類庫開始時有些混亂,現在已經重新設計了兩次)。

System.out.println(new Date());這個表示式會構造一個新物件啊你個,這個物件初始化為當前的日期和時間。image-20240926194346958

或者可以對剛構造的物件應用一個方法。Date類中有一個toString的方法。這個方法將生成日期的一個字串描述。image-20240926194605240

在這兩個例子中,構造的物件只使用了一次。通常,可能希望保留所構造的現象從而能繼續使用,為此我們把物件存放在一個變數裡Date rightnow = new Date(),rightnow引用了新構造的物件

image-20240926201214554

物件和物件變數之間存在著一個重要的區別

Date startTime定義了一個物件變數startTime,它可以引用Date型別的物件。但是,一定要認識到它不是一個物件,而且實際上它沒有引用任何物件。所以無法呼叫startTime.toString()方法。所以必須首先初始化startTime變數,可以寫成startTime = rightnow或者startTime = new Date(),這兩種寫法都引用了同一個物件image-20240926202640117

要認識到重要的一點:物件變數並不實際包含一個物件,它只是引用一個物件。在Java中,任何物件變數的值都是一個引用,指向儲存在另外一個地方的某個物件。new 運算子的返回值也是一個引用。下面的語句:
Date startTime =new Date();有兩個部分。表示式new Date()構造了一個Date型別的物件,它的值是新建立物件的一個引用。再將這個引用儲存在 startTime 變數中。
可以顯式地將物件變數設定為null,指示這個物件變數目前沒有引用任何物件。image-20240926203001884

Java的物件變數雖然引用了物件,但是C++中沒有null作用,而且引用不能賦值。應當把物件變數看作是類似於C++的物件指標,例如:
Date rightNow; // Java
實際上等同於
Date* rightNow; //C++
一旦建立了這種關聯,一切就清楚了。當然,只有使用了new呼叫後Date * 指標才會初始化。就這一點而言,C++與 Java的語法兒乎是一樣的。
Date* rightNow= new Date();//C++
如果把一個變數複製到另一個變數,兩個變數就指向同一個日期,即它們是同一個物件的指標。Java中的null引用對應於C+中的NULL指標。
所有的Java物件都儲存在堆中。當一個物件包含另一個物件變數時,它只是包含另一個堆物件的指標。
在C++中,指標十分令人頭疼,因為它們很容易出錯。稍不小心就會建立一個錯誤的指標,或者使記憶體管理出問題。在Java語言中,這些問題都不復存在。如果使用一個沒有初始化的指標,那麼執行時系統將會產生一個行時錯誤,而不是生成隨機的結果。另外,你不必擔心記憶體管理問題,垃圾回收器會處理相關的事宜。
C++確實做了很大的努力,它透過支援複製構造器和賦值送算符來實現物件的自動複製。例如,一個連結串列(linked list)的副本是一個新連結串列,其內客與原始連結串列相同但是有一組獨立的連結。這樣一來就可以適當地設計類,使它們與內建型別有相同的複製行為。在Java中,必須使用cone方法獲得一個物件的完整副本。

LocalDate類

Java的時間是用距離一個固定時間點的毫秒數表示的,這個時間就是所謂

的紀元。它是UTC時間1970年1月1日00:00:00。UTC就是Coordinated Universal Time國際協調時間。

類庫設計者決定將儲存時間與給時間點命名分開。所以,標準Java類庫分別包含了兩個類:一個是用來表示時間點的 Date 類;另一個是用大家熟悉的日曆表示法表示日期的 LocalDate類。Java8引人了另外一些類來處理日期和時間的不同方面--有關內容參見卷Ⅱ第6章。
將時間度量與日曆分開是一種很好的物件導向設計。通常,最好使用不同的類表示不同的概念。
不要使用構造器來構造LocalDate類的物件。實際上,應當使用靜態工廠方法(factorymethod),它會代表你呼叫構造器。下面的表示式:
LocalDate.now()會構造一個新物件,表示構造這個物件時的日期。
可以提供年、月和日來構造對應一個特定日期的物件:
LocalDate.of(1999,12,31)
當然,通常我們都希望將構造的物件儲存在一個物件變數中:
LocalDate newYearsEve = LocalDate.of(1999, 12,31);
一旦有了一個 LocalDate物件,可以用方法getYear、getMonthValue和getDay0fMonth 得到年月和日:

image-20240926204551314

如果在向未來定一個時刻,比如增加1000天來計算是哪一天,我們可以使用plusday方法image-20240926204801966

Java庫的一個比較早的版本曾經有過另一個處理日曆的類,名為GregorianCalendar

GregorianCalendar someday = new GregorianCalendar(2000, 1, 27);
someday.add(Calendar.DAY_OF_MONTH, 1000);
int year = someday.get(Calendar.YEAR);
int month = someday.get(Calendar.MONTH);
int day = someday.get(Calendar.DAY_OF_MONTH);

image-20240926205600364

Eg:列印當月日曆

import java.time.DayOfWeek;
import java.time.LocalDate;

public class Main {
    public static void main(String[] args) {
        LocalDate date = LocalDate.now(); //首先構造一個物件,並用當前日期初始化
        //獲取當前月日
        int month = date.getMonthValue();
        int today = date.getDayOfMonth();
        date = date.minusDays(today - 1);// 講日期設定為當月第一天
        DayOfWeek weekday = date.getDayOfWeek();//並得到這一天是星期幾

        int value = weekday.getValue();// 1=Monday,...,7= Sunday
        System.out.println("Mon Tue Wed Thu Fri Sat Sun");
        for (int i = 1; i < value; i++)
            System.out.print("    ");
        while (date.getMonthValue() == month) {
            System.out.printf("%3d", date.getDayOfMonth());
            if (date.getDayOfMonth() == today) {
                System.out.print("*");
            } else {
                System.out.print(" ");
            }
            date = date.plusDays(1);
            if (date.getDayOfWeek().getValue() == 1)
                System.out.println();

        }
        if (date.getDayOfWeek().getValue() != 1)
            System.out.println();

    }
}

image-20240929172508929

相關文章