@@ -77,7 +77,7 @@ Module.register("calendar", {
7777
7878 // Define required scripts.
7979 getScripts ( ) {
80- return [ "calendarutils.js" , "moment.js" ] ;
80+ return [ "calendarutils.js" , "moment.js" , "moment-timezone.js" ] ;
8181 } ,
8282
8383 // Define required translations.
@@ -215,18 +215,9 @@ Module.register("calendar", {
215215 this . updateDom ( this . config . animationSpeed ) ;
216216 } ,
217217
218- eventEndingWithinNextFullTimeUnit ( event , ONE_DAY ) {
219- const now = new Date ( ) ;
220- return event . endDate - now <= ONE_DAY ;
221- } ,
222-
223218 // Override dom generator.
224219 getDom ( ) {
225220 const ONE_SECOND = 1000 ; // 1,000 milliseconds
226- const ONE_MINUTE = ONE_SECOND * 60 ;
227- const ONE_HOUR = ONE_MINUTE * 60 ;
228- const ONE_DAY = ONE_HOUR * 24 ;
229-
230221 const events = this . createEventList ( true ) ;
231222 const wrapper = document . createElement ( "table" ) ;
232223 wrapper . className = this . config . tableClass ;
@@ -258,7 +249,9 @@ Module.register("calendar", {
258249 let lastSeenDate = "" ;
259250
260251 events . forEach ( ( event , index ) => {
261- const dateAsString = moment ( event . startDate , "x" ) . format ( this . config . dateFormat ) ;
252+ const eventStartDateMoment = this . timestampToMoment ( event . startDate ) ;
253+ const eventEndDateMoment = this . timestampToMoment ( event . endDate ) ;
254+ const dateAsString = eventStartDateMoment . format ( this . config . dateFormat ) ;
262255 if ( this . config . timeFormat === "dateheaders" ) {
263256 if ( lastSeenDate !== dateAsString ) {
264257 const dateRow = document . createElement ( "tr" ) ;
@@ -340,7 +333,7 @@ Module.register("calendar", {
340333 repeatingCountTitle = this . countTitleForUrl ( event . url ) ;
341334
342335 if ( repeatingCountTitle !== "" ) {
343- const thisYear = new Date ( parseInt ( event . startDate ) ) . getFullYear ( ) ,
336+ const thisYear = eventStartDateMoment . year ( ) ,
344337 yearDiff = thisYear - event . firstYear ;
345338
346339 repeatingCountTitle = `, ${ yearDiff } ${ repeatingCountTitle } ` ;
@@ -395,14 +388,14 @@ Module.register("calendar", {
395388 timeWrapper . className = `time light ${ this . config . flipDateHeaderTitle ? "align-right " : "align-left " } ${ this . timeClassForUrl ( event . url ) } ` ;
396389 timeWrapper . style . paddingLeft = "2px" ;
397390 timeWrapper . style . textAlign = this . config . flipDateHeaderTitle ? "right" : "left" ;
398- timeWrapper . innerHTML = moment ( event . startDate , "x" ) . format ( "LT" ) ;
391+ timeWrapper . innerHTML = eventStartDateMoment . format ( "LT" ) ;
399392
400393 // Add endDate to dataheaders if showEnd is enabled
401394 if ( this . config . showEnd ) {
402395 if ( this . config . showEndsOnlyWithDuration && event . startDate === event . endDate ) {
403396 // no duration here, don't display end
404397 } else {
405- timeWrapper . innerHTML += ` - ${ CalendarUtils . capFirst ( moment ( event . endDate , "x" ) . format ( "LT" ) ) } ` ;
398+ timeWrapper . innerHTML += ` - ${ CalendarUtils . capFirst ( eventEndDateMoment . format ( "LT" ) ) } ` ;
406399 }
407400 }
408401
@@ -415,70 +408,69 @@ Module.register("calendar", {
415408 const timeWrapper = document . createElement ( "td" ) ;
416409
417410 eventWrapper . appendChild ( titleWrapper ) ;
418- const now = new Date ( ) ;
411+ const now = moment ( ) ;
419412
420413 if ( this . config . timeFormat === "absolute" ) {
421414 // Use dateFormat
422- timeWrapper . innerHTML = CalendarUtils . capFirst ( moment ( event . startDate , "x" ) . format ( this . config . dateFormat ) ) ;
415+ timeWrapper . innerHTML = CalendarUtils . capFirst ( eventStartDateMoment . format ( this . config . dateFormat ) ) ;
423416 // Add end time if showEnd
424417 if ( this . config . showEnd ) {
425418 // and has a duation
426419 if ( event . startDate !== event . endDate ) {
427420 timeWrapper . innerHTML += "-" ;
428- timeWrapper . innerHTML += CalendarUtils . capFirst ( moment ( event . endDate , "x" ) . format ( this . config . dateEndFormat ) ) ;
421+ timeWrapper . innerHTML += CalendarUtils . capFirst ( eventEndDateMoment . format ( this . config . dateEndFormat ) ) ;
429422 }
430423 }
431424
432425 // For full day events we use the fullDayEventDateFormat
433426 if ( event . fullDayEvent ) {
434427 //subtract one second so that fullDayEvents end at 23:59:59, and not at 0:00:00 one the next day
435- event . endDate -= ONE_SECOND ;
436- timeWrapper . innerHTML = CalendarUtils . capFirst ( moment ( event . startDate , "x" ) . format ( this . config . fullDayEventDateFormat ) ) ;
428+ eventEndDateMoment . subtract ( 1 , "second" ) ;
429+ timeWrapper . innerHTML = CalendarUtils . capFirst ( eventStartDateMoment . format ( this . config . fullDayEventDateFormat ) ) ;
437430 // only show end if requested and allowed and the dates are different
438- if ( this . config . showEnd && ! this . config . showEndsOnlyWithDuration && moment ( event . startDate , "x" ) . format ( "YYYYMMDD" ) !== moment ( event . endDate , "x" ) . format ( "YYYYMMDD ") ) {
431+ if ( this . config . showEnd && ! this . config . showEndsOnlyWithDuration && ! eventStartDateMoment . isSame ( eventEndDateMoment , "d " ) ) {
439432 timeWrapper . innerHTML += "-" ;
440- timeWrapper . innerHTML += CalendarUtils . capFirst ( moment ( event . endDate , "x" ) . format ( this . config . fullDayEventDateFormat ) ) ;
441- } else
442- if ( ( moment ( event . startDate , "x" ) . format ( "YYYYMMDD" ) !== moment ( event . endDate , "x" ) . format ( "YYYYMMDD" ) ) && ( moment ( event . startDate , "x" ) < moment ( now , "x" ) ) ) {
443- timeWrapper . innerHTML = CalendarUtils . capFirst ( moment ( now , "x" ) . format ( this . config . fullDayEventDateFormat ) ) ;
444- }
445- } else if ( this . config . getRelative > 0 && event . startDate < now ) {
433+ timeWrapper . innerHTML += CalendarUtils . capFirst ( eventEndDateMoment . format ( this . config . fullDayEventDateFormat ) ) ;
434+ } else if ( ! eventStartDateMoment . isSame ( eventEndDateMoment , "d" ) && eventStartDateMoment . isBefore ( now ) ) {
435+ timeWrapper . innerHTML = CalendarUtils . capFirst ( now . format ( this . config . fullDayEventDateFormat ) ) ;
436+ }
437+ } else if ( this . config . getRelative > 0 && eventStartDateMoment . isBefore ( now ) ) {
446438 // Ongoing and getRelative is set
447439 timeWrapper . innerHTML = CalendarUtils . capFirst (
448440 this . translate ( "RUNNING" , {
449441 fallback : `${ this . translate ( "RUNNING" ) } {timeUntilEnd}` ,
450- timeUntilEnd : moment ( event . endDate , "x" ) . fromNow ( true )
442+ timeUntilEnd : eventEndDateMoment . fromNow ( true )
451443 } )
452444 ) ;
453- } else if ( this . config . urgency > 0 && event . startDate - now < this . config . urgency * ONE_DAY ) {
445+ } else if ( this . config . urgency > 0 && eventStartDateMoment . diff ( now , "d" ) < this . config . urgency ) {
454446 // Within urgency days
455- timeWrapper . innerHTML = CalendarUtils . capFirst ( moment ( event . startDate , "x" ) . fromNow ( ) ) ;
447+ timeWrapper . innerHTML = CalendarUtils . capFirst ( eventStartDateMoment . fromNow ( ) ) ;
456448 }
457449 if ( event . fullDayEvent && this . config . nextDaysRelative ) {
458450 // Full days events within the next two days
459451 if ( event . today ) {
460452 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "TODAY" ) ) ;
461453 } else if ( event . yesterday ) {
462454 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "YESTERDAY" ) ) ;
463- } else if ( event . startDate - now < ONE_DAY && event . startDate - now > 0 ) {
455+ } else if ( event . tomorrow ) {
464456 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "TOMORROW" ) ) ;
465- } else if ( event . startDate - now < 2 * ONE_DAY && event . startDate - now > 0 ) {
457+ } else if ( event . dayAfterTomorrow ) {
466458 if ( this . translate ( "DAYAFTERTOMORROW" ) !== "DAYAFTERTOMORROW" ) {
467459 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "DAYAFTERTOMORROW" ) ) ;
468460 }
469461 }
470462 }
471463 } else {
472464 // Show relative times
473- if ( event . startDate >= now || ( event . fullDayEvent && this . eventEndingWithinNextFullTimeUnit ( event , ONE_DAY ) ) ) {
465+ if ( eventStartDateMoment . isSameOrAfter ( now ) || ( event . fullDayEvent && eventEndDateMoment . diff ( now , "days" ) === 0 ) ) {
474466 // Use relative time
475467 if ( ! this . config . hideTime && ! event . fullDayEvent ) {
476468 Log . debug ( "event not hidden and not fullday" ) ;
477- timeWrapper . innerHTML = `${ CalendarUtils . capFirst ( moment ( event . startDate , "x" ) . calendar ( null , { sameElse : this . config . dateFormat } ) ) } ` ;
469+ timeWrapper . innerHTML = `${ CalendarUtils . capFirst ( eventStartDateMoment . calendar ( null , { sameElse : this . config . dateFormat } ) ) } ` ;
478470 } else {
479471 Log . debug ( "event full day or hidden" ) ;
480472 timeWrapper . innerHTML = `${ CalendarUtils . capFirst (
481- moment ( event . startDate , "x" ) . calendar ( null , {
473+ eventStartDateMoment . calendar ( null , {
482474 sameDay : this . config . showTimeToday ? "LT" : `[${ this . translate ( "TODAY" ) } ]` ,
483475 nextDay : `[${ this . translate ( "TOMORROW" ) } ]` ,
484476 nextWeek : "dddd" ,
@@ -488,33 +480,33 @@ Module.register("calendar", {
488480 }
489481 if ( event . fullDayEvent ) {
490482 // Full days events within the next two days
491- if ( event . today || ( event . fullDayEvent && this . eventEndingWithinNextFullTimeUnit ( event , ONE_DAY ) ) ) {
483+ if ( event . today || ( event . fullDayEvent && eventEndDateMoment . diff ( now , "days" ) === 0 ) ) {
492484 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "TODAY" ) ) ;
493485 } else if ( event . dayBeforeYesterday ) {
494486 if ( this . translate ( "DAYBEFOREYESTERDAY" ) !== "DAYBEFOREYESTERDAY" ) {
495487 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "DAYBEFOREYESTERDAY" ) ) ;
496488 }
497489 } else if ( event . yesterday ) {
498490 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "YESTERDAY" ) ) ;
499- } else if ( event . startDate - now < ONE_DAY && event . startDate - now > 0 ) {
491+ } else if ( event . tomorrow ) {
500492 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "TOMORROW" ) ) ;
501- } else if ( event . startDate - now < 2 * ONE_DAY && event . startDate - now > 0 ) {
493+ } else if ( event . dayAfterTomorrow ) {
502494 if ( this . translate ( "DAYAFTERTOMORROW" ) !== "DAYAFTERTOMORROW" ) {
503495 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "DAYAFTERTOMORROW" ) ) ;
504496 }
505497 }
506498 Log . info ( "event fullday" ) ;
507- } else if ( event . startDate - now < this . config . getRelative * ONE_HOUR ) {
499+ } else if ( eventStartDateMoment . diff ( now , "h" ) < this . config . getRelative ) {
508500 Log . info ( "not full day but within getrelative size" ) ;
509501 // If event is within getRelative hours, display 'in xxx' time format or moment.fromNow()
510- timeWrapper . innerHTML = `${ CalendarUtils . capFirst ( moment ( event . startDate , "x" ) . fromNow ( ) ) } ` ;
502+ timeWrapper . innerHTML = `${ CalendarUtils . capFirst ( eventStartDateMoment . fromNow ( ) ) } ` ;
511503 }
512504 } else {
513505 // Ongoing event
514506 timeWrapper . innerHTML = CalendarUtils . capFirst (
515507 this . translate ( "RUNNING" , {
516508 fallback : `${ this . translate ( "RUNNING" ) } {timeUntilEnd}` ,
517- timeUntilEnd : moment ( event . endDate , "x" ) . fromNow ( true )
509+ timeUntilEnd : eventEndDateMoment . fromNow ( true )
518510 } )
519511 ) ;
520512 }
@@ -593,46 +585,46 @@ Module.register("calendar", {
593585 return false ;
594586 } ,
595587
588+ /**
589+ * converts the given timestamp to a moment with a timezone
590+ * @param {number } timestamp timestamp from an event
591+ * @returns {moment.Moment } moment with a timezone
592+ */
593+ timestampToMoment ( timestamp ) {
594+ return moment ( timestamp , "x" ) . tz ( moment . tz . guess ( ) ) ;
595+ } ,
596+
596597 /**
597598 * Creates the sorted list of all events.
598599 * @param {boolean } limitNumberOfEntries Whether to filter returned events for display.
599600 * @returns {object[] } Array with events.
600601 */
601602 createEventList ( limitNumberOfEntries ) {
602- const ONE_SECOND = 1000 ; // 1,000 milliseconds
603- const ONE_MINUTE = ONE_SECOND * 60 ;
604- const ONE_HOUR = ONE_MINUTE * 60 ;
605- const ONE_DAY = ONE_HOUR * 24 ;
606-
607- let now , today , future ;
608- if ( this . config . forceUseCurrentTime || this . defaults . forceUseCurrentTime ) {
609- now = new Date ( ) ;
610- today = moment ( ) . startOf ( "day" ) ;
611- future = moment ( ) . startOf ( "day" ) . add ( this . config . maximumNumberOfDays , "days" ) . toDate ( ) ;
612- } else {
613- now = new Date ( Date . now ( ) ) ; // Can use overridden time
614- today = moment ( now ) . startOf ( "day" ) ;
615- future = moment ( now ) . startOf ( "day" ) . add ( this . config . maximumNumberOfDays , "days" ) . toDate ( ) ;
616- }
603+ let now = moment ( ) ;
604+ let today = now . clone ( ) . startOf ( "day" ) ;
605+ let future = now . clone ( ) . startOf ( "day" ) . add ( this . config . maximumNumberOfDays , "days" ) ;
606+
617607 let events = [ ] ;
618608
619609 for ( const calendarUrl in this . calendarData ) {
620610 const calendar = this . calendarData [ calendarUrl ] ;
621611 let remainingEntries = this . maximumEntriesForUrl ( calendarUrl ) ;
622- let maxPastDaysCompare = now - this . maximumPastDaysForUrl ( calendarUrl ) * ONE_DAY ;
612+ let maxPastDaysCompare = now . clone ( ) . subtract ( this . maximumPastDaysForUrl ( calendarUrl ) , "days" ) ;
623613 let by_url_calevents = [ ] ;
624614 for ( const e in calendar ) {
625615 const event = JSON . parse ( JSON . stringify ( calendar [ e ] ) ) ; // clone object
616+ const eventStartDateMoment = this . timestampToMoment ( event . startDate ) ;
617+ const eventEndDateMoment = this . timestampToMoment ( event . endDate ) ;
626618
627619 if ( this . config . hidePrivate && event . class === "PRIVATE" ) {
628620 // do not add the current event, skip it
629621 continue ;
630622 }
631623 if ( limitNumberOfEntries ) {
632- if ( event . endDate < maxPastDaysCompare ) {
624+ if ( eventEndDateMoment . isBefore ( maxPastDaysCompare ) ) {
633625 continue ;
634626 }
635- if ( this . config . hideOngoing && event . startDate < now ) {
627+ if ( this . config . hideOngoing && eventStartDateMoment . isBefore ( now ) ) {
636628 continue ;
637629 }
638630 if ( this . config . hideDuplicates && this . listContainsEvent ( events , event ) ) {
@@ -641,47 +633,46 @@ Module.register("calendar", {
641633 }
642634
643635 event . url = calendarUrl ;
644- event . today = event . startDate >= today && event . startDate < today + ONE_DAY ;
645- event . dayBeforeYesterday = event . startDate >= today - ONE_DAY * 2 && event . startDate < today - ONE_DAY ;
646- event . yesterday = event . startDate >= today - ONE_DAY && event . startDate < today ;
647- event . tomorrow = ! event . today && event . startDate >= today + ONE_DAY && event . startDate < today + 2 * ONE_DAY ;
648- event . dayAfterTomorrow = ! event . tomorrow && event . startDate >= today + ONE_DAY * 2 && event . startDate < today + 3 * ONE_DAY ;
636+ event . today = eventStartDateMoment . isSame ( now , "d" ) ;
637+ event . dayBeforeYesterday = eventStartDateMoment . isSame ( now . clone ( ) . subtract ( 2 , "days" ) , "d" ) ;
638+ event . yesterday = eventStartDateMoment . isSame ( now . clone ( ) . subtract ( 1 , "days" ) , "d" ) ;
639+ event . tomorrow = eventStartDateMoment . isSame ( now . clone ( ) . add ( 1 , "days" ) , "d" ) ;
640+ event . dayAfterTomorrow = eventStartDateMoment . isSame ( now . clone ( ) . add ( 2 , "days" ) , "d" ) ;
649641
650642 /*
651643 * if sliceMultiDayEvents is set to true, multiday events (events exceeding at least one midnight) are sliced into days,
652644 * otherwise, esp. in dateheaders mode it is not clear how long these events are.
653645 */
654- const maxCount = Math . round ( ( event . endDate - 1 - moment ( event . startDate , "x" ) . endOf ( "day" ) . format ( "x" ) ) / ONE_DAY ) + 1 ;
646+ const maxCount = eventEndDateMoment . diff ( eventStartDateMoment , "days" ) ;
655647 if ( this . config . sliceMultiDayEvents && maxCount > 1 ) {
656648 const splitEvents = [ ] ;
657649 let midnight
658- = moment ( event . startDate , "x" )
650+ = eventStartDateMoment
659651 . clone ( )
660652 . startOf ( "day" )
661653 . add ( 1 , "day" )
662- . endOf ( "day" )
663- . format ( "x" ) ;
654+ . endOf ( "day" ) ;
664655 let count = 1 ;
665- while ( event . endDate > midnight ) {
656+ while ( eventEndDateMoment . isAfter ( midnight ) ) {
666657 const thisEvent = JSON . parse ( JSON . stringify ( event ) ) ; // clone object
667- thisEvent . today = thisEvent . startDate >= today && thisEvent . startDate < today + ONE_DAY ;
668- thisEvent . tomorrow = ! thisEvent . today && thisEvent . startDate >= today + ONE_DAY && thisEvent . startDate < today + 2 * ONE_DAY ;
669- thisEvent . endDate = moment ( midnight , "x" ) . clone ( ) . subtract ( 1 , "day" ) . format ( "x" ) ;
658+ thisEvent . today = this . timestampToMoment ( thisEvent . startDate ) . isSame ( now , "d" ) ;
659+ thisEvent . tomorrow = this . timestampToMoment ( thisEvent . startDate ) . isSame ( now . clone ( ) . add ( 1 , "days" ) , "d" ) ;
660+ thisEvent . endDate = midnight . clone ( ) . subtract ( 1 , "day" ) . format ( "x" ) ;
670661 thisEvent . title += ` (${ count } /${ maxCount } )` ;
671662 splitEvents . push ( thisEvent ) ;
672663
673- event . startDate = midnight ;
664+ event . startDate = midnight . format ( "x" ) ;
674665 count += 1 ;
675- midnight = moment ( midnight , "x" ) . add ( 1 , "day" ) . endOf ( "day" ) . format ( "x ") ; // next day
666+ midnight = midnight . clone ( ) . add ( 1 , "day" ) . endOf ( "day" ) ; // next day
676667 }
677668 // Last day
678669 event . title += ` (${ count } /${ maxCount } )` ;
679- event . today += event . startDate >= today && event . startDate < today + ONE_DAY ;
680- event . tomorrow = ! event . today && event . startDate >= today + ONE_DAY && event . startDate < today + 2 * ONE_DAY ;
670+ event . today += this . timestampToMoment ( event . startDate ) . isSame ( now , "d" ) ;
671+ event . tomorrow = this . timestampToMoment ( event . startDate ) . isSame ( now . clone ( ) . add ( 1 , "days" ) , "d" ) ;
681672 splitEvents . push ( event ) ;
682673
683674 for ( let splitEvent of splitEvents ) {
684- if ( splitEvent . endDate > now && splitEvent . endDate <= future ) {
675+ if ( this . timestampToMoment ( splitEvent . endDate ) . isAfter ( now ) && this . timestampToMoment ( splitEvent . endDate ) . isSameOrBefore ( future ) ) {
685676 by_url_calevents . push ( splitEvent ) ;
686677 }
687678 }
@@ -716,16 +707,16 @@ Module.register("calendar", {
716707 */
717708 if ( this . config . limitDays > 0 ) {
718709 let newEvents = [ ] ;
719- let lastDate = today . clone ( ) . subtract ( 1 , "days" ) . format ( "YYYYMMDD" ) ;
710+ let lastDate = today . clone ( ) . subtract ( 1 , "days" ) ;
720711 let days = 0 ;
721712 for ( const ev of events ) {
722- let eventDate = moment ( ev . startDate , "x" ) . format ( "YYYYMMDD" ) ;
713+ let eventDate = this . timestampToMoment ( ev . startDate ) ;
723714
724715 /*
725716 * if date of event is later than lastdate
726717 * check if we already are showing max unique days
727718 */
728- if ( eventDate > lastDate ) {
719+ if ( eventDate . isAfter ( lastDate ) ) {
729720 // if the only entry in the first day is a full day event that day is not counted as unique
730721 if ( ! this . config . limitDaysNeverSkip && newEvents . length === 1 && days === 1 && newEvents [ 0 ] . fullDayEvent ) {
731722 days -- ;
0 commit comments