簡體   English   中英

Java,將日期設置為0/0/0

[英]Java, set date to 0/0/0

我有一個帶有一些日期的對象,我想在getter中返回它們。 問題是我需要做Date.toString(); 因為我必須打印它們,並且當日期為null時,我得到了NullPointerException

我正在考慮在日期為null時返回日期0/0/0,但是我不知道如何設置該值。 有什么辦法嗎? 就像new Date(0)返回1970-01-01-00:00:00一樣 ,除了返回0/0/0之外,是否有與此類似的東西?

謝謝!

根據定義,沒有日期0/0/0,因為沒有日0和月0。一天是集合{1,..,28或30或31}的成員,而month是集合{的成員。集{1,... 12}。 因此,將0/0/0表示為Date Object是不可能的,而且最好是不可能。

可怕的DateCalendar類在幾年前被java.time類所取代。

LocalDate

LocalDate類表示僅包含日期的值,沒有日期, 時間段offset-from-UTC

您可以用數字設置月份,一月至十二月的理智編號為1-12。

LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.

或者,最好使用預定義的Month枚舉對象,一年中的每個月使用一個。 提示:在整個代碼庫中使用這些Month對象,而不是僅使用整數,可以使您的代碼更具自文檔性,確保有效值並提供類型安全 YearYearMonth

LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;

零日期無意義

除了返回0/0/0之外,還有其他類似的東西嗎?

沒有。

嘗試用全零的日期表示一個null值是錯誤的方法。 日期全為零(年,月和日均為零)是沒有的。

而是選擇一個任意日期作為特殊值。 徹底記錄您的選擇及其含義。

不要選擇時間間隔太短的日期。 許多庫和數據庫的值范圍受到限制。 您不希望數據在那里中斷。

通常,我建議使用1970-01-01T00:00:00Z的紀元,即1970年UTC的第一刻( Z表示UTC,發音為“ Zulu”)。 此刻用作Unix時代參考 ,與Java捆綁在一起的舊式日期時間類以及Java 8和更高版本中內置的現代日期時間類。 因此,許多程序員和系統管理員會意識到這一刻很特別。 為了方便起見, java.time類包含一個常量: Instant.EPOCH

顯然,我的建議適用於對前瞻性近期日期感興趣的常見的面向商業的應用程序,其過去的歷史不能追溯到1970年。如果這不能滿足您的需求,請選擇另一個任意值,例如1900-01-01。


關於java.time

java.time框架內置於Java 8及更高版本中。 這些類取代了麻煩的舊的舊式日期時間類,例如java.util.DateCalendarSimpleDateFormat

要了解更多信息,請參見Oracle教程 並在Stack Overflow中搜索許多示例和說明。 規格為JSR 310

現在處於維護模式Joda-Time項目建議遷移到java.time類。

您可以直接與數據庫交換java.time對象。 使用與JDBC 4.2或更高版本兼容的JDBC驅動程序 不需要字符串,不需要java.sql.*類。

在哪里獲取java.time類?

ThreeTen-Extra項目使用其他類擴展了java.time。 該項目為將來可能在java.time中添加內容提供了一個試驗場。 您可以在這里找到一些有用的類,比如IntervalYearWeekYearQuarter ,和更多

Java使用沒有0年的公歷。 另外,您必須記住,現在也有零個月。 將月份設置為“ 0”將導致獲得一月份,因為月份是基於0索引的。 零日也不存在。 假設您要獲取並返回“現代”日期(AD),則可以在BC時代設置“下界”日期。 因此,當您得到一個日期時,您可以返回一個BC日期,以將其與實際日期區分開。 這是代碼:

Calendar cal = Calendar.getInstance();    
cal.set(Calendar.ERA, GregorianCalendar.BC); //Set the BC era
cal.set(Calendar.YEAR, 1); //Set the year to 1 BC
cal.set(Calendar.MONTH, 0); //Set the month to January
cal.set(Calendar.DAY_OF_MONTH, 1); //Set the day to 1st
DateFormat df = new SimpleDateFormat("yyyy MMM d G"); //Format the date
String returnedDate = df.format(cal.getTime()); //Generate a String of it for other use

如果您還從BC時代獲取日期,則可以根據需要自定義代碼(也許通過設置更早的日期)。

編輯:當然,您可以使用其他人提出的建議,即檢查null並返回"0/0/0"字符串,但這稍后可能會導致進一步的問題,當您嘗試解析上述字符串時。 同樣,由於定義為0/0/0在公歷中不是有效日期(請參見說明),因此,您應該避免使用此“通配符”字符串並設置實際日期,如上所述。

澄清:公歷既不定義也不包含0年,0月或0天也不包含Java實現(這不是故意的限制,它是其概念的一部分)。

我的解決方案是使用EPOCH日期和LocalDate.ofEpochDay()作為基礎來創建LocalDate常量。 而不是返回空日期( 不存在 ),而是根據評估的情況返回LocalDate對象。 然后,根據我在域中獲取的getBirthdate方法,我做了一些事情。

常數的定義

public class LocalDateUtils {

    public static final LocalDate EMPTY_FIELDS = createLocalDate(0);
    public static final LocalDate EMPTY_FIELD_DAY_OF_MONTH = createLocalDate(1);
    public static final LocalDate EMPTY_FIELD_MONTH = createLocalDate(2);
    public static final LocalDate EMPTY_FIELD_YEAR = createLocalDate(3);

    /**
     * Purpose: Create a date with @param epochDay days added
     * Observation: EPOCH (1970-01-01)
     */
    private static LocalDate createLocalDate(long epochDay) {
        return LocalDate.ofEpochDay(epochDay);
    }
}

實作

/**
 * Purpose: Describe a birthday or a constant indicating empty field (s).
 * Observation: According to if the parameters are zeros.
 */
LocalDate getBirthdate(int year,
                       int month,
                       int dayOfMonth) {
    if (dayOfMonth == 0 && month == 0 && year == 0)
        return LocalDateUtils.EMPTY_FIELDS;
    if (dayOfMonth == 0)
        return LocalDateUtils.EMPTY_FIELD_DAY_OF_MONTH;
    if (month == 0)
        return LocalDateUtils.EMPTY_FIELD_MONTH;
    if (year == 0)
        return LocalDateUtils.EMPTY_FIELD_YEAR;
    return LocalDate.of(year, month, dayOfMonth);
}

用法

    if (getBirthdate() == LocalDateUtils.EMPTY_FIELDS) {
    }

    if (getBirthdate() == LocalDateUtils.EMPTY_FIELD_DAY_OF_MONTH) {
    }

    if (getBirthdate() == LocalDateUtils.EMPTY_FIELD_MONTH) {
    }

    if (getBirthdate() == LocalDateUtils.EMPTY_FIELD_YEAR) {
    }

資源

GL

正如您對問題的評論中已經提到的那樣,這種簡單的方法可以滿足您的需求:

public String dateString(Date date) {   
    if (date != null)
        return date.toString();
    else
        return "0/0/0";
}

要么

String dateString;
try {
    dateString = date.toString();
}
catch(NullPointerException e) {
    dateString = "0/0/0";
}

更新 :不建議在評論中建議第二種選擇。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM