Calendar filter
Value resolver – Abstract
Purpose: Performs a check for working days against a specified Calendar based on a date or date range provided as an input value. If the check fails, an alternate date is returned, otherwise the input value is returned.
The Calendar filter value resolver performs a check for working days based on a date or date range provided as input value (see below for details) against a Calendar specified either as Static or at runtime by a value resolver. The check is considered passed if the Calendar classifies the date or the from and to dates of a date range as a working day. Then the input value is returned. Otherwise, an alternative date for the date or date range is searched for and returned.
The Jump backwards option decides the search direction (earlier/later) for the alternative date if the input value does not pass the check for working days against the specified Calendar.
Special use case: In the context of a For each loop event action (see last example below), the Calendar filter value resolver can be used to determine, starting from a start date, a date that is a certain number of business days away from the start date.
One of the following data types is expected as input value:
Long ( java.lang.Long)
'Date' (java.lang.Date)
'Timestamp' (java.sql.Timestamp)
'Date with time' (DateTime)
'Date range with time' (DateRange)
Interpretation of date values without declared time zone
A Long value as input value is interpreted as milliseconds since 01.01.1970 00:00:00.000 (UTC). However, as for all input value types interpreted as a date without a time zone (Long, Timestamp, Date), the UTC time zone is not the default. Rather, the default time zone applicable in the context is considered according to the following logic:
If a 'Default time zone' (defaultTimeZone) is defined for the User of session (in the actual logged-in session), this will be used.
Otherwise, the account of the Company of session (in the actual logged-in session) and the 'Default time zone' (defaultTimeZone) defined there, if applicable, will be used.
Only if neither account defines a 'Default time zone' for the actual logged in session, the selection for the time zone in the operating system of the server or client will be the deciding factor:
In the server context (e.g. for Event handling) the time zone is taken from the Lobster Data Platform / Orchestration server execution context.
In the client context (e.g. in a Client workflow), the selection for the time zone is adopted in the client operating system.
The type of the return value always corresponds to the type of the input value.
►NOTE◄ For the data types summarized as 'Date values without declared time zone' this means that the default time zone applicable in the context is taken into account by the checking and calculation logic, but does not explicitly appear in the data of the return value. The time zone used for interpretation can be decisive for which calendar day a certain input value is assigned, which formally defines only 'UTC milliseconds'. However, the return value determined depending on the comparison between the assigned calendar day and a Calendar is then again defined only in 'UTC milliseconds'.
The following case distinction is used to determine the return value:
Suitable type as input value? |
Calendar defined? |
'Check for working days' (see below) against the Calendar? |
'Jump backwards?' option |
Return value |
|
irrelevant |
irrelevant |
irrelevant |
Input value |
|
|
|||
|
|
|||
|
|
Alternative date: Least possible shift of the input value (date value/range) to later, |
||
|
Alternative date: Least possible shift of the input value (date value/range) to earlier, |
|||
►NOTE◄ Rules for 'Jump forward' or 'Jump backward'.
|
The following rules apply to the 'Check for working days' of the input value against the defined Calendar:
Type of input value |
Checking logic |
Long |
A date value (as opposed to a 'Date range', see below) is considered a working day if the calendar day determined with respect to the applicable time zone is considered a working day according to the defined Calendar. If necessary, definitions on different levels of the calendar model are taken into account:
A calendar day is considered a working day if one of the following conditions is met:
References to improperly parameterized calendars in a calendar filter value resolver can cause infinite loops that require a server restart. |
'Date range with time' |
A 'Date range' is considered a working day if the calendar days for the 'From' and 'To' components, determined taking into account the time zone, are considered working days when evaluated against the defined Calendar according to the check logic described above. ►IMPORTANT◄ Whether the Calendar shows working days between the 'From' and 'To' calendar days or not is irrelevant for the check! If the check is not passed for a date range, then the date range as a whole is moved 'in parallel', i.e. an alternative date is determined while retaining the original time span between the 'From' and 'To' components. ►WARNING◄ It is possible that a Calendar in the desired search direction does not contain a pair of working days (for 'From' and 'To') in the 'suitable' interval. For example, if a calendar defines only three adjacent days of the week (say: Monday, Tuesday and Wednesday) as working days, then it is impossible to find a suitable date for a date range with a time span of 3 – 4 days. The following diagram illustrates the problem in the example: |
Configuration
The Calendar filter value resolver expects a date value or date range as input value, which can be provided by concatenation or as a reference object.
The Static option (unchecked by default) refers to the configuration for the required Calendar parameter. If the option is checked (see image), a dropdown box appears, which supports a static single selection for a Calendar. All calendars for which read access exists in the context of the configuration appear in the dropdown. At runtime, there is always access to the selected calendar. An already selected calendar for which there is no read access in the current configuration session appears with the label 'Hidden calendar'. As shown in the image, a search function supports the selection of the calendar based on the properties contained in the label (in the example: Name '24-1 (MON)'). |
|
If the Static option is unchecked, then a value resolver must be configured for the Calendar parameter. As return value for the value resolver either a Calendar object (Calendar) is expected (see image below right) or a Long value (see image right), which specifies the ID (id) of a Calendar object. In the upper right image, the statically defined Long value 451 references the Calendar '24-1 (MON)' from the example above. In the image on the bottom right, a Variable value resolver is used to read a variable that must return an object of Type 'Calendar' (Calendar) at runtime. This variable could be filled with a Search (Event action), for example. ►NOTE◄
|
|
|
|
The option Jump backwards is unchecked by default. Then the calendar (or along a theoretical 'time axis') is 'jumped forward' if the input value does not pass the 'Check for working day' (see above). If the option Jump backwards is checked, then the system searches for replacement dates that are earlier than the input value, if necessary.
|
|
Examples
Simple date calculation taking into account working days
In the context of an event handling, the estimated time of arrival ('ETA') of a shipment is calculated as the 'Date with time'. Since the incoming goods are considered to be available immediately (or on the same calendar day) only if they are received on a working day, the calculated 'ETA' date is compared with an existing Calendar to determine a further date ('AVAIL') for the effective availability of the goods at the consignee's address. The user should be informed about the calendar days for 'ETA' and 'AVAIL' by a Show alert (Popup) event action. Runtime example:
Configuration: For the configuration on the right, the already calculated 'ETA' date (as 'Date with time') is valid as a reference object within an Execute with event action (not shown in the image).
►NOTE◄ The availability date is only displayed here as a calendar day without time components and is not otherwise processed or stored. In this respect, it does not matter that a time contained in the calculated 'ETA' date may pass to the 'AVAIL' date. The following example deals with this problem. |
|
Date calculation with conditional adjustment of the time (only when 'jumping forward' to the following working day)
The previous example is now extended so that on the one hand the time calculated in the 'ETA' date appears in the message to the exact minute. On the other hand, when 'jumping forward' – i.e. when the 'ETA' date falls on a calendar day that is not a working day – the time for the availability date ('AVAIL') is statically set to the time 07:30 (on the following working day). If the 'ETA' directly matches a working day, the goods are considered 'immediately' available. Runtime example:
Configuration:
|
|
Appointment determination against a 'dynamically' selected calendar at runtime
In the context of event handling, it is determined up to which date in the current month partial loads can still be ordered via the freight forwarder already selected for the specific order. For this reason, a Calendar with the uniform name 'LTL' has been created for each freight forwarder for the coordination of appointments, which represents recurring and discreetly defined appointment options for the processing of partial loads as 'working days'. Configuration: The event handling must first determine the calendar matching the selected freight forwarder in the context of the relevant order. This allows a Search (Event action) to be executed within a Run as event action to ensure read access for the calendars created in the possession of the various freight forwarders. The Search (Event action) will not be described in detail here. It is intended as a tuple search to find the first (and by convention: only) Calendar owned by a particular freight forwarder whose name is 'LTL'. As a projection, only the id field is needed for the Calendar filter. The result of the tuple search is written to the variable LTL@FWD.
►NOTE◄ The fact that the LTL_ultimate date is already in the past at the time of the request is not dealt with separately here. |
|
Runtime example: According to its 'LTL' calendar, a freight forwarder offers transports for partial loads only on Thursdays as a rule. A query for the LTL_ultimate date in August 2022 results in the value shown to the right, which refers to the calendar day 'Thursday, 25 August 2022'. ►NOTE◄ The millisecond value in the dateValue field in the image on the right shows that the time (23:59:59.999) from the input value ('end of the month') is also reflected in the return value of the calendar filter. |
Section from the 'Storage' with variable values in a test run
<entry> <key xsi:type= "xsd:string" >LTL_ultimate</key> <value dateValue= "1661464799999" timeZone= "Europe/Berlin" xsi:type= "core:DateTime" /> </entry> |
Appointment offset by a predefined number of working days
A target date (end) is determined from a given date – here as a 'Date with time' value in the variable start – by comparing it with a specific Calendar. The target date is a specific number of working days (offset) after the start date. Configuration: Within an event action, the For each loop shown on the right iterates over the offset variable, which defines the number of business days from start as an integer:
At the end there should be exactly as many working days (according to the selected Calendar) difference between start and end as specified in the offset variable. ►NOTE◄ The configuration shown here assumes that the value of the offset>0 variable and the end variable does not contain a value ($null) at the beginning. |
|