1function checkIfRruleExists(settingsRrule) { 2 return !!settingsRrule && settingsRrule !== 'null'; 3} 4 5function isInRange( 6 originStartTime, 7 originEndTime, 8 allDayEnabled = false, 9 settingsRrule, 10 timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone 11) { 12 13 const timeZoneValue = decodeURIComponent(timeZone); 14 const now = new Date(); 15 const currentTime = timeZoneValue 16 ? new Date(now.toLocaleString('en-US', { timeZone: timeZoneValue })) 17 : now; 18 19 // Convert the times to the same timezone as the conditionTimezone 20 let startTime = new Date( 21 originStartTime.toLocaleString('en-US', { timeZone: timeZoneValue }) 22 ); 23 let endTime = new Date(originEndTime.toLocaleString('en-US', { timeZone: timeZoneValue })); 24 25 // If all day is true, adjust the start and end times to be full day 26 if (allDayEnabled) { 27 startTime.setHours(0, 0, 0, 0); 28 endTime.setHours(23, 59, 59, 999); 29 } 30 31 if (checkIfRruleExists(settingsRrule) && rrule) { 32 //rrule is a 3rd party library to parse rrule strings 33 const recurringRule = rrule.rrulestr(settingsRrule); 34 recurringRule.options = { 35 ...recurringRule.options, 36 tzid: timeZoneValue, 37 dtstart: startTime, 38 until: getEndDate( 39 endTime, 40 recurringRule.options, 41 currentTime, 42 originStartTime, 43 originEndTime, 44 allDayEnabled 45 ), 46 }; 47 48 const betweenOccurrences = measureFunctionExecutionTime(() => 49 recurringRule.between( 50 recurringRule.options.dtstart, 51 recurringRule.options.until, 52 true 53 ) 54 ); 55 56 return betweenOccurrences.some((occurrence) => { 57 if (!allDayEnabled) { 58 setTimeFromAnotherDate(occurrence, originEndTime); 59 return ( 60 compareDates(currentTime, occurrence, true) && 61 compareDatesIgnoringSeconds(currentTime, occurrence) <= 0 62 ); 63 } 64 return compareDates(currentTime, occurrence, allDayEnabled); 65 }); 66 } 67 68 return ( 69 compareDatesIgnoringSeconds(currentTime, startTime) >= 0 && 70 compareDatesIgnoringSeconds(currentTime, endTime) <= 0 71 ); 72} 73 74function shouldShowRuleObjectForDateTimeRange( 75 ruleObjName, 76 condition, 77 actionType 78) { 79 const settings = shouldCheckMultipleConditions 80 ? condition.params 81 : condition; 82 const startTimeValue = decodeURIComponent(settings.start_time); 83 const endTimeValue = decodeURIComponent(settings.end_time); 84 const settingsStartTime = new Date(startTimeValue); 85 const settingsEndTime = new Date(endTimeValue); 86 const settingsAllDayEnabled = parseBoolean(settings.all_day_enabled); 87 const settingsRrule = settings.rrule; 88 const settingsTimeZone = settings.timezone; 89 90 if (settingsStartTime && settingsEndTime) { 91 const cookieName = getSmartRuleCookieName(ruleObjName, actionType); 92 return ( 93 isInRange( 94 settingsStartTime, 95 settingsEndTime, 96 settingsAllDayEnabled, 97 settingsRrule, 98 settingsTimeZone 99 ) && 100 //if the rule was already shown we shouldn't show it again until the ttl time when cookie expires 101 getCookie(cookieName) === null && 102 // there is no cookie of the same action type - site visitor already saw this action 103 !hasCookieOfType(actionType) 104 ); 105 } 106 107 //if there is no start_time, end_time, all_day_enabled, timezone in settings it means 108 // that the condition is not date time range, and we need to disregard this conditions 109 return true; 110} 111 112function compareDates(date1, date2, allDay) { 113 const d1 = new Date(date1); 114 const d2 = new Date(date2); 115 116 if (allDay) { 117 const year1 = d1.getFullYear(); 118 const month1 = d1.getMonth(); 119 const day1 = d1.getDate(); 120 121 const year2 = d2.getFullYear(); 122 const month2 = d2.getMonth(); 123 const day2 = d2.getDate(); 124 125 return year1 === year2 && month1 === month2 && day1 === day2; 126 } else { 127 d1.setSeconds(0, 0); 128 d2.setSeconds(0, 0); 129 130 return d1.getTime() === d2.getTime(); 131 } 132} 133 134function compareDatesIgnoringSeconds(date1, date2) { 135 let d1 = new Date(date1.getTime()); 136 let d2 = new Date(date2.getTime()); 137 138 d1.setSeconds(0, 0); 139 d2.setSeconds(0, 0); 140 141 if (d1.getTime() === d2.getTime()) { 142 return 0; 143 } else if (d1.getTime() < d2.getTime()) { 144 return -1; //d1 is earlier than d2 145 } else { 146 return 1; //d1 is later than d2 147 } 148} 149 150function getEndDate( 151 endTime, 152 options, 153 currentTime, 154 originStartTime, 155 originEndTime, 156 allDay 157) { 158 if (options.until) { 159 if (allDay) { 160 return options.until; 161 } 162 return setTimeFromAnotherDate(options.until, originEndTime); 163 } 164 const isOriginStartTimeEqualsToOriginEndTime = compareDates( 165 originStartTime, 166 originEndTime, 167 true 168 );
169 if (!isOriginStartTimeEqualsToOriginEndTime) { 170 // it means the user specify end time, rule should live until the end time 171 return endTime; 172 } 173 const isEndTimeBeforeCurrentTime = 174 compareDatesIgnoringSeconds(endTime, currentTime) < 0; 175 if (isOriginStartTimeEqualsToOriginEndTime && isEndTimeBeforeCurrentTime) { 176 // endTime === startTime - means the user didnt specify end time, the rule should live forever 177 // we need to check if endTime < currentTime - in this case check until tmrw to not miss today 178 const tmrw = new Date(currentTime); 179 tmrw.setDate(currentTime.getDate() + 1); 180 return tmrw; 181 } 182 return currentTime; 183} 184 185function setTimeFromAnotherDate(targetDate, sourceDate) { 186 const hours = sourceDate.getHours(); 187 const minutes = sourceDate.getMinutes(); 188 const seconds = sourceDate.getSeconds(); 189 const milliseconds = sourceDate.getMilliseconds(); 190 191 targetDate.setHours(hours, minutes, seconds, milliseconds); 192 193 return targetDate; 194} 195 196function measureFunctionExecutionTime(callback) { 197 const startTime = performance.now(); 198 const res = callback(); 199 const endTime = performance.now(); 200 const duration = endTime - startTime; 201 202 if (duration > 1000) { 203 window.runtime.API.logService.warn( 204 `The RRULE function took more than a second: ${duration.toFixed( 205 3 206 )} ms` 207 ); 208 } 209 return res; 210} 211 212//for testing purposes. 213// unit tests are here: client/src/modules/runtime/src/code/services/tests/timeRangeConditionService.test.js 214window.timeRangeConditionService = { 215 isInRange, 216};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.