【发布时间】:2021-11-03 03:21:38
【问题描述】:
我见过的所有日历视图库和基于日历的日期选择器的示例都使用旧的日历 API。但是,我还没有发现任何使用 Java 8 日期 API 来构建日历视图的工具。这是我正在努力实现并且基本上已经完成的事情,但我遇到的问题是使用语言环境设置一周的第一天。
我已经设法获取并显示给定月份一周中每一天的所有日期。但是,我遇到的问题是生成的日历不是根据我的语言环境从一周的第一天开始的。 Java.Time 使用的DayOfWeek 枚举从星期一到星期日(1 - 7)开始计算天数。但是,我希望日历按地区显示日期,在我的例子中是周日到周六。
根据文档,WeekFields 类提供了对基于区域设置的星期几的访问,并具有“正确”的值,但我不确定如何正确使用它。
这是我到目前为止所做的:
private enum class DaysOfWeek {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
}
fun TimetableCalendar() {
val dates = getDaysOfMonth(LocalDate.now().year, LocalDate.now().month)
// WORK AROUND: Hardcoding the first day of the week by manually inserting them into a new map
val tempDates = hashMapOf<DaysOfWeek, MutableList<LocalDate>>()
tempDates[DaysOfWeek.SUNDAY] = dates[DayOfWeek.SUNDAY] !!
tempDates[DaysOfWeek.MONDAY] = dates[DayOfWeek.MONDAY] !!
tempDates[DaysOfWeek.TUESDAY] = dates[DayOfWeek.TUESDAY] !!
tempDates[DaysOfWeek.WEDNESDAY] = dates[DayOfWeek.WEDNESDAY] !!
tempDates[DaysOfWeek.THURSDAY] = dates[DayOfWeek.THURSDAY] !!
tempDates[DaysOfWeek.FRIDAY] = dates[DayOfWeek.FRIDAY] !!
tempDates[DaysOfWeek.SATURDAY] = dates[DayOfWeek.SATURDAY] !!
// Sort the days by ordinal, 0 - 6
val sortedDates = tempDates.toSortedMap(compareBy {
d -> d.ordinal
})
LazyVerticalGrid(
cells = GridCells.Fixed(7),
contentPadding = PaddingValues(16. dp)
) {
// Display short day of week name
items(sortedDates.keys.toList()) { dayOfWeek ->
Text(text = dayOfWeek.name.substring(0, 3), textAlign = TextAlign.Center)
}
itemsIndexed(sortedDates.values.toList()) { _, date ->
Column(
modifier = Modifier.padding(4. dp)
) {
date.forEach { day ->
DateView(date = day.dayOfMonth.toString())
}
}
}
}
}
/**
* Returns the dates for each day of the week in the given [year] and [month]
* Including dates of the previous and next month if the [month] does not
* begin on the first or last day of the week
*/
fun getDaysOfMonth(year: Int, month: Month): HashMap<DayOfWeek, MutableList<LocalDate>> {
val weekFields = WeekFields.of(Locale.getDefault())
val daysOfWeek = mutableSetOf<DayOfWeek>()
daysOfWeek.add(DayOfWeek.SUNDAY)
daysOfWeek.add(DayOfWeek.MONDAY)
daysOfWeek.add(DayOfWeek.TUESDAY)
daysOfWeek.add(DayOfWeek.WEDNESDAY)
daysOfWeek.add(DayOfWeek.THURSDAY)
daysOfWeek.add(DayOfWeek.FRIDAY)
daysOfWeek.add(DayOfWeek.SATURDAY)
val ym = YearMonth.of(year, month)
val firstOfMonth = ym.atDay(1) // first day of the month
val lastDayOfMonth = ym.atDay(ym.lengthOfMonth())
val dayDates = hashMapOf<DayOfWeek, MutableList<LocalDate>>()
// Get all the dates for each day of the week
daysOfWeek.forEach { day ->
val dates = mutableListOf<LocalDate>()
var ld = firstOfMonth.with(TemporalAdjusters.dayOfWeekInMonth(1, day))
do {
dates.add(ld)
ld = ld.plusWeeks(1)
} while (YearMonth.from(ld).equals(ym))
dayDates[day] = dates
}
// If current month does not start on a Sunday, get the last few days of the previous month
if (firstOfMonth.dayOfWeek != weekFields.firstDayOfWeek) {
val previousMonth = YearMonth.of(year, month.minus(1))
var lastDateOfPrevMonth = LocalDate.of(year, previousMonth.month, previousMonth.atEndOfMonth().dayOfMonth)
do {
dayDates[lastDateOfPrevMonth.dayOfWeek]?.add(0, lastDateOfPrevMonth)
lastDateOfPrevMonth = lastDateOfPrevMonth.minusDays(1)
} while (lastDateOfPrevMonth.dayOfWeek != DayOfWeek.SATURDAY)
}
// If current month does not end on a saturday, get the first few days of the next month
if (lastDayOfMonth.dayOfWeek != weekFields.firstDayOfWeek.minus(1)) {
val nextMonth = YearMonth.of(year, month.plus(1))
var firstDateOfNextMonth = LocalDate.of(year, nextMonth.month, 1)
do {
dayDates[firstDateOfNextMonth.dayOfWeek]?.add(firstDateOfNextMonth)
firstDateOfNextMonth = firstDateOfNextMonth.plusDays(1)
} while (firstDateOfNextMonth.dayOfWeek != DayOfWeek.SUNDAY)
}
return dayDates
}
上面的代码按预期工作,并显示一个从星期日开始的星期的日历。正如我所做的那样,使用从星期日开始的新枚举手动将星期几插入新的哈希图中是否有意义?还是让日期 api 处理它(如果可能)以及如何处理它更有意义?
还是我只是采取了错误的方法,而日历 API 会是更好的选择?
【问题讨论】:
-
永远不要使用旧的日期时间类。它们完全被 JSR 310 中定义的现代 java.time 类所取代。遗留类很糟糕,在设计上存在严重缺陷。
标签: java android kotlin android-jetpack-compose java-time