@@ -465,6 +465,20 @@ Module.register("calendar", {
465465 return moment ( timestamp , "x" ) . tz ( moment . tz . guess ( ) ) ;
466466 } ,
467467
468+ /**
469+ * Sets the relative day flags (today, yesterday, ...) on an event based on its day.
470+ * @param {object } event The event to flag.
471+ * @param {moment.Moment } dayMoment The day the event belongs to.
472+ * @param {moment.Moment } now The current moment.
473+ */
474+ setRelativeDayFlags ( event , dayMoment , now ) {
475+ event . today = dayMoment . isSame ( now , "d" ) ;
476+ event . dayBeforeYesterday = dayMoment . isSame ( now . clone ( ) . subtract ( 2 , "days" ) , "d" ) ;
477+ event . yesterday = dayMoment . isSame ( now . clone ( ) . subtract ( 1 , "days" ) , "d" ) ;
478+ event . tomorrow = dayMoment . isSame ( now . clone ( ) . add ( 1 , "days" ) , "d" ) ;
479+ event . dayAfterTomorrow = dayMoment . isSame ( now . clone ( ) . add ( 2 , "days" ) , "d" ) ;
480+ } ,
481+
468482 /**
469483 * Creates the sorted list of all events.
470484 * @param {boolean } limitNumberOfEntries Whether to filter returned events for display.
@@ -503,43 +517,36 @@ Module.register("calendar", {
503517 }
504518
505519 event . url = calendarUrl ;
506- event . today = eventStartDateMoment . isSame ( now , "d" ) ;
507- event . dayBeforeYesterday = eventStartDateMoment . isSame ( now . clone ( ) . subtract ( 2 , "days" ) , "d" ) ;
508- event . yesterday = eventStartDateMoment . isSame ( now . clone ( ) . subtract ( 1 , "days" ) , "d" ) ;
509- event . tomorrow = eventStartDateMoment . isSame ( now . clone ( ) . add ( 1 , "days" ) , "d" ) ;
510- event . dayAfterTomorrow = eventStartDateMoment . isSame ( now . clone ( ) . add ( 2 , "days" ) , "d" ) ;
520+ this . setRelativeDayFlags ( event , eventStartDateMoment , now ) ;
511521
512522 /*
513- * if sliceMultiDayEvents is set to true, multiday events (events exceeding at least one midnight) are sliced into days,
514- * otherwise, esp. in dateheaders mode it is not clear how long these events are.
523+ * If sliceMultiDayEvents is enabled, an event spanning several calendar days is split into one entry per day.
524+ * Otherwise, esp. in dateheaders mode, it is not clear how long these events are.
525+ * dayCount is the number of calendar days the event touches (an end exactly at midnight does not add a day).
515526 */
516- const maxCount = eventEndDateMoment . diff ( eventStartDateMoment , "days" ) ;
517- if ( this . config . sliceMultiDayEvents && maxCount > 1 ) {
527+ const eventStartDay = eventStartDateMoment . clone ( ) . startOf ( "day" ) ;
528+ const eventEndDay = eventEndDateMoment . clone ( ) . startOf ( "day" ) ;
529+ const endsAtMidnight = ! eventEndDateMoment . isAfter ( eventEndDay ) ;
530+ const dayCount = eventEndDay . diff ( eventStartDay , "days" ) + ( endsAtMidnight ? 0 : 1 ) ;
531+ if ( this . config . sliceMultiDayEvents && dayCount > 1 ) {
518532 const splitEvents = [ ] ;
519- let midnight
520- = eventStartDateMoment
521- . clone ( )
522- . startOf ( "day" )
523- . add ( 1 , "day" )
524- . endOf ( "day" ) ;
525- let count = 1 ;
526- while ( eventEndDateMoment . isAfter ( midnight ) ) {
527- const thisEvent = JSON . parse ( JSON . stringify ( event ) ) ; // clone object
528- thisEvent . today = this . timestampToMoment ( thisEvent . startDate ) . isSame ( now , "d" ) ;
529- thisEvent . tomorrow = this . timestampToMoment ( thisEvent . startDate ) . isSame ( now . clone ( ) . add ( 1 , "days" ) , "d" ) ;
530- thisEvent . endDate = midnight . clone ( ) . subtract ( 1 , "day" ) . format ( "x" ) ;
531- thisEvent . title += ` (${ count } /${ maxCount } )` ;
532- splitEvents . push ( thisEvent ) ;
533-
534- event . startDate = midnight . clone ( ) . startOf ( "day" ) . format ( "x" ) ; // start next slice at 00:00, not 23:59
535- count += 1 ;
536- midnight = midnight . clone ( ) . add ( 1 , "day" ) . endOf ( "day" ) ; // next day
533+ // Each slice covers one day: it starts at the event start (first slice) or midnight,
534+ // and ends at the event end (last slice) or one millisecond before the next midnight.
535+ let sliceStart = eventStartDateMoment . clone ( ) ;
536+
537+ for ( let dayNumber = 1 ; dayNumber <= dayCount ; dayNumber ++ ) {
538+ const isLastSlice = dayNumber === dayCount ;
539+ const nextMidnight = sliceStart . clone ( ) . startOf ( "day" ) . add ( 1 , "day" ) ;
540+
541+ const slice = JSON . parse ( JSON . stringify ( event ) ) ; // clone object
542+ slice . startDate = sliceStart . format ( "x" ) ;
543+ slice . endDate = isLastSlice ? event . endDate : nextMidnight . clone ( ) . subtract ( 1 , "millisecond" ) . format ( "x" ) ;
544+ slice . title = `${ event . title } (${ dayNumber } /${ dayCount } )` ;
545+ this . setRelativeDayFlags ( slice , sliceStart , now ) ;
546+ splitEvents . push ( slice ) ;
547+
548+ sliceStart = nextMidnight ;
537549 }
538- // Last day
539- event . title += ` (${ count } /${ maxCount } )` ;
540- event . today += this . timestampToMoment ( event . startDate ) . isSame ( now , "d" ) ;
541- event . tomorrow = this . timestampToMoment ( event . startDate ) . isSame ( now . clone ( ) . add ( 1 , "days" ) , "d" ) ;
542- splitEvents . push ( event ) ;
543550
544551 for ( const splitEvent of splitEvents ) {
545552 if ( this . timestampToMoment ( splitEvent . endDate ) . isAfter ( now ) && this . timestampToMoment ( splitEvent . endDate ) . isSameOrBefore ( future ) ) {
0 commit comments