为什么Calendar.SEPTEMBER不工作?
我想看一个包含整整一天的月份。
private void createRandomData(InMemoryCursor cursor) {
List<Object[]> data = new ArrayList<>();
Calendar today = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
today.set(Calendar.HOUR_OF_DAY,0);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);
today.set(Calendar.MILLISECOND, 0);
mStart = (Calendar) today.clone();
mStart.add(Calendar.SEPTEMBER, -5);
while (mStart.compareTo(today) <= 0) {
data.add(createItem(mStart.getTimeInMillis()));
mStart.add(Calendar.SEPTEMBER, 1);
}
cursor.addAll(data);
}
当我编写Calendar.SEPTEMBER(或其他几个月)时,我在Calendar.SEPTEMBER上看到红线,其中包含:
必须是以下其中一项:Calendar.ERA,Calendar.YEAR,Calendar.MONTH,Calendar.WEEK_OF_YEAR,Calendar.WEEK_OF_MONTH,Calendar.DATE,Calendar.DAY_OF_MONTH,Calendar.DAY_OF_YEAR,Calendar.DAY_OF_WEEK,Calendar.DAY_OF_WEEK_IN_MONTH,Calendar.AM_PM,Google日历.HOUR,Calendar.HOUR_OF_DAY,Calendar.MINUTE,Calendar.SECOND,Calendar.MILLISECOND,Calendar.ZONE_OFFSET,Calendar.DST_OFFSET less ...(Ctrl + F1)此检查查看已用各种支持注释注释的Android API调用(例如RequiresPermission或UiThread),并标记任何未按注释指定的API正确使用的调用。 此检查标记的错误示例:将错误类型的资源整数(例如R.string)传递给期望不同类型的API(例如R.dimen)。 忘记在需要它的方法中调用重写的方法(通过超级方法)调用需要权限但未在清单中声明该权限的方法将资源颜色引用传递给期望RGB整数值的方法。 ...还有很多。 有关更多信息,请参阅developer.android.com/tools/debugging/annotations.html上的文档
当我运行它尽管红线,它显示复杂的日期,如:看到
我从GitHub使用这个库:https://github.com/jruesga/timeline-chart-view是与库相关的问题? 或者关于Java日历?
您正在使用不兼容的选项。 Calendar.add()
的第一个参数是错误中概述的可能选项所定义的时间单位(日,周,小时等)。 Calendar.SEPTEMBER
不是一个时间单位,它是代表九月MONTH
的便利常量,通常用于set()
方法。
假设你迭代了几个月,你需要改变Calendar.MONTH
。
正如@迈克尔的答案中所解释的,您不能在add
方法中使用Calendar.SEPTEMBER
。
如果您想添加或减去指定的月份数量,只需使用Calendar.MONTH
。 如果您想添加/减去天数,则可以使用Calendar.DAY_OF_MONTH
等。
Calendar
API有时可能会引起混淆(大多数时候是IMO),并且存在很多问题和设计问题。
在Android中,有更好的选择:您可以使用ThreeTen Backport,这是Java 8新日期/时间类的一个很好的后端。 为了使它工作,你还需要ThreeTenABP(更多关于如何在这里使用它)。
当您在默认时区中获取Calendar
时,替换的一个好候选是org.threeten.bp.ZonedDateTime
(它表示特定时区中的日期和时间)。 首先我使用now()
方法(在JVM默认时区取当前日期/时间)。 然后我使用org.threeten.bp.LocalTime
将时间设置为午夜。
我还使用minusMonths
方法在当前日期前5个月获取日期,并在循环内部使用toInstant()
方法获取plusMonths
值,并使用plusMonths
方法获取下一个月的值:
// get today at default timezone, at midnight
ZonedDateTime today = ZonedDateTime.now().with(LocalTime.MIDNIGHT);
// 5 months ago
ZonedDateTime start = today.minusMonths(5);
while (start.compareTo(today) <= 0) {
data.add(createItem(start.toInstant().toEpochMilli()));
start = start.plusMonths(1);
}
例如,如果您想添加/减去分钟而不是几个月,则可以使用方法minusMinutes
和plusMinutes
。 对于其他单位也有其他方法(如小时,天等),请检查javadoc以查看所有选项。
使用默认时区的问题是,即使在运行时,它也可以在不通知的情况下进行更改,因此最好始终明确指出您正在使用哪一个。
使用Calendar
,您可以使用TimeZone.getTimeZone(zoneName)
:
Calendar todayCal = Calendar.getInstance(TimeZone.getTimeZone("Europe/London"), Locale.getDefault());
使用ThreeTen Backport,您可以使用ZoneId.of(zoneName)
:
ZonedDateTime today = ZonedDateTime.now(ZoneId.of("Europe/London")).with(LocalTime.MIDNIGHT);
在上面的例子中,我使用了Europe/London
,但您可以将其更改为您想要的任何时区。 该API使用IANA时区名称(始终以Region/City
的格式,如America/Sao_Paulo
或Europe/Berlin
)。 避免使用3字母缩写(如CST
或PST
),因为它们不明确而不是标准。
您可以通过调用ZoneId.getAvailableZoneIds()
或TimeZone.getAvailableIDs()
来获得可用时区列表(并选择最适合您的系统的时TimeZone.getAvailableIDs()
。