簡體   English   中英

將 DAY_OF_MONTH 或 DAY_OF_YEAR 添加到 Calendar 對象有什么區別?

[英]What's the difference between adding DAY_OF_MONTH or DAY_OF_YEAR to a Calendar object?

我想將某個日期增加 1 天。 我創建了一個日歷對象,如:

Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2012);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DAY_OF_MONTH, 31);

然后,為了增加 1 天,我可以做兩件事:

cal.add(Calendar.DAY_OF_MONTH, 1);

要么

cal.add(Calendar.DAY_OF_YEAR, 1);

還有其他“DAY”常量,但使用上述 2 種將天數增加 1 的方法,我得到了相同的結果。在這種情況下,這兩者會得到不同的結果嗎?

添加它確實沒有區別,但這

Calendar c = Calendar.getInstance();
System.out.println(c.get(Calendar.DAY_OF_MONTH));
System.out.println(c.get(Calendar.DAY_OF_YEAR));

印刷

28
363

Calendar.add根據日歷的規則在給定的日歷字段中添加或減去指定的時間量。

在這里,您可以添加或減去日歷字段列表:

  • MILLISECOND是 0 到 999 之間的毫秒數

  • SECOND是 0 到 59 之間的秒數

  • MINUTE是 0 到 59 之間的分鍾數

  • HOUR是 0 到 11 之間的小時數

  • HOUR_OF_DAY是 0 到 23 之間的小時數

  • DAY_OF_WEEK是與 1 和 7 之間的周相關的天

  • DAY_OF_MONTH是與 1 到 31 之間的月份相關的日期

  • DAY_OF_YEAR是與 1 到 365 之間的年份相關的日期

  • WEEK_OF_MONTH是從 1 開始的與月份相關的周

  • WEEK_OF_YEAR是從 1 開始的與年份相關的周

  • MONTH是與 0 到 11 之間的年份相關的月份

  • YEAR是從 1 開始的年數

小時、天和周有多個字段,但您選擇哪一個並不重要1 例如,對DAY_OF_WEEK使用 -8 將起作用。

calendar.add(Calendar.DAY_OF_MONTH, -2); // subtract 2 days
calendar.add(Calendar.DAY_OF_WEEK, -2);  // subtract 2 days
calendar.add(Calendar.DAY_OF_YEAR, -2);  // subtract 2 days

calendar.add(Calendar.YEAR, -2);         // subtract 2 years

1使用Calendar.add沒有關系,其他操作結果可能不同。

Calendar.DATE用於您的目的。 在您的情況下,這三個常量是同義詞。

調用 add 時沒有任何區別。 然而,吸氣劑返回不同的結果:D

來自GregorianCalendar#add代碼片段

case DAY_OF_MONTH: // synonym of DATE
 case DAY_OF_YEAR:
 case DAY_OF_WEEK:
    break;
DAY_OF_YEAR

get 和 set 的字段編號表示當前年份中的天數

DAY_OF_MONTH

get 和 set 的字段編號,指示月份中的某一天 這是 DATE 的同義詞

如果一天大於 31,您將看到差異。

在這兩種情況下,您基本上都將日期提前了一個。 所以這兩種方法沒有區別。

但是堅持使用單一方法將使您的代碼庫保持一致,維護人員會感到賓至如歸,並且運行時可能也會通過編譯來優化方法調用。

實際上,根據您選擇的字段類型,可能會有差異:

* http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Calendar.html

使用模型。

為了激發 add() 和 roll() 的行為,考慮一個帶有月、日和年遞增和遞減按鈕的用戶界面組件,以及一個底層的 GregorianCalendar。 如果界面顯示 1999 年 1 月 31 日,用戶按下月份遞增按鈕,它應該顯示什么? 如果底層實現使用 set(),它可能會顯示 1999 年 3 月 3 日。更好的結果是 1999 年 2 月 28 日。此外,如果用戶再次按下月份增量按鈕,它應該顯示 1999 年 3 月 31 日,而不是 3 月 28 日, 1999。通過保存原始日期並使用 add() 或 roll(),根據是否應該影響較大的字段,用戶界面可以像大多數用戶直觀地期望的那樣運行。

tl;博士

LocalDate.of( 2012 , Month.JANUARY , 31 )
    .plusDays( 1 )

2012-02-01

…要么…

LocalDate.of( 2012 , 1 , 31 )  // Sane numbering: 1-12 for January-December, and `2012` means year 2012.
    .plusDays( 1 )

