簡體   English   中英

Android - GregorianCalendar 顯示錯誤的月份

[英]Android - GregorianCalendar displays wrong month

我嘗試在互聯網上搜索並在 StackOverlflow 上發現了很多關於同一主題的問題,但找不到任何我能夠理解的內容......

所以,我有這個數據 class,其中包含 GregorianCalendar 類型的 dateOfOrigin。 使用 gson 我轉換所有 json 並返回一個包含所有位置的 Observable 數組。 在 json 文件中,我將 dateOfOrigin 添加為 object,如下所示:

{
    "id": 6,
    "name": "Fuse",
    "image": "fuse.jpg",
    "street": "Blaesstraat 208",
    "city": "Brussels Hoofdstedelijk Gewest",
    "zip": 1000,
    "date_of_origin": {"year":1994,"month":4,"dayOfMonth":16},
    "parking": true
}

這就是我的數據 class 的樣子:

data class Location (
    val id : Int,
    val name : String,
    val image : String,
    val street : String,
    val city : String,
    val zip : Int,
    @SerializedName("date_of_origin")
    val originDate : GregorianCalendar?,
    val parking : Boolean = true,
    var imageBitmap : Bitmap? = null
)

每當我嘗試像這樣設置 dateText 時:

originDate?.let {
    dateText = "${it.get(Calendar.DAY_OF_MONTH)} ${it.getDisplayName(Calendar.MONTH, Calendar.SHORT, Locale.getDefault())} ${it.get(Calendar.YEAR)}"

    dateText = resources.getString(R.string.origin_date, dateText)
}

它輸出16 May 1994而不是16 Apr 1994

我無法弄清楚如何解決這個問題......

編輯從月份中減去 1 似乎可以解決大多數情況下的問題。 不過,我有一個結果應該是 output 30 Jan 2016但顯示1 Feb 2016

"date_of_origin": {"year":2016,"month":1,"dayOfMonth":30}

GregorianCalendar表示月份,數字范圍從011 這意味着數字0表示為 1 月,而11表示為 12 月。

因此,如果您的 API 未使用與 Java 實現相同的邏輯,則需要減1

更新: GregorianCalendar(2016, 1, 30)理解為 2 月 30 日。 這在內部轉換為 3 月 1 日,因此當您從日期中減去一個月時,您將得到 2 月 1 日。 您需要使用減去的月份數創建一個GregorianCalendar class 實例,即。 一月為 0,二月為 1,依此類推。

Hawklike的答案是正確的。 您被GregorianCalendar class 采用的瘋狂月份編號方案欺騙了。 避免使用此 class 的眾多原因之一。


tl;博士

myGregCal  
.toZonedDateTime()                           // Convert from obsolete `GregorianCalendar` class to modern `java.time.ZonedDateTime` class.
.toLocalDate()                               // Extract the date portion, without time-of-day and without time zone.
.format(                                     // Generate text representing the value of this date-time object.
    DateTimeFormatter
    .ofLocalizedDate( FormatStyle.MEDIUM )   // Automatically localize.
    .withLocale(                             // Specify a locale for the human language and cultural norms used in localization. 
        Locale.UK
    )
)

2021 年 1 月 23 日

細節

切勿使用GregorianCalendar 此 class 是與 Java 的最早版本捆綁在一起的日期時間類的一部分。 這些類在幾年前被JSR 310中定義的現代java.time類所取代。

如果您必須與尚未更新到java.time的代碼進行互操作,請轉換。 調用添加到舊類的新轉換方法。

GregorianCalendarZonedDateTime取代。

ZonedDateTime zdt = myGregCal.toZonedDateTime() ;  // From legacy class to modern class.

往另一個方向走。

ZonedDateTime zdt = ZonedDateTime.of( 2021 , Month.JANUARY , 23 , 12 , 0 , 0 , 0 , ZoneId.of( "America/Montreal" ) ) ;
GregorianCalendar myGregCal = GregorianCalendar.from( zdt ) ;

或打破該int多個部分。

LocalDate ld = LocalDate.of( 2021 , Month.JANUARY , 23 ) ;
LocalTime lt = LocalTime.of( 12 , 0 ) ;
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
GregorianCalendar myGregCal = GregorianCalendar.from( zdt ) ;

或者使用月份編號而不是Month枚舉。 請注意,與GregorianCalendar不同, java.time使用合理的編號,1-12 表示一月至十二月。

LocalDate.of( 2021 , 1 , 23 )  // Same effect as Month.JANUARY. 

要生成文本,請使用DateTimeFormatter class。 您所需的格式恰好與英國使用的本地化格式相匹配。 因此,通過調用DateTimeFormatter.ofLocalizedDatejava.time自動為您本地化。

Locale locale = Locale.UK ; 
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM ).withLocale( locale ) ;
String output = zdt2.toLocalDate().format( f ) ;

請參閱在 IdeOne.com 上實時運行的代碼

2021 年 1 月 23 日


關於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.*類。 Hibernate 5 & JPA 2.2 支持java.time

從哪里獲得 java.time 課程?

哪個 java.time 庫與哪個版本的 Java 或 Android 一起使用的表

暫無
暫無

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

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