我在日历项目中工作并使用这个 Github 项目: https://github.com/wdullaer/MaterialDateTimePicker
我的日历可以正常工作,但我的要求是禁用所有工作日并仅启用周六和周日。
该库具有 datepickerdialog.setDisabledDays()
功能,我们必须在其中传递 Calendar[]
。
如果我将 Calendar.Monday
添加到数组(返回 int
值),它会抛出类似
setDisabledDays (java.util.Calendar[]) in DatePickerDialog cannot be applied to (int)
我主要尝试做的是,将所有工作日添加到 Calendar
数组中以禁用它们。那么,如何将 int
值转换为 Java 中的 Calendar
呢?
最佳答案
Yes @OleV.V. Any idea on how to do it?
是也不是。我会使用 ZonedDateTime
进行计算,这在您的 Android Java 7 中并不容易使用。如果您要在应用程序中使用日期和/或时间做更多工作和/或您预见维护在未来几年,您应该考虑使用 ThreeTen ABP 库。这为您提供了 JSR-310 中描述的日期和时间类。这些是用于 2017 年日期和时间的选项。另外,由于 Stack Overflow 应该是一个知识库,我将首先介绍这个选项,然后再介绍没有 JSR-310 的选项。
您询问要将什么传递给 setDisabledDays()
。当我阅读您的链接时,您需要传递一个数组,其中包含不允许用户选择的所有日期。原则上是无限多天。因此,您首先需要确定用户真正需要选择一天到过去和/或 future 多长时间。然后强制用户在你的限制内,这样你就可以控制选择。接下来我觉得通过setSelectableDays
来控制会容易很多。这将同时控制边界和星期几,并且星期六和星期日比工作日少,因此您需要一个更短的数组。
编辑:在我下面的代码中,我假设用户必须在 1 年 6 个月前到 future 1 个月的时间范围内选择星期六或星期日。我相信你会为你设定正确的界限。
现代解决方案
// start 1 year 6 months before today
// please change to the number of years, months, weeks and/or days you require
ZonedDateTime start = ZonedDateTime.now(ZoneId.systemDefault()).minusYears(1).minusMonths(6);
// end 1 month after today - also change to your own requirements
ZonedDateTime end = ZonedDateTime.now(ZoneId.systemDefault()).plusMonths(1);
List<Calendar> satsAndSuns = new ArrayList<>(200);
ZonedDateTime current = start;
if (current.getDayOfWeek().equals(DayOfWeek.SUNDAY)) {
satsAndSuns.add(GregorianCalendar.from(current));
}
current = current.with(TemporalAdjusters.nextOrSame(DayOfWeek.SATURDAY));
while (! current.isAfter(end)) {
satsAndSuns.add(GregorianCalendar.from(current));
// add 1 day to get Sunday
current = current.plusDays(1);
assert current.getDayOfWeek().equals(DayOfWeek.SUNDAY);
if (current.isAfter(end)) {
break;
}
satsAndSuns.add(GregorianCalendar.from(current));
// add 6 days to get Saturday
current = current.plusDays(6);
assert current.getDayOfWeek().equals(DayOfWeek.SATURDAY);
}
Calendar[] selecatbleDays = satsAndSuns.toArray(new Calendar[satsAndSuns.size()]);
编辑:我使用 GregorianCalendar.from(current)
将 ZonedDateTime
转换为 MaterialDateTimePicker 需要的 Calendar
对象。 Android 上没有此方法。根据the docs感谢 Basil Bourque,您应该改为使用 DateTimeUtils.toGregorianCalendar(current)
。
今天在我的计算机上运行上面的代码 fragment 生成了一个包含 165 个 Calendar
对象的数组,所有星期六和星期日。
老式解决方案
如果您不想依赖 ThreeTen ABP,请使用此解决方案。使用的算法与上面相同,只是细节不同:
Calendar end = new GregorianCalendar(TimeZone.getDefault());
end.add(Calendar.MONTH, 1);
List<Calendar> satsAndSuns = new ArrayList<>(200);
// start 1 year 6 months before today
Calendar current = new GregorianCalendar(TimeZone.getDefault());
current.add(Calendar.YEAR, -1);
current.add(Calendar.MONTH, -6);
if (current.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
// we need to add a copy because we will continue to modify current
// I really don’t like using clone(), but it’s the simplest way
satsAndSuns.add((Calendar) current.clone());
}
// Set current to next saturday
// This is where Calendar is not so straightforward as ZonedDateTime
// Subtraction of day of week works because in Calendar, Saturday is the last day of the week
current.add(Calendar.DATE, Calendar.SATURDAY - current.get(Calendar.DAY_OF_WEEK));
assert current.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY;
while (! current.after(end)) {
satsAndSuns.add((Calendar) current.clone());
current.add(Calendar.DATE, 1);
assert current.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY;
if (current.after(end)) {
break;
}
satsAndSuns.add((Calendar) current.clone());
current.add(Calendar.DATE, 6);
assert current.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY;
}
Calendar[] selecatbleDays = satsAndSuns.toArray(new Calendar[satsAndSuns.size()]);
.equals()
或 ==
与枚举?
编辑:这实际上不是问题的一部分,但现在我们开始讨论它:我首先使用 current.getDayOfWeek() == DayOfWeek.SUNDAY
因为我发现它更简单一些读取比 .equals()
。它之所以有效,是因为 DayOfWeek
是一个枚举,而 JVM 保证每个枚举常量只有一个实例。请在评论中找到异议。 Basil Bourque 在教导年轻程序员首先也是最重要的一点是使用 .equals()
来比较对象的身份。许多人花了很长时间来寻找由在字符串或其他对象之间使用 ==
引起的错误。
关于java - 转换为 Calendar 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43981023/