2025.1 to 2025.2
datetime.toDate(...) without a pattern is deprecated
What changed
Starting with ADITO 2025.2, the following method is deprecated:
// deprecated (no longer supported)
datetime.toDate("1755761468080");
The method keeps using a timestamp in milliseconds as input.
Why it matters
This method will be removed in a future major release. Prepare your code now to avoid issues in upcoming updates.
Recommended actions
Use a method signature that includes a pattern.
For example, convert:
// deprecated (no longer supported)
datetime.toDate("1755761468080");
to a method signature that includes a pattern:
// better
datetime.toDate("1755761468080", "yyyy-MM-dd");
Developer comments on why this was changed
In previous versions of ADITO, the behavior of the method was undefined and ambiguous. This meant the method could be used in different ways, which could lead to unexpected behavior and errors in customizations without being noticed.
To prevent this, always provide an explicit pattern when calling the method.
Two new constants were also added:
// new pattern constants:
datetime.DATETIME_PATTERN_ISO_LOCAL_DATE_TIME //yyyy-MM-dd'T'HH:mm:ss
datetime.DATETIME_PATTERN_ISO_OFFSET_DATE_TIME_MILLIS //yyyy-MM-dd'T'HH:mm:ss.SSSXXX
These produce strings formatted according to ISO 8601
For the example above, this results in:
// result (for UTC — e.g., ADITO server context): 2025-08-21T07:31:08
datetime.toDate("1755761468080", datetime.DATETIME_PATTERN_ISO_LOCAL_DATE_TIME);
// result (for Europe/Berlin — e.g., in a client context running in the Europe/Berlin time zone): 2025-08-21T09:31:08
datetime.toDate("1755761468080", datetime.DATETIME_PATTERN_ISO_LOCAL_DATE_TIME);
Explicit Over Implicit: Why no default date format is used
Why is the method variant without date format deprecated instead of continuing with a default format as fallback?
This was discussed while addressing the grounding issues of the method.
This decision follows the fundamental software design idea: "Explicit is better than implicit".
Consider the following analogies why this is the case here:
- Translations: "Translate this text" without specifying a target language makes no sense
- Unit Conversion: Like currency conversion - without a target currency, the operation is incomplete
Reasoning for this method:
Code Quality & Maintainability
- Explicit Intent: Developers must consciously choose a format → self-documenting code
- Avoidance of Implicit behavior: No "magical" default behavior that could lead to confusion later
- Code Readability: When reading code, the format is immediately clear without needing to consult documentation
- Refactoring Safety: Changes to a default format would silently affect many code locations
Internationalization (i18n) & Localization
- Locale Dependency Issues: A "default format" is not universal — what works in DE may be confusing in the US
- No Implicit Locale Assumptions: Prevents unintentional use of system-dependent formats (e.g. operating system-level)
- Conscious i18n Decision: Forces consideration of whether the format needs to be localized
Error Prevention
- Avoid False Assumptions: Developers might incorrectly assume "their" expected format is the default
- Reduce Copy-Paste Errors: Without explicit format, calls are copied uncritically without questioning the format
- Prevent API Misuse: The deprecation warning makes it harder for accidental usage
Data Consistency
- API Compatibility: Explicit formats ensure data is stored/transmitted in consistent formats
- Prevent Parsing Problems: Consistent formats reduce errors during subsequent parsing
Maintenance & Evolution
- Default Changes Problematic: Later changing a default format would constitute a breaking change
- Backward Compatibility: No hidden behavior that must be maintained for compatibility reasons
- Avoid Technical Debt: Prevents establishment of code based on implicit assumptions
Team Communication
- More Effective Code Reviews: Format choice becomes visible and can be discussed
- Onboarding: New developers are forced to familiarize themselves with format conventions
A thought on migration paths:
For common use cases, specialized methods and constants could be introduced if necessary in the future:
Frequent Patterns: Create dedicated methods that clearly describe their purpose (e.g., toIsoDate(), toRfc3339(),
toLogFormat() or similar)
This approach keeps the code clear, understandable, and maintainable while preventing ambiguity and potential errors.
FreeBusy information no longer has UID Information
What changed
Starting with ADITO 2025.2, all calendar queries will no longer contain UIDs for the free/busy information. This is only relevant for the new Graph-based calendar backend over our new Backend-Server (MIBS) and will not affect the old calendar backend. (Currently the MIBS is not yet in use, so this will only have an effect in the not so distant future.)
Why it matters
This change was made to improve performance because, to have UIDs, we need to load the events from the remote backend. This resulted in a lot of data being transferred over the network.
With the introduction of the new Graph-based calendar backend, we decided to change this behavior so that we can load the free/busy information way more efficiently.
Recommended actions
Most probably this will not impact you, but if you are using the free/busy UID information in your customizations, you will need to adjust your code.
Example methods that are affected:
getEntries
getExpandedEntries
This already did not work in when using UIDs in the calendar queries. That is also the reason why the single event methods like (getEntry, getExpandedEntry) didn't work either. You need to use a UID to fetch the single event.
Value of entityFields with linkedContext needs to return an ID
What changed
Starting with ADITO 2025.2, the value of entityFields with linkedContext needs to return an ID. Due to numerous bugfixes related to linkedContext / targetContext, the linkedContext is evaluated before the targetContext. In the past the targetContextIdField of the provider was sometimes (e.g., 360Degree_entity.TITLE) used for the linkedContextId. Since this is not always correct, the ID needs to be returned explicitly.
Why it matters
If you are using the linkedContext feature, you need to make sure that the value of entityFields the ID of the record; otherwise an incorrect link will be created.
Recommended actions
Make sure that the value of entityFields with a linkedContext returns the ID of the record. Check all occurrences of entityFields with linkedContext / linkedContextProcess.
Example:
- 360Degree_entity.TITLE.linkedContext returns: "Organisation"
- 360Degree_entity.TITLE.VALUE returns: "UUID to the Organisation record>"
- 360Degree_entity.TITLE.DISPLAYVALUE returns: "Name of the Organisation record"