2012-02-01

時間

Calendar類令人困惑、笨拙且設計不佳。 其眾多問題之一是這些傳遞單位標志方法。 幸運的是,您現在可以忘記這個類的所有內容。

Java 8 及更高版本中內置的java.time類現在取代了遺留的日期時間類。

LocalDate

LocalDate類表示沒有時間和時區的僅日期值。

時區對於確定日期至關重要。 對於任何給定時刻,日期因地區而異。 例如,在法國巴黎午夜過后幾分鍾是新的一天,而在魁北克蒙特利爾仍然是“昨天”。

如果未指定時區,JVM 會隱式應用其當前默認時區。 該默認值可能隨時更改,因此您的結果可能會有所不同。 最好將您想要/預期的時區明確指定為參數。

continent/region的格式指定正確的時區名稱,例如America/MontrealAfrica/CasablancaPacific/Auckland 永遠不要使用ESTIST等 3-4 個字母的縮寫,因為它們不是真正的時區,不是標准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

如果您想使用 JVM 的當前默認時區,請詢問它並作為參數傳遞。 如果省略,則隱式應用 JVM 的當前默認值。 最好是明確的,因為 JVM 中任何應用程序的任何線程中的任何代碼都可能在運行時隨時更改默認值。

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

或指定日期。 您可以通過數字設置月份,1-12 月的數字為 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對象而不僅僅是整數,以使您的代碼更具自文檔性、確保有效值並提供類型安全

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

部分

有了LocalDate ,您就可以查詢其部分。

要獲取月份中的日期,即從 2018 年 1 月 23 23開始的“日期”,例如23

int dayOfMonth = ld.getDayOfMonth() ; // 1-31, depending on length of month.

要從 1-365 或閏年 1-366 獲取一年中的第 n 天:

int dayOfYear = ld.getDayOfYear() ;

數學

在 java.time 中添加或減去天數非常簡單和直觀。 便捷方法和時間跨度對象使代碼更加清晰。

LocalDate dayLater = ld.plusDays( 1 ) ;

所以明天將是:

LocalDate tomorrow = LocalDate.now( ZoneId.of( "Africa/Tunis" ) ).plusDays( 1 ) ;

或者,您可以表示不附加到時間線的時間跨度。 對於年-月-日,請使用Period 對於小時-分鍾-秒,請使用Duration

Period p = Period.ofDays( 1 ) ;
LocalDate dayLater = ld.plus( p ) ;

請注意,與遺留類不同, java.time 使用合理的編號 數字20182018年。 1-12 月的月份編號為 1-12。 根據ISO 8601標准,星期一至星期日的星期幾編號為 1-7。


關於java.time

java.time框架內置於 Java 8 及更高版本中。 這些類取代麻煩的老傳統日期時間類,如java.util.DateCalendar ,和SimpleDateFormat

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

要了解更多信息,請參閱Oracle 教程 並在 Stack Overflow 上搜索許多示例和解釋。 規范是JSR 310

從哪里獲得 java.time 類?

ThreeTen-Extra項目用額外的類擴展了 java.time。 該項目是未來可能添加到 java.time 的試驗場。 您可以在這里找到一些有用的類,比如IntervalYearWeekYearQuarter ,和更多

除了日期之外,無論您使用 DAY_OF_MONTH 還是 DAY_OF_YEAR 都沒有任何區別。 但是,當您獲得 call getter 並傳遞其中一個時,這是有道理的。

使用 DATE 或 DAY_OF_MONTH 兩者都相同

這是區別:

DATE or DAY_OF_MONTH : Get and Set indicating the day of the month
DAY_OF_WEEK          : get and set indicating the week number within the current month
DAY_OF_YEAR          : get and set indicating the day number within the current ye

來源: https : //docs.oracle.com/javase/7/docs/api/java/util/Calendar.html

   public static String findDay(int month, int day, int year) {
// Creating a calendar
  Calendar calndr = Calendar.getInstance();
     calndr.set(Calendar.MONTH, month-1);
     calndr.set(Calendar.YEAR, year);        
     calndr.set(Calendar.DAY_OF_MONTH, day);
     String[] strDays = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
                "Friday", "Saturday" };
      return strDays[calndr.get(Calendar.DAY_OF_WEEK)-1].toUpperCase();
    }

}

暫無
暫無

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

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