11/* global CalendarUtils */
22
3+ const moment = require ( "moment-timezone" ) ;
4+
35Module . register ( "calendar" , {
46 // Define module defaults
57 defaults : {
@@ -77,7 +79,7 @@ Module.register("calendar", {
7779
7880 // Define required scripts.
7981 getScripts ( ) {
80- return [ "calendarutils.js" , "moment.js" ] ;
82+ return [ "calendarutils.js" , "moment-timezone .js" ] ;
8183 } ,
8284
8385 // Define required translations.
@@ -215,11 +217,6 @@ Module.register("calendar", {
215217 this . updateDom ( this . config . animationSpeed ) ;
216218 } ,
217219
218- eventEndingWithinNextFullTimeUnit ( event , ONE_DAY ) {
219- const now = new Date ( ) ;
220- return event . endDate - now <= ONE_DAY ;
221- } ,
222-
223220 // Override dom generator.
224221 getDom ( ) {
225222 const ONE_SECOND = 1000 ; // 1,000 milliseconds
@@ -258,7 +255,9 @@ Module.register("calendar", {
258255 let lastSeenDate = "" ;
259256
260257 events . forEach ( ( event , index ) => {
261- const dateAsString = moment ( event . startDate , "x" ) . format ( this . config . dateFormat ) ;
258+ const eventStartDateMoment = this . timestampToMoment ( event . startDate ) ;
259+ const eventEndDateMoment = this . timestampToMoment ( event . endDate ) ;
260+ const dateAsString = eventStartDateMoment . format ( this . config . dateFormat ) ;
262261 if ( this . config . timeFormat === "dateheaders" ) {
263262 if ( lastSeenDate !== dateAsString ) {
264263 const dateRow = document . createElement ( "tr" ) ;
@@ -340,7 +339,7 @@ Module.register("calendar", {
340339 repeatingCountTitle = this . countTitleForUrl ( event . url ) ;
341340
342341 if ( repeatingCountTitle !== "" ) {
343- const thisYear = new Date ( parseInt ( event . startDate ) ) . getFullYear ( ) ,
342+ const thisYear = eventStartDateMoment . year ( ) ,
344343 yearDiff = thisYear - event . firstYear ;
345344
346345 repeatingCountTitle = `, ${ yearDiff } ${ repeatingCountTitle } ` ;
@@ -395,14 +394,14 @@ Module.register("calendar", {
395394 timeWrapper . className = `time light ${ this . config . flipDateHeaderTitle ? "align-right " : "align-left " } ${ this . timeClassForUrl ( event . url ) } ` ;
396395 timeWrapper . style . paddingLeft = "2px" ;
397396 timeWrapper . style . textAlign = this . config . flipDateHeaderTitle ? "right" : "left" ;
398- timeWrapper . innerHTML = moment ( event . startDate , "x" ) . format ( "LT" ) ;
397+ timeWrapper . innerHTML = eventStartDateMoment . format ( "LT" ) ;
399398
400399 // Add endDate to dataheaders if showEnd is enabled
401400 if ( this . config . showEnd ) {
402401 if ( this . config . showEndsOnlyWithDuration && event . startDate === event . endDate ) {
403402 // no duration here, don't display end
404403 } else {
405- timeWrapper . innerHTML += ` - ${ CalendarUtils . capFirst ( moment ( event . endDate , "x" ) . format ( "LT" ) ) } ` ;
404+ timeWrapper . innerHTML += ` - ${ CalendarUtils . capFirst ( eventEndDateMoment . format ( "LT" ) ) } ` ;
406405 }
407406 }
408407
@@ -415,70 +414,70 @@ Module.register("calendar", {
415414 const timeWrapper = document . createElement ( "td" ) ;
416415
417416 eventWrapper . appendChild ( titleWrapper ) ;
418- const now = new Date ( ) ;
417+ const now = moment ( ) ;
419418
420419 if ( this . config . timeFormat === "absolute" ) {
421420 // Use dateFormat
422- timeWrapper . innerHTML = CalendarUtils . capFirst ( moment ( event . startDate , "x" ) . format ( this . config . dateFormat ) ) ;
421+ timeWrapper . innerHTML = CalendarUtils . capFirst ( eventStartDateMoment . format ( this . config . dateFormat ) ) ;
423422 // Add end time if showEnd
424423 if ( this . config . showEnd ) {
425424 // and has a duation
426425 if ( event . startDate !== event . endDate ) {
427426 timeWrapper . innerHTML += "-" ;
428- timeWrapper . innerHTML += CalendarUtils . capFirst ( moment ( event . endDate , "x" ) . format ( this . config . dateEndFormat ) ) ;
427+ timeWrapper . innerHTML += CalendarUtils . capFirst ( eventEndDateMoment . format ( this . config . dateEndFormat ) ) ;
429428 }
430429 }
431430
432431 // For full day events we use the fullDayEventDateFormat
433432 if ( event . fullDayEvent ) {
434433 //subtract one second so that fullDayEvents end at 23:59:59, and not at 0:00:00 one the next day
435434 event . endDate -= ONE_SECOND ;
436- timeWrapper . innerHTML = CalendarUtils . capFirst ( moment ( event . startDate , "x" ) . format ( this . config . fullDayEventDateFormat ) ) ;
435+ timeWrapper . innerHTML = CalendarUtils . capFirst ( eventStartDateMoment . format ( this . config . fullDayEventDateFormat ) ) ;
437436 // 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 ") ) {
437+ if ( this . config . showEnd && ! this . config . showEndsOnlyWithDuration && ! eventStartDateMoment . isSame ( eventEndDateMoment , "d " ) ) {
439438 timeWrapper . innerHTML += "-" ;
440- timeWrapper . innerHTML += CalendarUtils . capFirst ( moment ( event . endDate , "x" ) . format ( this . config . fullDayEventDateFormat ) ) ;
439+ timeWrapper . innerHTML += CalendarUtils . capFirst ( eventEndDateMoment . format ( this . config . fullDayEventDateFormat ) ) ;
441440 } 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 ) ) ;
441+ if ( ! eventStartDateMoment . isSame ( eventEndDateMoment , "d" ) && eventStartDateMoment . isBefore ( now ) ) {
442+ timeWrapper . innerHTML = CalendarUtils . capFirst ( now . format ( this . config . fullDayEventDateFormat ) ) ;
444443 }
445- } else if ( this . config . getRelative > 0 && event . startDate < now ) {
444+ } else if ( this . config . getRelative > 0 && eventStartDateMoment . isBefore ( now ) ) {
446445 // Ongoing and getRelative is set
447446 timeWrapper . innerHTML = CalendarUtils . capFirst (
448447 this . translate ( "RUNNING" , {
449448 fallback : `${ this . translate ( "RUNNING" ) } {timeUntilEnd}` ,
450- timeUntilEnd : moment ( event . endDate , "x" ) . fromNow ( true )
449+ timeUntilEnd : eventEndDateMoment . fromNow ( true )
451450 } )
452451 ) ;
453- } else if ( this . config . urgency > 0 && event . startDate - now < this . config . urgency * ONE_DAY ) {
452+ } else if ( this . config . urgency > 0 && eventStartDateMoment . diff ( now , "d" ) < this . config . urgency ) {
454453 // Within urgency days
455- timeWrapper . innerHTML = CalendarUtils . capFirst ( moment ( event . startDate , "x" ) . fromNow ( ) ) ;
454+ timeWrapper . innerHTML = CalendarUtils . capFirst ( eventStartDateMoment . fromNow ( ) ) ;
456455 }
457456 if ( event . fullDayEvent && this . config . nextDaysRelative ) {
458457 // Full days events within the next two days
459458 if ( event . today ) {
460459 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "TODAY" ) ) ;
461460 } else if ( event . yesterday ) {
462461 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "YESTERDAY" ) ) ;
463- } else if ( event . startDate - now < ONE_DAY && event . startDate - now > 0 ) {
462+ } else if ( event . tomorrow ) {
464463 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "TOMORROW" ) ) ;
465- } else if ( event . startDate - now < 2 * ONE_DAY && event . startDate - now > 0 ) {
464+ } else if ( event . dayAfterTomorrow ) {
466465 if ( this . translate ( "DAYAFTERTOMORROW" ) !== "DAYAFTERTOMORROW" ) {
467466 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "DAYAFTERTOMORROW" ) ) ;
468467 }
469468 }
470469 }
471470 } else {
472471 // Show relative times
473- if ( event . startDate >= now || ( event . fullDayEvent && this . eventEndingWithinNextFullTimeUnit ( event , ONE_DAY ) ) ) {
472+ if ( eventStartDateMoment . isSameOrAfter ( now ) || ( event . fullDayEvent && eventEndDateMoment . diff ( now , "days" ) === 0 ) ) {
474473 // Use relative time
475474 if ( ! this . config . hideTime && ! event . fullDayEvent ) {
476475 Log . debug ( "event not hidden and not fullday" ) ;
477- timeWrapper . innerHTML = `${ CalendarUtils . capFirst ( moment ( event . startDate , "x" ) . calendar ( null , { sameElse : this . config . dateFormat } ) ) } ` ;
476+ timeWrapper . innerHTML = `${ CalendarUtils . capFirst ( eventStartDateMoment . calendar ( null , { sameElse : this . config . dateFormat } ) ) } ` ;
478477 } else {
479478 Log . debug ( "event full day or hidden" ) ;
480479 timeWrapper . innerHTML = `${ CalendarUtils . capFirst (
481- moment ( event . startDate , "x" ) . calendar ( null , {
480+ eventStartDateMoment . calendar ( null , {
482481 sameDay : this . config . showTimeToday ? "LT" : `[${ this . translate ( "TODAY" ) } ]` ,
483482 nextDay : `[${ this . translate ( "TOMORROW" ) } ]` ,
484483 nextWeek : "dddd" ,
@@ -488,33 +487,33 @@ Module.register("calendar", {
488487 }
489488 if ( event . fullDayEvent ) {
490489 // Full days events within the next two days
491- if ( event . today || ( event . fullDayEvent && this . eventEndingWithinNextFullTimeUnit ( event , ONE_DAY ) ) ) {
490+ if ( event . today || ( event . fullDayEvent && eventEndDateMoment . diff ( now , "days" ) === 0 ) ) {
492491 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "TODAY" ) ) ;
493492 } else if ( event . dayBeforeYesterday ) {
494493 if ( this . translate ( "DAYBEFOREYESTERDAY" ) !== "DAYBEFOREYESTERDAY" ) {
495494 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "DAYBEFOREYESTERDAY" ) ) ;
496495 }
497496 } else if ( event . yesterday ) {
498497 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "YESTERDAY" ) ) ;
499- } else if ( event . startDate - now < ONE_DAY && event . startDate - now > 0 ) {
498+ } else if ( event . tomorrow ) {
500499 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "TOMORROW" ) ) ;
501- } else if ( event . startDate - now < 2 * ONE_DAY && event . startDate - now > 0 ) {
500+ } else if ( event . dayAfterTomorrow ) {
502501 if ( this . translate ( "DAYAFTERTOMORROW" ) !== "DAYAFTERTOMORROW" ) {
503502 timeWrapper . innerHTML = CalendarUtils . capFirst ( this . translate ( "DAYAFTERTOMORROW" ) ) ;
504503 }
505504 }
506505 Log . info ( "event fullday" ) ;
507- } else if ( event . startDate - now < this . config . getRelative * ONE_HOUR ) {
506+ } else if ( eventStartDateMoment . diff ( now , "h" ) < this . config . getRelative ) {
508507 Log . info ( "not full day but within getrelative size" ) ;
509508 // If event is within getRelative hours, display 'in xxx' time format or moment.fromNow()
510- timeWrapper . innerHTML = `${ CalendarUtils . capFirst ( moment ( event . startDate , "x" ) . fromNow ( ) ) } ` ;
509+ timeWrapper . innerHTML = `${ CalendarUtils . capFirst ( eventStartDateMoment . fromNow ( ) ) } ` ;
511510 }
512511 } else {
513512 // Ongoing event
514513 timeWrapper . innerHTML = CalendarUtils . capFirst (
515514 this . translate ( "RUNNING" , {
516515 fallback : `${ this . translate ( "RUNNING" ) } {timeUntilEnd}` ,
517- timeUntilEnd : moment ( event . endDate , "x" ) . fromNow ( true )
516+ timeUntilEnd : eventEndDateMoment . fromNow ( true )
518517 } )
519518 ) ;
520519 }
@@ -593,46 +592,46 @@ Module.register("calendar", {
593592 return false ;
594593 } ,
595594
595+ /**
596+ * converts the given timestamp to a moment with a timezone
597+ * @param timestamp timestamp from an event
598+ * @returns {moment.Moment } moment with a timezone
599+ */
600+ timestampToMoment ( timestamp ) {
601+ return moment . unix ( timestamp ) . tz ( moment . tz . guess ( ) ) ;
602+ } ,
603+
596604 /**
597605 * Creates the sorted list of all events.
598606 * @param {boolean } limitNumberOfEntries Whether to filter returned events for display.
599607 * @returns {object[] } Array with events.
600608 */
601609 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 ;
610+ let now = moment ( ) ;
611+ let today = now . clone ( ) . startOf ( "day" ) ;
612+ let future = now . clone ( ) . startOf ( "day" ) . add ( this . config . maximumNumberOfDays , "days" ) ;
606613
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- }
617614 let events = [ ] ;
618615
619616 for ( const calendarUrl in this . calendarData ) {
620617 const calendar = this . calendarData [ calendarUrl ] ;
621618 let remainingEntries = this . maximumEntriesForUrl ( calendarUrl ) ;
622- let maxPastDaysCompare = now - this . maximumPastDaysForUrl ( calendarUrl ) * ONE_DAY ;
619+ let maxPastDaysCompare = now . clone ( ) . subtract ( this . maximumPastDaysForUrl ( calendarUrl ) , "days" ) ;
623620 let by_url_calevents = [ ] ;
624621 for ( const e in calendar ) {
625622 const event = JSON . parse ( JSON . stringify ( calendar [ e ] ) ) ; // clone object
623+ const eventStartDateMoment = this . timestampToMoment ( event . startDate ) ;
624+ const eventEndDateMoment = this . timestampToMoment ( event . endDate ) ;
626625
627626 if ( this . config . hidePrivate && event . class === "PRIVATE" ) {
628627 // do not add the current event, skip it
629628 continue ;
630629 }
631630 if ( limitNumberOfEntries ) {
632- if ( event . endDate < maxPastDaysCompare ) {
631+ if ( eventEndDateMoment . isBefore ( maxPastDaysCompare ) ) {
633632 continue ;
634633 }
635- if ( this . config . hideOngoing && event . startDate < now ) {
634+ if ( this . config . hideOngoing && eventStartDateMoment . isBefore ( now ) ) {
636635 continue ;
637636 }
638637 if ( this . config . hideDuplicates && this . listContainsEvent ( events , event ) ) {
@@ -641,47 +640,46 @@ Module.register("calendar", {
641640 }
642641
643642 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 ;
643+ event . today = eventStartDateMoment . isSame ( now , "d" ) ;
644+ event . dayBeforeYesterday = eventStartDateMoment . isSame ( now . clone ( ) . subtract ( 2 , "days" ) , "d" ) ;
645+ event . yesterday = eventStartDateMoment . isSame ( now . clone ( ) . subtract ( 1 , "days" ) , "d" ) ;
646+ event . tomorrow = eventStartDateMoment . isSame ( now . clone ( ) . add ( 1 , "days" ) , "d" ) ;
647+ event . dayAfterTomorrow = eventStartDateMoment . isSame ( now . clone ( ) . add ( 2 , "days" ) , "d" ) ;
649648
650649 /*
651650 * if sliceMultiDayEvents is set to true, multiday events (events exceeding at least one midnight) are sliced into days,
652651 * otherwise, esp. in dateheaders mode it is not clear how long these events are.
653652 */
654- const maxCount = Math . round ( ( event . endDate - 1 - moment ( event . startDate , "x" ) . endOf ( "day" ) . format ( "x" ) ) / ONE_DAY ) + 1 ;
653+ const maxCount = eventEndDateMoment . diff ( eventStartDateMoment , "days" ) + 1 ;
655654 if ( this . config . sliceMultiDayEvents && maxCount > 1 ) {
656655 const splitEvents = [ ] ;
657656 let midnight
658- = moment ( event . startDate , "x" )
657+ = eventStartDateMoment
659658 . clone ( )
660659 . startOf ( "day" )
661660 . add ( 1 , "day" )
662- . endOf ( "day" )
663- . format ( "x" ) ;
661+ . endOf ( "day" ) ;
664662 let count = 1 ;
665- while ( event . endDate > midnight ) {
663+ while ( eventEndDateMoment . isAfter ( midnight ) ) {
666664 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" ) ;
665+ thisEvent . today = this . timestampToMoment ( thisEvent . startDate ) . isSame ( now , "d" ) ;
666+ thisEvent . tomorrow = this . timestampToMoment ( thisEvent . startDate ) . isSame ( now . clone ( ) . add ( 1 , "days" ) , "d" ) ;
667+ thisEvent . endDate = midnight . clone ( ) . subtract ( 1 , "day" ) . unix ( ) ;
670668 thisEvent . title += ` (${ count } /${ maxCount } )` ;
671669 splitEvents . push ( thisEvent ) ;
672670
673- event . startDate = midnight ;
671+ event . startDate = midnight . unix ( ) ;
674672 count += 1 ;
675- midnight = moment ( midnight , "x" ) . add ( 1 , "day" ) . endOf ( "day" ) . format ( "x" ) ; // next day
673+ midnight = midnight . clone ( ) . add ( 1 , "day" ) . endOf ( "day" ) . unix ( ) ; // next day
676674 }
677675 // Last day
678676 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 ;
677+ event . today += this . timestampToMoment ( event . startDate ) . isSame ( now , "d" ) ;
678+ event . tomorrow = this . timestampToMoment ( event . startDate ) . isSame ( now . clone ( ) . add ( 1 , "days" ) , "d" ) ;
681679 splitEvents . push ( event ) ;
682680
683681 for ( let splitEvent of splitEvents ) {
684- if ( splitEvent . endDate > now && splitEvent . endDate <= future ) {
682+ if ( this . timestampToMoment ( splitEvent . endDate ) . isAfter ( now ) && this . timestampToMoment ( splitEvent . endDate ) . isSameOrBefore ( future ) ) {
685683 by_url_calevents . push ( splitEvent ) ;
686684 }
687685 }
@@ -716,16 +714,16 @@ Module.register("calendar", {
716714 */
717715 if ( this . config . limitDays > 0 ) {
718716 let newEvents = [ ] ;
719- let lastDate = today . clone ( ) . subtract ( 1 , "days" ) . format ( "YYYYMMDD" ) ;
717+ let lastDate = today . clone ( ) . subtract ( 1 , "days" ) ;
720718 let days = 0 ;
721719 for ( const ev of events ) {
722- let eventDate = moment ( ev . startDate , "x" ) . format ( "YYYYMMDD" ) ;
720+ let eventDate = this . timestampToMoment ( ev . startDate ) ;
723721
724722 /*
725723 * if date of event is later than lastdate
726724 * check if we already are showing max unique days
727725 */
728- if ( eventDate > lastDate ) {
726+ if ( eventDate . isAfter ( lastDate ) ) {
729727 // if the only entry in the first day is a full day event that day is not counted as unique
730728 if ( ! this . config . limitDaysNeverSkip && newEvents . length === 1 && days === 1 && newEvents [ 0 ] . fullDayEvent ) {
731729 days -- ;
0 commit comments