![](/img/trans.png)
[英]Calendar.get(Calendar.DAY_OF_MONTH) returning wrong day
[英]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”
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
。
因此,存在關於時區的問題。 什么是“今天”和什么是“明天”取決於您的時區。
讓我提起真正的解決方案,而不是進一步弄臟我的大腦: 停止使用這些可怕的日期時間類 。
那些舊的日期時間類( Date
, Calendar
, SimpleDateFormat
)在多年前被現代的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本身。 ZoneOffset
類ZoneOffset
具有一個常量。
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 8及更高版本中。 這些類取代了麻煩的舊的舊式日期時間類,例如java.util.Date
, Calendar
和SimpleDateFormat
。
現在處於維護模式的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.