[英]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
表示月份,數字范圍從0
到11
。 這意味着數字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 的眾多原因之一。
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的代碼進行互操作,請轉換。 調用添加到舊類的新轉換方法。
GregorianCalendar
被ZonedDateTime
取代。
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.ofLocalizedDate
讓java.time自動為您本地化。
Locale locale = Locale.UK ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM ).withLocale( locale ) ;
String output = zdt2.toLocalDate().format( f ) ;
2021 年 1 月 23 日
java.time框架內置於 Java 8 及更高版本中。 這些類取代了麻煩的舊日期時間類,例如java.util.Date
、 Calendar
和SimpleDateFormat
。
要了解更多信息,請參閱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 課程?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.