日历和数组列表:如何正确分配日期?
Calendar and array list : how do I assign the date right?
下面的 lastDay 变量并不总是包含列表的 i+1。不知道为什么。
我正在介绍 Java 8 的日期。但我仍然想知道出了什么问题......
彼得(非常新手)
// organize the intervals and split them into the years
ArrayList<intervall> tmpIntervallList = new ArrayList<intervall>();
Calendar lastDay = Calendar.getInstance();
for (i = 0; i < deliveryList.size() - 1; i++) {
Log.d(TAG, "my log comments: Intervallanfang " +
deliveryList.get(i).getDatumasString() +" nächstes: " + deliveryList.get(i+1).getDatumasString());
//Beginning of the next intervall -1 is the last day of the Intervall before.
lastDay.set(deliveryList.get(i+1).getYear(),
deliveryList.get(i+1).getMonth(),
deliveryList.get(i+1).getDay());
//debugging
String tmp1String = String.format("%d/%d/%d", lastDay.get(Calendar.DAY_OF_MONTH),
lastDay.get(Calendar.MONTH) + 1,
lastDay.get(Calendar.YEAR));
Log.d(TAG, "my log comments: tmp lastday " + tmp1String );
lastDay.add(Calendar.DATE, -1);
//debugging
String tmpString = String.format("%d/%d/%d", lastDay.get(Calendar.DAY_OF_MONTH),
lastDay.get(Calendar.MONTH) + 1,
lastDay.get(Calendar.YEAR));
Log.d(TAG, "my log comments: ende intervall " + tmpString);
intervall tmp2intervall = new intervall(deliveryList.get(i).getAmountFilled(),
deliveryList.get(i).getYear(),
deliveryList.get(i).getMonth(),
deliveryList.get(i).getDay(),
lastDay.get(Calendar.YEAR),
lastDay.get(Calendar.MONTH),
lastDay.get(Calendar.DAY_OF_MONTH));
tmpIntervallList.add(tmp2intervall);
}
结果是
我的日志评论:Intervallanfang 01/01/2018 nächstes:01/02/2018
我的日志评论:tmp lastday 1/1/2018
我的日志评论:结束时间 31/12/2017
我的日志评论:Intervallanfang 01/02/2018 nächstes:01/06/2018
我的日志评论:tmp lastday 1/1/2018
我的日志评论:结束时间 31/12/2017
我的日志评论:Intervallanfang 01/06/2018 nächstes:01/01/2019
我的日志评论:tmp lastday 1/1/2019
我的日志评论:结束时间 31/12/2018
我的日志评论:Intervallanfang 01/01/2019 nächstes:01/01/2020
我的日志评论:tmp lastday 1/1/2020
我的日志评论:结束时间 31/12/2019
我的日志评论:Intervallanfang 01/01/2020 nächstes:01/06/2020
我的日志评论:tmp lastday 1/1/2020
我的日志评论:结束时间 31/12/2019
我的日志评论:Intervallanfang 01/06/2020 nächstes:02/01/2021
我的日志评论:tmp 最后一天 2/1/2021
我的日志评论:结束时间 1/1/2021
根据要求提供更多源代码
public intervall(int amountFilled, int yearBegin, int monthBegin, int
dayBegin, int yearEnd, int monthEnd, int dayEnd) {
begin = Calendar.getInstance();
end = Calendar.getInstance();
this.setIntervall( yearBegin, monthBegin, dayBegin,
yearEnd, monthEnd, dayEnd);
this.amountFilled = amountFilled;
.....
public void setIntervall(int amountFilled, int yearBegin, int
monthBegin, int dayBegin, int yearEnd, int monthEnd, int dayEnd){
this.begin.set(yearBegin, monthBegin, dayBegin);
this.end.set(yearEnd, monthEnd, dayEnd);
.......
避免遗留日期时间 classes
您使用的是可怕的日期时间 classes,它在几年前被 JSR 中定义的现代 java.time classes 取代310. 永远不要使用 Date
或 Calendar
。
java.time
获取今天的日期。需要时区。对于任何给定时刻,全球各地的日期因时区而异。
ZoneId z = ZoneId.of( "Europe/Berlin" ) ;
LocalDate today = LocalDate.now( z ) ;
生成标准 ISO 8601 格式 YYYY-MM-DD 的字符串。请注意 java.time 使用合理的编号,因此月份为 1-12,不需要 + 1
。
String output = today.toString() ;
要增加或减少该日期的天数,请调用 plusDays
或 minusDays
。 java.time class 使用不可变对象。因此,我们没有改变原始对象,而是得到了一个全新的 LocalDate
对象。
LocalDate yesterday = today.minusDays( 1 ) ;
LocalDate tomorrow = today.plusDays( 1 ) ;
三十加
我建议您添加 ThreeTen-Extra library to your project. This gives you access to the LocalDateRange
class 来表示一对 LocalDate
对象。
LocalDateRange dateRange = LocalDateRange.of( today , today.plusWeeks( 1 ) ) ;
我猜这个 class 可以用来代替你自制的 intervall
class。顺便说一下,Java中的class名称应该有一个首字母大写,Intervall
class名称,intervall
实例变量名称。
这个LocalDateRange
class有几种比较方法,比如邻接、包含、重叠等
boolean containsJan23 = dateRange.contains( LocalDate.of( 2020 , Month.JANUARY , 23 ) ) ;
this does not explain the strange behavior. As written I am in the
course of introducing the Date from Java 8 but still I would like to
understand.
让我们先检查日志输出的前两行:
my log comments: Intervallanfang 01/01/2018 nächstes: 01/02/2018
my log comments: tmp lastday 1/1/2018
(对于不懂德文的读者:第一行表示interval start 01/01/2018 next: 01/02/2018.)
日期 nächstes
和 tmp lastday
来自您 deliveryList
的同一个元素,即 deliveryList.get(i+1)
。 01/02/2018
来自 getDatumasString()
而 1/1/2018
来自 getYear()
、getMonth()
和 getDay()
。在输出中,您已正确地将 1 添加到月份编号,因为月份是从 0 而不是 1 疯狂编号的(可能是令人困惑的 GregorianCalendar
class 的特征)。因此,当这两个日期不一致时,问题一定出在 class 这些交货所属的任何地方。根据您提供的信息,我不知道 class 是什么,更不知道 class 中的问题是什么(我在评论中鼓励您创建一个原因是有原因的最小的、可重现的例子)。
不过有一个模式:当我们读取您的整个日志输出时,nächstes
和 tmp lastday
总是在年份和月份日期上一致(即使在最后一次迭代中,月为 2 更改)。并且 tmp lastday
始终将月份指定为 1(一月),无论它在 nächstes
(2、6 或 1)中是什么。因此,似乎 getMonth()
中存在一个错误,导致它总是 return 0(一月),而不管对象中有什么。
为什么 getMonth()
总是 return 一月,这是我的猜测,但我敢于开始猜测。它可能来自使用 SimpleDateFormat
解析日期字符串,这是一个臭名昭著的 class 麻烦制造者。有两个典型的错误经常导致它 return 一月的日期,即使输入字符串在不同的月份:
- 在格式模式字符串中使用大写
Y
而不是小写 y
作为年份。例如参见 [=34=].
- 在您的情况下更有可能使用小写
m
作为月份。例如参见 [=35=]
如果这两个结果中的任何一个符合您的问题,我几乎可以向您保证一件事:java.time 不会发生这种情况,现代 Java 日期和时间 API Basil Bourque 在另一个答案中正确地认可了这一点。 java.time 在需要开始调试之前很久就可以更好地捕获此类错误。
下面的 lastDay 变量并不总是包含列表的 i+1。不知道为什么。 我正在介绍 Java 8 的日期。但我仍然想知道出了什么问题...... 彼得(非常新手)
// organize the intervals and split them into the years
ArrayList<intervall> tmpIntervallList = new ArrayList<intervall>();
Calendar lastDay = Calendar.getInstance();
for (i = 0; i < deliveryList.size() - 1; i++) {
Log.d(TAG, "my log comments: Intervallanfang " +
deliveryList.get(i).getDatumasString() +" nächstes: " + deliveryList.get(i+1).getDatumasString());
//Beginning of the next intervall -1 is the last day of the Intervall before.
lastDay.set(deliveryList.get(i+1).getYear(),
deliveryList.get(i+1).getMonth(),
deliveryList.get(i+1).getDay());
//debugging
String tmp1String = String.format("%d/%d/%d", lastDay.get(Calendar.DAY_OF_MONTH),
lastDay.get(Calendar.MONTH) + 1,
lastDay.get(Calendar.YEAR));
Log.d(TAG, "my log comments: tmp lastday " + tmp1String );
lastDay.add(Calendar.DATE, -1);
//debugging
String tmpString = String.format("%d/%d/%d", lastDay.get(Calendar.DAY_OF_MONTH),
lastDay.get(Calendar.MONTH) + 1,
lastDay.get(Calendar.YEAR));
Log.d(TAG, "my log comments: ende intervall " + tmpString);
intervall tmp2intervall = new intervall(deliveryList.get(i).getAmountFilled(),
deliveryList.get(i).getYear(),
deliveryList.get(i).getMonth(),
deliveryList.get(i).getDay(),
lastDay.get(Calendar.YEAR),
lastDay.get(Calendar.MONTH),
lastDay.get(Calendar.DAY_OF_MONTH));
tmpIntervallList.add(tmp2intervall);
}
结果是
我的日志评论:Intervallanfang 01/01/2018 nächstes:01/02/2018
我的日志评论:tmp lastday 1/1/2018
我的日志评论:结束时间 31/12/2017
我的日志评论:Intervallanfang 01/02/2018 nächstes:01/06/2018
我的日志评论:tmp lastday 1/1/2018
我的日志评论:结束时间 31/12/2017
我的日志评论:Intervallanfang 01/06/2018 nächstes:01/01/2019
我的日志评论:tmp lastday 1/1/2019
我的日志评论:结束时间 31/12/2018
我的日志评论:Intervallanfang 01/01/2019 nächstes:01/01/2020
我的日志评论:tmp lastday 1/1/2020
我的日志评论:结束时间 31/12/2019
我的日志评论:Intervallanfang 01/01/2020 nächstes:01/06/2020
我的日志评论:tmp lastday 1/1/2020
我的日志评论:结束时间 31/12/2019
我的日志评论:Intervallanfang 01/06/2020 nächstes:02/01/2021
我的日志评论:tmp 最后一天 2/1/2021
我的日志评论:结束时间 1/1/2021
根据要求提供更多源代码
public intervall(int amountFilled, int yearBegin, int monthBegin, int
dayBegin, int yearEnd, int monthEnd, int dayEnd) {
begin = Calendar.getInstance();
end = Calendar.getInstance();
this.setIntervall( yearBegin, monthBegin, dayBegin,
yearEnd, monthEnd, dayEnd);
this.amountFilled = amountFilled;
.....
public void setIntervall(int amountFilled, int yearBegin, int
monthBegin, int dayBegin, int yearEnd, int monthEnd, int dayEnd){
this.begin.set(yearBegin, monthBegin, dayBegin);
this.end.set(yearEnd, monthEnd, dayEnd);
.......
避免遗留日期时间 classes
您使用的是可怕的日期时间 classes,它在几年前被 JSR 中定义的现代 java.time classes 取代310. 永远不要使用 Date
或 Calendar
。
java.time
获取今天的日期。需要时区。对于任何给定时刻,全球各地的日期因时区而异。
ZoneId z = ZoneId.of( "Europe/Berlin" ) ;
LocalDate today = LocalDate.now( z ) ;
生成标准 ISO 8601 格式 YYYY-MM-DD 的字符串。请注意 java.time 使用合理的编号,因此月份为 1-12,不需要 + 1
。
String output = today.toString() ;
要增加或减少该日期的天数,请调用 plusDays
或 minusDays
。 java.time class 使用不可变对象。因此,我们没有改变原始对象,而是得到了一个全新的 LocalDate
对象。
LocalDate yesterday = today.minusDays( 1 ) ;
LocalDate tomorrow = today.plusDays( 1 ) ;
三十加
我建议您添加 ThreeTen-Extra library to your project. This gives you access to the LocalDateRange
class 来表示一对 LocalDate
对象。
LocalDateRange dateRange = LocalDateRange.of( today , today.plusWeeks( 1 ) ) ;
我猜这个 class 可以用来代替你自制的 intervall
class。顺便说一下,Java中的class名称应该有一个首字母大写,Intervall
class名称,intervall
实例变量名称。
这个LocalDateRange
class有几种比较方法,比如邻接、包含、重叠等
boolean containsJan23 = dateRange.contains( LocalDate.of( 2020 , Month.JANUARY , 23 ) ) ;
this does not explain the strange behavior. As written I am in the course of introducing the Date from Java 8 but still I would like to understand.
让我们先检查日志输出的前两行:
my log comments: Intervallanfang 01/01/2018 nächstes: 01/02/2018 my log comments: tmp lastday 1/1/2018
(对于不懂德文的读者:第一行表示interval start 01/01/2018 next: 01/02/2018.)
日期 nächstes
和 tmp lastday
来自您 deliveryList
的同一个元素,即 deliveryList.get(i+1)
。 01/02/2018
来自 getDatumasString()
而 1/1/2018
来自 getYear()
、getMonth()
和 getDay()
。在输出中,您已正确地将 1 添加到月份编号,因为月份是从 0 而不是 1 疯狂编号的(可能是令人困惑的 GregorianCalendar
class 的特征)。因此,当这两个日期不一致时,问题一定出在 class 这些交货所属的任何地方。根据您提供的信息,我不知道 class 是什么,更不知道 class 中的问题是什么(我在评论中鼓励您创建一个原因是有原因的最小的、可重现的例子)。
不过有一个模式:当我们读取您的整个日志输出时,nächstes
和 tmp lastday
总是在年份和月份日期上一致(即使在最后一次迭代中,月为 2 更改)。并且 tmp lastday
始终将月份指定为 1(一月),无论它在 nächstes
(2、6 或 1)中是什么。因此,似乎 getMonth()
中存在一个错误,导致它总是 return 0(一月),而不管对象中有什么。
为什么 getMonth()
总是 return 一月,这是我的猜测,但我敢于开始猜测。它可能来自使用 SimpleDateFormat
解析日期字符串,这是一个臭名昭著的 class 麻烦制造者。有两个典型的错误经常导致它 return 一月的日期,即使输入字符串在不同的月份:
- 在格式模式字符串中使用大写
Y
而不是小写y
作为年份。例如参见 [=34=]. - 在您的情况下更有可能使用小写
m
作为月份。例如参见 [=35=]
如果这两个结果中的任何一个符合您的问题,我几乎可以向您保证一件事:java.time 不会发生这种情况,现代 Java 日期和时间 API Basil Bourque 在另一个答案中正确地认可了这一点。 java.time 在需要开始调试之前很久就可以更好地捕获此类错误。