簡體   English   中英

Android的Calendar.Day_Of_Month是否基於零?

[英]Is Android's Calendar.Day_Of_Month zero based?

根據android文檔,Day_Of_Month是從1開始的(即“ 1”表示每月的第一天)(請參閱https://developer.android.com/reference/java/util/Calendar#DAY_OF_MONTH )。

但是,當我在兩個Android設備上運行以下代碼時,結果為“ 2018-01-02”。 我想念什么嗎?

Calendar cal = new GregorianCalendar();
TimeZone tzone = TimeZone.getTimeZone("GMT");
cal.setTimeZone(tzone);

cal.set(Calendar.HOUR, 12);
cal.set(2018, 0, 1);

DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String date = df.format(cal.getTime());

我不僅僅認為文檔有誤的原因是,我有一些證據表明我的客戶設備之一將日期報告為“ 2018-01-01”

TL;博士

Android的Calendar.Day_Of_Month是否基於零?

沒有。

我得到“ 2018-01-02”…

…報告日期為“ 2018-01-01”

您的1st vs 2nd問題與其他有關:時區。

使用java.time而不是那些非常麻煩的舊類。

OffsetDateTime.of(
    LocalDate.of( 2018 , Month.JANUARY , 1 ) , 
    LocalTime.NOON ,
    ZoneOffset.UTC
)

.toString():2018-01-01T12:00Z

.format(
    DateTimeFormatter.ISO_LOCAL_DATE
)

2018年1月1日

或覆蓋區域/偏移。

.format(
    DateTimeFormatter.ISO_LOCAL_DATE
                     .withZone( ZoneId.of( "Pacific/Kiritimati" ) )  // Using zone 14 hours ahead of UTC. So noon UTC is “tomorrow” in Kiribati.
)

2018年1月2日

時區

如果我在16:00在America/Los_Angeles時區在這里運行代碼,則得到2018-01-01 但是,如果我將您的代碼更改為將hour設置為23而不是12 ,則結果為2018-01-02

因此,存在關於時區的問題。 什么是“今天”和什么是“明天”取決於您的時區。

讓我提起真正的解決方案,而不是進一步弄臟我的大腦: 停止使用這些可怕的日期時間類

java.time

那些舊的日期時間類( DateCalendarSimpleDateFormat )在多年前被現代的java.time類所取代。

顯然,您希望在第一年中午。 這是如何做。 注意理智的編號 :1月到12月的月份是1到12(不像傳統類),倒數第一個月是1到31(像傳統類)。

獲取日期。

LocalDate ld = LocalDate.of( 2018 , 1 , 1 ) ; // January 1, 2018.

或使用更具可讀性的Month枚舉。

LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 1 ) ; // January 1, 2018.

生成一個字符串,以標准ISO 8601格式表示該值。

ld.toString():2018-01-01

獲取一天中的時間。 LocalTime類為此具有一個常量。

LocalTime lt = LocalTime.NOON ; 

將自UTC的偏移量指定為零,即UTC本身。 ZoneOffsetZoneOffset具有一個常量。

ZoneOffset offset = ZoneOffset.UTC ;

組合起來,以OffsetDateTime對象的形式表示一個時刻。

OffsetDateTime odt = OffsetDateTime.of( ld , lt , offset ) ;

生成一個字符串,以標准ISO 8601格式表示該值。

odt.toString():2018-01-01T12:00Z

如果只需要日期部分,請提取LocalDate

LocalDate ld = odt.toLocalDate() ;

或者只是通過定義DateTimeFormatter來僅使用日期部分來打印String。

DateTimeFormatter f = DateTimeFormatter.ISO_LOCAL_DATE ; 
String outputOdtDateOnly = odt.format( f ) ;

2018年1月1日

默認情況下, DateTimeFormatter對象使用新字符串表示的對象的偏移量或區域。 您可以選擇覆蓋該偏移量/區域。 讓我們嘗試一下。

ZoneId z = ZoneId.of( "Pacific/Kiritimati" );  // Most eastern (earliest) time zone is in Kiribati. https://en.wikipedia.org/wiki/Kiribati
DateTimeFormatter fKiritimati = f.withZone( z );
String outputOdtDateOnlyInKiribati = odt.format( fKiritimati );

請清楚,我們更改了格式化程序對象,而不是數據對象,而不是OffsetDateTime對象。 我們增加了一個時區到以前的格式舉行了新的格式化對象null如記錄 並注意java.time如何使用不可變對象 ,在該對象中,將基於原始值而不是更改(“變異”)原始對象來實例化一個新對象。 因此,我們根據第一個對象獲得了第二個DateTimeFormatter對象,但添加了指定的override-zone。

讓我們看看我們得到了什么。

System.out.println( outputOdtDateOnlyInKiribati );

2018年1月2日

驚喜! 回到您的問題中的問題。 基里巴斯的部分地區比世界協調時間早14小時。 因此,在UTC中午時,同時又是Pacific/Kiritimati地區的14小時后,因此明天“第二”。


關於java.time

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

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

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

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

在哪里獲取java.time類?

實際上,您正在做的三件事會影響您的結果。

(1)您使用的Calendar.HOUR是12小時制!

Java文件:

小時:
get和set的字段編號,指示上午或下午的時間。 HOUR用於12小時制(0-11)。 中午和午夜用0而不是12表示。例如,在10:04:15.250 PM,小時是10。

您要使用的是Calendar.HOUR_OF_DAY ,用於24小時制!

Java文件:

HOUR_OF_DAY:
get和set的字段號指示一天中的小時。 HOUR_OF_DAY用於24小時制。 例如,在10:04:15.250 PM,HOUR_OF_DAY是22。

(2)您將時間設置為12。這在使用Calendar.HOUR時會引起一些問題。

(3)您將TimeZone “ GMT”與Calendar.HOUR設置結合使用時,日期會根據用戶所在的實際時區而減少。

例:

我在CST時區,並且運行了以下代碼:

Calendar cal = new GregorianCalendar();
cal.set(2018, 0, 1);
int h = 0;

cal.set(Calendar.HOUR_OF_DAY, h);
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String date1 = df.format(cal.getTime());
Log.e(TAG, "date1 = " + date1)

cal.set(Calendar.HOUR, h);
TimeZone tzone = TimeZone.getTimeZone("GMT");
cal.setTimeZone(tzone);
String date2 = df.format(cal.getTime());
Log.e(TAG, "date2 GMT = " + date2)

並得到h = 0的這些結果:

date1 = 2018-01-01 00:54
date2 GMT = 2017-12-31 18:54

設置h = 12:

date1 = 2018-01-01 12:54
date2 GMT = 2018-01-01 18:54

七個小時后,我會得到:

date1 = 2018-01-01 19:54
date2 GMT = 2018-01-02 01:54

暫無
暫無

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

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