我需要实施一个能够记录工作天以及自然天数的劳动日历。日历必须能够处理国定假日,并且这些天必须由用户提交。 因此,如果我需要计算两天之间的差额,则计数必须忽略周六,周日和节假日。
Java类Calendar不能处理假期或工作日,因此我需要自己做。我认为有两种可能的方式:
我可以实现一个新的Day
类,该类具有一个布尔isHoliday
来检查这是否是一个工作日,然后使用我需要处理的所有方法创建一个新类/计算天数。
我对此方法的怀疑是如何存储它。这意味着要制作365个对象并将它们存储在List
或Linked List
中,这需要处理大量数据。
我的第二个想法是使其更简单。创建一个Strings
或Dates数组,用于存储假期。
示例new ArrayList<String> freeDays = ["01/01/2019", "05/01/2019", "06/01/2019"...]
,并使用新的CalendarUtils类或类似的类来进行处理。
对我来说,第一种选择看起来更好,但是,我不想浪费内存或使用不良做法。
哪个选项看起来更好?有第三种选择吗?
答案 0 :(得分:1)
从不使用Date
或Calendar
类。那些非常麻烦的旧类现在已成为旧版,由 java.time 类取代,特别是Instant
和ZonedDateTime
。您可能会发现LocalDate
也很有帮助。
请不要在Java代码中使用字符串来表示日期时间。使用对象,即 java.time 类。
以文本形式交换日期时间值时,请始终使用标准的ISO 8601格式。 java.time 类在解析/生成字符串时默认使用这些格式。对于将为YYYY-MM-DD的日期,例如2018-01-23
。
TemporalAdjuster
界面要跳过周末,请使用TemporalAdjuster
项目中的ThreeTen-Extra实现。
示例:
LocalDate // Represent a date-only value, without a time-of-day and without a time zone.
.now( // Capture the current date.
ZoneId.of( "Africa/Tunis" ) // Time zone required. For any given moment the date varies around the globe by zone.
)
.with( // Invoke a `TemporalAdjuster` implementation.
org.threeten.extra.Temporals.nextWorkingDay()
) // Returns a `LocalDate`. Using immutable objects pattern, producing a fresh object based on the values of another while leaving the original unaltered.
要跳过假期,您必须编写自己的代码。没有两个人,公司或国家/地区对假期有相同的定义。
您需要定义自己的假期列表。我建议将其写为TemporalAdjuster
的实现,以便与 java.time 类一起使用。也许nextBusinessDay
和previousBusinessDay
。上面提到的 ThreeTen-Extra 项目是开源的,因此请参考那里的代码来指导您。我隐约记得在堆栈溢出中自己张贴了TemporalAdjuster
的一个或多个实现。
您可以将那些假期日期存储在数据库中以保持持久性。并在运行时按时间顺序将它们表示为List< LocalDate >
,用Collections.sort
排序并用Collections.binarySearch
搜索。但请注意thread-safety。您可能需要在运行时更新该列表。阅读时写作必须受到保护。搜索更多信息。并阅读优秀的书籍Java Concurrency in Practice by Brian Goetz et al.
您可以将假期跳过代码与周末跳过代码结合使用。使用搜索引擎使用EnumSet
和DayOfWeek
枚举在周末跳过时找到我的答案。 (不幸的是,Stack Overflow中内置的搜索功能偏向于“问题”,而忽略了“答案”。)
搜索堆栈溢出。所有这些都已经被问过并回答过。