Java 用于表示具有设定时间粒度的日历计划的数据结构?

Java 用于表示具有设定时间粒度的日历计划的数据结构?,java,data-structures,maps,Java,Data Structures,Maps,我一直在尝试用纯Java的方式来表示整个日历年的日程安排。每个时间表为30分钟(半小时粒度) 这将通过存储库方法进行抽象,如findByDateTime() 基本上,我需要为每天30分钟的时间段建模 我把它拼凑起来的方式就是这样 public Map<Integer, Map<Integer, Programme>> enumerateMapOfMapSchedules() { int numberOfSlots = 48; //48 half hours in

我一直在尝试用纯Java的方式来表示整个日历年的日程安排。每个时间表为30分钟(半小时粒度)

这将通过存储库方法进行抽象,如
findByDateTime()

基本上,我需要为每天30分钟的时间段建模

我把它拼凑起来的方式就是这样

public Map<Integer, Map<Integer, Programme>> enumerateMapOfMapSchedules() {

    int numberOfSlots = 48; //48 half hours in a day

    Map<Integer, Map<Integer, Programme>> dayToTimeScheduleMap = new HashMap<>();

    //create a key value map for each day of the year
    for (int i = 1; i < 366; i++) {

        Map<Integer, Programme> dayProgrammeScheduleMap = new HashMap<>();

        for (int y = 1; y < numberOfSlots; y++) {
            dayProgrammeScheduleMap.put(y, null);
        }

        dayToTimeScheduleMap.put(i, dayProgrammeScheduleMap);
    }
    //creates a map with 365 days and each day having a map of 48 schedule slots
    return dayToTimeScheduleMap;
}
但是,要遍历所有数据结构以查看某个特定程序存在多少次

我的问题是,有没有更简单的方法

我试着用关系数据库来表示时间段,但是如果没有大量的SQL,很难轻松地表示时间段

欢迎任何建议或实施建议

日子长短不一 日历计划仅在时区和年份的情况下才有意义。政客们经常改变他们管辖的时区使用的偏移量。这意味着一天并不总是24小时长。异常情况,如平均一天可能长达23小时、25小时或其他时间,如23.5小时

从头开始,以30分钟为增量计数 因此,如果你想把整个一年分成30分钟的部分,你必须从特定时区的特定一年的第一天的第一刻开始,每次增加30分钟,直到新年到来

ZoneId z = ZoneId.of( "America/Montreal" );
Year year = Year.of( 2021 );
LocalDate firstOfYear = year.atDay( 1 );
ZonedDateTime start = firstOfYear.atStartOfDay( z );
List < ZonedDateTime > zdts = new ArrayList <>();

Duration duration = Duration.ofMinutes( 30 );
ZonedDateTime zdt = start;
while ( zdt.getYear() == year.getValue() )
{
    zdts.add( zdt );
    // Setup the next loop.
    zdt = zdt.plus( duration );
}
然后,您可以通过乘以持续时间,并将结果添加到年初,跳到一年中的某个点

int slotNumber = 22;
Duration jump = slotLength.multipliedBy( slotNumber - 1 );  // Subtract one to change an ordinal number into a zero-based index. 
ZonedDateTime slot22 = start.plus( jump );
预约簿跟踪 如果你在做预约,比如在美发沙龙或牙科诊所,通常的方法是用一天中的特定时间跟踪一年一个月的一天。但要单独追踪时区。因此,在Java模型中使用带有单独的
ZoneId
LocalDateTime
。在数据库表中,使用一对列,其中一列的类型类似于不带时区的SQL标准类型
TIMESTAMP
,另一列的文本类型包含时区名称,如
America/Montreal
Africa/Tunis

构建明细表时,应用分区以确定某个力矩。在Java中,这意味着对
LocalDateTime
应用
ZoneId
以获得
ZoneDateTime

您需要明确一个基本概念,
LocalDateTime
对象并不代表一个时刻。在我们这里的例子中,明年23日的下午3点可能意味着日本东京的下午3点或美国俄亥俄州托莱多的下午3点,两个截然不同的时刻相隔几个小时。
LocalDateTime
本身就是不明确的。因此也需要存储一个时区,但要分开保存

LocalDateTime ldt = LocalDateTime.of( 2021 , 1 , 23 , 15 , 0 , 0 , 0 ) ;
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;  // Determine a moment.
通过提取一个
瞬间
,查看UTC中的同一时刻

Instant instant = zdt.toInstant() ;
int slotNumber = 22;
Duration jump = slotLength.multipliedBy( slotNumber - 1 );  // Subtract one to change an ordinal number into a zero-based index. 
ZonedDateTime slot22 = start.plus( jump );
LocalDateTime ldt = LocalDateTime.of( 2021 , 1 , 23 , 15 , 0 , 0 , 0 ) ;
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;  // Determine a moment.
Instant instant = zdt.toInstant() ;