如何创建通用日期(即不附加于任何实际的yyMMdd
,但类似于:
val START = LocalTime.of(startHour, startMinute)
val END = LocalTime.of(endHour, endMinute)
但是,我还想包括dayOfWeek
。
我的意图是计算时间间隔的重叠,即对于两个给定的(开始和结束)时间戳,我想计算与指定的工作日和时间(如开放时间)的重叠。
编辑
我不确定定制类是否足够好。我的意图是,如果我有这样的事件清单:
id,start,end
1,2018-01-01 08:00, 2018-01-01 08:00 || opening hours 8-10, duration: 1
2,2018-01-01 10:00, 2018-01-01 12:00 || opening hours 8-10, duration: 0
3,2018-01-02 10:00, 2018-01-02 12:00 || opening hours 10-15, duration 2
若要验证start-end
的时间间隔是否与另一个时间间隔(即开放时间)相交,则其他时间间隔取决于周中的日期。
在构造对象之后(目前我的对象可能因为无法以通用方式组合dayOfWeek和Time )
我会使用isBefore/isAfter
几次,然后计算重叠的持续时间。
发布于 2018-09-27 16:07:15
只需使用内置于Java中的DayOfWeek
枚举即可。它提供了七个预定义的对象,一周中每天都有一个,比如DayOfWeek.MONDAY
。
我并不完全关注您的业务问题,但听起来您需要定义您自己的类。
public class Shift {
DayOfWeek dayOfWeek ;
LocalTime startTime , stopTime ;
}
添加一种将其转化为真实时刻的方法。
public ZonedDateTime startAtDate( LocalDate ld , ZoneId z ) {
LocalDate LocalDate = ld.with( TemporalAdjustors.previousOrSame( this.dayOfWeek ) ) ;
ZonedDateTime zdt = ZonedDateTime.of( localDate , this.startTime , z ) ;
return zdt ;
}
您可能会想要向项目中添加第三个额外的库。它提供了一些类,如Interval
和LocalDateTime
,您可能会发现它们很有用。这些类提供了一系列比较方法,如连接、重叠等。
看起来这个库缺少一个LocalTimeRange
,所以可能需要自己的。也许还会把这样的课程捐给那个项目。
关于java.time
http://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html框架内置到Java8和更高版本中。这些类取代了麻烦的旧遗赠日期时间类,如java.util.Date
、Calendar
和SimpleDateFormat
。
http://www.joda.org/joda-time/项目现在在维护模式中,建议迁移到java.time类。
要了解更多信息,请参见http://docs.oracle.com/javase/tutorial/datetime/TOC.html。并搜索堆栈溢出以获得许多示例和解释。规范是JSR 310。
您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC 4.2。不需要字符串,也不需要java.sql.*
类。
在哪里获得java.time类?
发布于 2018-09-27 16:33:24
一种简单的方法是为这些“标准”间隔使用枚举映射。
假设下面是计算重叠的方法:
static int calculateOverlap(LocalTime expectedStartTime, LocalTime expectedEndTime,
LocalTime actualStartTime, LocalTime actualEndTime) {
//calculate overlap...
}
您可以这样查找值(为了简单起见,可以使用带有两个Pair
字段的自定义类):
Map<DayOfWeek, Pair<LocalTime, LocalTime>> openingHours =
new EnumMap<>(DayOfWeek.class);
openingHours.put(DayOfWeek.MONDAY,
Pair.of(LocalTime.of(8, 0), LocalTime.of(16, 0)));
openingHours.put(DayOfWeek.TUESDAY,
Pair.of(LocalTime.of(9, 0), LocalTime.of(17, 0)));
//...entries for other weekdays
然后使用以下方法查找:
MyEvent mondayEvent = ...
Pair<LocalTime, LocalTime> mondayHours = officialHours.get(DayOfWeek.MONDAY);
int overlap = calculateOverlap(mondayHours.getLeft(), mondayHours.getRight(),
mondayEvent.getStart(), mondayEvent.getEnd());
发布于 2018-11-01 02:55:47
我的lib Time4J (v5.0)为您的整个业务问题提供了以下开箱即用的解决方案:
DayPartitionRule rule =
new DayPartitionBuilder()
.addWeekdayRule(
Weekday.MONDAY,
ClockInterval.between(PlainTime.of(8, 0), PlainTime.of(10, 0)))
.addWeekdayRule(
Weekday.TUESDAY,
ClockInterval.between(PlainTime.of(10, 0), PlainTime.of(15, 0)))
.build();
Map<Integer, TimestampInterval> events = new HashMap<>();
events.put(
1,
TimestampInterval.between(
PlainTimestamp.of(2018, 1, 1, 8, 0),
PlainTimestamp.of(2018, 1, 1, 9, 0)));
events.put(
2,
TimestampInterval.between(
PlainTimestamp.of(2018, 1, 1, 10, 0),
PlainTimestamp.of(2018, 1, 1, 12, 0)));
events.put(
3,
TimestampInterval.between(
PlainTimestamp.of(2018, 1, 2, 10, 0),
PlainTimestamp.of(2018, 1, 2, 12, 0)));
events.forEach(
(id, interval) -> System.out.println(
"Event: " + id + " => "
+ Duration.formatter(ClockUnit.class, "#h:mm").format(
interval
.streamPartitioned(rule)
.map(i -> i.getDuration(ClockUnit.HOURS, ClockUnit.MINUTES))
.collect(Duration.summingUp())
.with(Duration.STD_CLOCK_PERIOD)
)));
输出:
事件:1 => 1:00 事件:2 => 0:00 活动:3 => 2:00
该算法使用量程包 of Time4J,如果每周有一个以上的时钟间隔,或者输入间隔超过一天(这需要对持续时间的总结),则仍能正常工作。
顺便说一句,我假设您的第一个间隔线“2018-01- 08:00,2018-01- 08:00”包含一个错误,所以我已经将结束时间调整为上午9点(结果是预期的持续时间为1小时)。
https://stackoverflow.com/questions/52540796
复制相似问题