[英]Android - GregorianCalendar displays wrong month
I tried searching the internet and found a lot of questions on StackOverlflow somewhat regarding the same topic, but couldn't find anything that I was able to understand...我尝试在互联网上搜索并在 StackOverlflow 上发现了很多关于同一主题的问题,但找不到任何我能够理解的内容......
So, I have this data class that contains a dateOfOrigin of type GregorianCalendar.所以,我有这个数据 class,其中包含 GregorianCalendar 类型的 dateOfOrigin。 Using gson I convert all json and return an Observable array with all locations.
使用 gson 我转换所有 json 并返回一个包含所有位置的 Observable 数组。 Inside the json file, I added the dateOfOrigin as an object like so:
在 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
}
And this is what my data class looks like:这就是我的数据 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 )
Whenever I try to set the dateText like this:每当我尝试像这样设置 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)
}
It outputs 16 May 1994
instead of 16 Apr 1994
它输出
16 May 1994
而不是16 Apr 1994
I'm not able to figure out how to fix this...我无法弄清楚如何解决这个问题......
EDIT Subtracting 1 from the month seems to fix the problem for most cases.编辑从月份中减去 1 似乎可以解决大多数情况下的问题。 Still, I have one result that is supposed to output
30 Jan 2016
but displays 1 Feb 2016
.不过,我有一个结果应该是 output
30 Jan 2016
但显示1 Feb 2016
。
"date_of_origin": {"year":2016,"month":1,"dayOfMonth":30}
GregorianCalendar
represents months with numbers in the range from 0
to 11
. GregorianCalendar
表示月份,数字范围从0
到11
。 This means that the number 0
is represented as January and 11
is represented as of December.这意味着数字
0
表示为 1 月,而11
表示为 12 月。
Therefore you need to subtract 1
if your API is not using the same logic as the Java implementation.因此,如果您的 API 未使用与 Java 实现相同的逻辑,则需要减
1
。
Updated: GregorianCalendar(2016, 1, 30)
is understood as 30th of February.更新:
GregorianCalendar(2016, 1, 30)
理解为 2 月 30 日。 This is internally converted to 1st of March, therefore when you subtract one month from the date, you get 1st of February.这在内部转换为 3 月 1 日,因此当您从日期中减去一个月时,您将得到 2 月 1 日。 You need to create an instance of
GregorianCalendar
class already with the subtracted month number, ie.您需要使用减去的月份数创建一个
GregorianCalendar
class 实例,即。 January as 0, February as 1 and so on.一月为 0,二月为 1,依此类推。
The Answer by Hawklike is correct. Hawklike的答案是正确的。 You were tricked by the crazy month-numbering scheme employed by the
GregorianCalendar
class.您被
GregorianCalendar
class 采用的疯狂月份编号方案欺骗了。 One of many reasons to avoid this 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
)
)
23 Jan 2021
2021 年 1 月 23 日
Never use GregorianCalendar
.切勿使用
GregorianCalendar
。 This class is part of the date-time classes bundled with the earliest versions of Java.此 class 是与 Java 的最早版本捆绑在一起的日期时间类的一部分。 These classes were years ago supplanted by the modern java.time classes defined in JSR 310 .
这些类在几年前被JSR 310中定义的现代java.time类所取代。
If you must interoperate with code not yet updated to java.time , convert.如果您必须与尚未更新到java.time的代码进行互操作,请转换。 Call new conversion methods added to the old classes.
调用添加到旧类的新转换方法。
GregorianCalendar
was replaced by ZonedDateTime
. GregorianCalendar
被ZonedDateTime
取代。
ZonedDateTime zdt = myGregCal.toZonedDateTime() ; // From legacy class to modern class.
Going the other direction.往另一个方向走。
ZonedDateTime zdt = ZonedDateTime.of( 2021 , Month.JANUARY , 23 , 12 , 0 , 0 , 0 , ZoneId.of( "America/Montreal" ) ) ;
GregorianCalendar myGregCal = GregorianCalendar.from( zdt ) ;
Or break that int multiple parts.或打破该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 ) ;
Or use month number rather than Month
enum for the month.或者使用月份编号而不是
Month
枚举。 Notice that java.time uses sane numbering, 1-12 for January-December, unlike GregorianCalendar
.请注意,与
GregorianCalendar
不同, java.time使用合理的编号,1-12 表示一月至十二月。
LocalDate.of( 2021 , 1 , 23 ) // Same effect as Month.JANUARY.
To generate text, use DateTimeFormatter
class.要生成文本,请使用
DateTimeFormatter
class。 Your desired format happens to match that of localized format used in the UK.您所需的格式恰好与英国使用的本地化格式相匹配。 So let java.time automatically localize for you by calling
DateTimeFormatter.ofLocalizedDate
.因此,通过调用
DateTimeFormatter.ofLocalizedDate
让java.time自动为您本地化。
Locale locale = Locale.UK ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM ).withLocale( locale ) ;
String output = zdt2.toLocalDate().format( f ) ;
See this code run live at IdeOne.com .请参阅在 IdeOne.com 上实时运行的代码。
23 Jan 2021
2021 年 1 月 23 日
The java.time framework is built into Java 8 and later. java.time框架内置于 Java 8 及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as
java.util.Date
, Calendar
, & SimpleDateFormat
.这些类取代了麻烦的旧日期时间类,例如
java.util.Date
、 Calendar
和SimpleDateFormat
。
To learn more, see the Oracle Tutorial .要了解更多信息,请参阅Oracle 教程。 And search Stack Overflow for many examples and explanations.
并在 Stack Overflow 上搜索许多示例和解释。 Specification is JSR 310 .
规范是JSR 310 。
The Joda-Time project, now in maintenance mode , advises migration to the java.time classes.现在处于维护模式的Joda-Time项目建议迁移到java.time类。
You may exchange java.time objects directly with your database.您可以直接与数据库交换java.time对象。 Use a JDBC driver compliant with JDBC 4.2 or later.
使用符合JDBC 4.2或更高版本的JDBC 驱动程序。 No need for strings, no need for
java.sql.*
classes.不需要字符串,不需要
java.sql.*
类。 Hibernate 5 & JPA 2.2 support java.time . Hibernate 5 & JPA 2.2 支持java.time 。
Where to obtain the java.time classes?从哪里获得 java.time 课程?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.