โครงสร้างข้อมูลสำหรับการแสดงตารางปฏิทินพร้อมรายละเอียดเวลาที่กำหนด?

ฉันพยายามคิดถึงวิธี 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;
}

ฉันขอขอบคุณที่โซลูชันนี้ไม่สามารถจัดการหรือมีแนวคิดเกี่ยวกับปีได้ แต่เนื่องจากสิ่งเหล่านี้มีไว้สำหรับการเยาะเย้ย/การทดสอบ ฉันจึงพอใจกับสิ่งนี้

นอกจากนี้ยังไม่จัดการกับตารางเวลาที่ทับซ้อนกัน หากโปรแกรมครอบคลุมช่วงสองชั่วโมงครึ่ง

วิธีการสืบค้นของฉันค่อนข้างง่ายในการค้นหาสิ่งที่อยู่ในช่องกำหนดการเฉพาะ

public Programme findByDateTime(LocalDateTime dateTime) {

    int scheduleSlot = dateTime.getHour() * 2;

    //if its the after 30 minute schedule slot
    if (dateTime.getMinute() > 30) {
        scheduleSlot++;
    }

    return scheduleMap.get(dateTime.getDayOfYear()).get(scheduleSlot);
}

อย่างไรก็ตาม สำหรับการวนซ้ำโครงสร้างข้อมูลทั้งหมดเพื่อดูว่ามีโปรแกรมใดเกิดขึ้นกี่ครั้ง

คำถามของฉัน มีวิธีที่ง่ายกว่านี้ไหม?

ฉันลองทำด้วยฐานข้อมูลเชิงสัมพันธ์ แต่มันยากที่จะแสดงช่วงเวลาได้อย่างง่ายดายโดยไม่ต้องใช้ SQL มากนัก

ยินดีรับข้อเสนอแนะหรือคำแนะนำในการดำเนินการ!


person tomaytotomato    schedule 15.06.2020    source แหล่งที่มา


คำตอบ (1)


วันมีความยาวแตกต่างกันไป

ตารางปฏิทินจะเหมาะสมในบริบทของเขตเวลาและปีเท่านั้น นักการเมืองมักเปลี่ยนค่าชดเชยที่ใช้ตามเขตเวลาในเขตอำนาจศาลของตน ซึ่งหมายความว่าวันต่างๆ ไม่ได้ยาวนานตลอด 24 ชั่วโมงเสมอไป ความผิดปกติเช่น เวลาออมแสง (DST) หมายความว่าหนึ่งวันอาจยาวนาน 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 );
}

ส่งกลับสำเนาที่ไม่สามารถแก้ไขได้ของรายการนั้น

List < ZonedDateTime > slots = List.copyOf( zdts );

เมื่อวิ่ง. แจ้งให้ทราบจะเกิดอะไรขึ้น เวลา 01.00 หรือ 02.00 น. ของวันที่ 14 มีนาคม 2021 และ 7 พ.ย. 2021.

slots = [2021-01-01T00:00-05:00[อเมริกา/มอนทรีออล], 2021-01-01T00:30-05:00[อเมริกา/มอนทรีออล], 2021-01-01T01:00-05:00[อเมริกา /มอนทรีออล], 2021-01-01T01:30-05:00[อเมริกา/มอนทรีออล], 2021-01-01T02:00-05:00[อเมริกา/มอนทรีออล],

2021-03-14T01:00-05:00[อเมริกา/มอนทรีออล], 2021-03-14T01:30-05:00[อเมริกา/มอนทรีออล], 2021-03-14T03:00-04:00[อเมริกา/มอนทรีออล] ,

2021-11-07T00:30-04:00[อเมริกา/มอนทรีออล], 2021-11-07T01:00-04:00[อเมริกา/มอนทรีออล] 2021-11-07T01:30-04:00[อเมริกา/มอนทรีออล] , 2021-11-07T01:00-05:00[อเมริกา/มอนทรีออล], 2021-11-07T01:30-05:00[อเมริกา/มอนทรีออล], 2021-11-07T02:00-05:00[อเมริกา/มอนทรีออล] ],

2021-12-31T22:00-05:00[อเมริกา/มอนทรีออล], 2021-12-31T22:30-05:00[อเมริกา/มอนทรีออล], 2021-12-31T23:00-05:00[อเมริกา/มอนทรีออล] , 2021-12-31T23:30-05:00[อเมริกา/มอนทรีออล]]

คาดการณ์อนาคตไม่น่าเชื่อถือ!

แต่ระวัง: นักการเมืองมักเปลี่ยนค่าชดเชยที่ใช้ในโซน! สิ่งนี้เกิดขึ้นบ่อยกว่าที่คุณจะรู้ นักการเมืองยิ่งแย่ลงไปอีกในการลดคำเตือนล่วงหน้าจากหลายปีเหลือไม่กี่เดือน หรือแม้แต่หลายสัปดาห์อย่างที่เห็นเมื่อเร็วๆ นี้ในตุรกีและโมร็อกโก และไม่มีการเตือนล่วงหน้าเลยเหมือนที่พบในเกาหลีเหนือ

ดังนั้น คุณไม่สามารถคาดการณ์อนาคตได้อย่างน่าเชื่อถือ โดยใช้แนวทางที่เห็นด้านบน

คณิตศาสตร์สล็อต

ฉันคิดว่าคุณสามารถแก้ไขปัญหาสล็อตแห่งปีได้ในอีกทางหนึ่ง คำนวณจำนวนช่องทั้งหมดในระหว่างปีด้วยวิธีนี้

ZoneId z = ZoneId.of( "America/Montreal" );
Year year = Year.of( 2021 );
LocalDate firstOfYear = year.atDay( 1 );
ZonedDateTime start = firstOfYear.atStartOfDay( z );
ZonedDateTime end = start.plusYears( 1 );

Duration slotLength = Duration.ofMinutes( 30 );
long wholeSlotsInYear = Duration.between( start , end ).dividedBy( slotLength );

จากนั้น คุณสามารถข้ามไปยังจุดใดจุดหนึ่งของปีได้โดยการคูณระยะเวลา และเพิ่มผลลัพธ์ที่จุดเริ่มต้นของปี

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 กับ ZoneId แยกต่างหากในโมเดล Java ของคุณ ในตารางฐานข้อมูลของคุณ ให้ใช้คอลัมน์คู่หนึ่ง ซึ่งเป็นประเภทที่คล้ายกับประเภทมาตรฐาน SQL TIMESTAMP WITHOUT TIME ZONE และอีกคอลัมน์หนึ่งของประเภทข้อความที่เก็บชื่อของเขตเวลา เช่น America/Montreal หรือ Africa/Tunis

เมื่อสร้างตารางเวลา ให้ใช้โซนเพื่อกำหนดช่วงเวลา ใน Java นั่นหมายถึงการใช้ ZoneId กับ LocalDateTime เพื่อรับ ZonedDateTime

คุณต้องมีความชัดเจนในแนวคิดพื้นฐานที่ว่าวัตถุ LocalDateTime ไม่ได้ เป็นตัวแทนของช่วงเวลาหนึ่ง ในตัวอย่างของเราที่นี่ เวลา 15.00 น. ของวันที่ 23 ปีหน้าอาจหมายถึง 15.00 น. ในโตเกียว ญี่ปุ่น หรือ 15.00 น. ในโทเลโด รัฐโอไฮโอ สหรัฐอเมริกา ซึ่งเป็นช่วงเวลาที่แตกต่างกันมากซึ่งห่างกันหลายชั่วโมง A 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 instant = zdt.toInstant() ;
person Basil Bourque    schedule 16.06.2020