You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2022/03/10 15:32:32 UTC

[syncope] branch master updated: [SYNCOPE-1332] Moving to Java 8 DateTime APIs (#324)

This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/master by this push:
     new 7309dd3  [SYNCOPE-1332] Moving to Java 8 DateTime APIs (#324)
7309dd3 is described below

commit 7309dd303f2fe9238df4b69776f6284a87549599
Author: Francesco Chicchiriccò <il...@users.noreply.github.com>
AuthorDate: Thu Mar 10 16:32:22 2022 +0100

    [SYNCOPE-1332] Moving to Java 8 DateTime APIs (#324)
---
 .../main/resources/archetype-resources/fit/pom.xml |   7 ++
 .../apache/syncope/client/console/pages/WA.java    |   4 +-
 .../apache/syncope/client/console/panels/OIDC.java |   6 +-
 .../client/console/rest/AMSessionDeserializer.java |   9 +-
 .../client/console/rest/AMSessionRestClient.java   |   4 +-
 .../console/rest/SRAStatisticsRestClient.java      |   4 +-
 .../client/console/rest/WASessionRestClient.java   |  18 +--
 .../client/console/panels/VirSchemaDetails.java    |   4 +-
 .../policies/ProvisioningPolicyModalPanel.java     | 118 ++++++++++----------
 .../console/topology/TopologyTogglePanel.java      |  70 ++++++------
 .../topology/TopologyWebSocketBehavior.java        |   6 +-
 .../any/MergeLinkedAccountsWizardBuilder.java      |   4 +-
 .../syncope/client/ui/commons/BaseSession.java     |   3 +-
 .../apache/syncope/client/ui/commons/DateOps.java  |  85 ++++++++++++++
 .../syncope/client/ui/commons/MIMETypesLoader.java |   4 +-
 .../markup/html/form/AjaxDateFieldPanel.java       |   5 +-
 .../commons/markup/html/form/DateFieldPanel.java   |   3 +-
 .../syncope/client/console/PreferenceManager.java  |   4 +-
 .../client/console/SyncopeConsoleSession.java      |   5 +-
 .../client/console/audit/AuditHistoryDetails.java  |   8 +-
 .../syncope/client/console/batch/BatchContent.java | 100 ++++++++---------
 .../client/console/chartjs/ChartJSPanel.java       |   5 +-
 .../client/console/commons/AnyDataProvider.java    |  11 +-
 .../client/console/commons/DateFormatROModel.java  |  50 ---------
 .../client/console/layout/AnyLayoutUtils.java      |   4 +-
 .../console/panels/AccessTokenDirectoryPanel.java  |  11 +-
 .../client/console/panels/AnyDirectoryPanel.java   |   5 +-
 .../syncope/client/console/panels/BeanPanel.java   |  56 +++++-----
 .../client/console/panels/DirectoryPanel.java      |   6 +-
 .../console/panels/ImplementationModalPanel.java   |   4 +-
 .../console/panels/ParametersWizardAttrStep.java   |   5 +-
 .../console/panels/search/SearchClausePanel.java   |  46 ++++----
 .../console/policies/PolicyRuleWizardBuilder.java  |   4 +-
 .../console/reports/ReportletWizardBuilder.java    |   9 +-
 .../client/console/rest/ExecutionRestClient.java   |   4 +-
 .../client/console/rest/LoggerConfRestClient.java  |   4 +-
 .../client/console/rest/ReportRestClient.java      |  17 +--
 .../client/console/rest/TaskRestClient.java        |  31 +++---
 .../console/tasks/TaskAttributesDetailsView.java   |   4 +-
 .../repeater/data/table/DatePropertyColumn.java    |   7 +-
 .../syncope/client/console/widgets/LoadWidget.java |   5 +-
 .../client/console/widgets/ProgressesPanel.java    |   5 +-
 .../console/widgets/ReconciliationWidget.java      |  35 +++---
 .../reconciliation/ReconciliationReport.java       |  18 +--
 .../reconciliation/ReconciliationReportParser.java |   4 +-
 .../console/wizards/DelegationWizardBuilder.java   |  27 +++--
 .../wizards/any/AbstractAttrsWizardStep.java       |   5 +-
 .../client/console/layout/AnyLayoutTest.java       |   4 +-
 .../syncope/client/enduser/PreferenceManager.java  |   4 +-
 .../client/enduser/SyncopeEnduserSession.java      |   7 +-
 .../client/enduser/SyncopeWebApplication.java      |   4 +-
 .../client/enduser/pages/SelfRegistration.java     |   4 +-
 .../client/enduser/panels/any/PlainAttrs.java      | 108 +++++++++---------
 .../apache/syncope/client/lib/SyncopeClient.java   |  27 +++--
 .../client/lib/SyncopeClientFactoryBean.java       |  12 +-
 .../org/apache/syncope/common/lib/AMSession.java   |   8 +-
 .../common/lib/wa/GoogleMfaAuthAccount.java        |  17 ++-
 .../syncope/common/lib/wa/GoogleMfaAuthToken.java  |  19 ++--
 .../apache/syncope/common/lib/wa/U2FDevice.java    |  17 ++-
 .../org/apache/syncope/common/lib/JSONTest.java    |   3 +-
 .../org/apache/syncope/common/lib/YAMLTest.java    |   3 +-
 .../common/rest/api/beans/U2FDeviceQuery.java      |  12 +-
 .../api/service/wa/GoogleMfaAuthTokenService.java  |  12 +-
 .../syncope/common/lib/to/RemediationTO.java       |  13 +--
 .../syncope/common/lib/SyncopeConstants.java       |   2 -
 .../syncope/common/lib/audit/AuditEntry.java       |  16 +--
 ...opeObjectMapper.java => SyncopeJsonMapper.java} |   8 +-
 .../common/lib/report/StaticReportletConf.java     |  13 +--
 .../common/lib/to/AbstractStartEndBean.java        |  23 ++--
 .../syncope/common/lib/to/AccessTokenTO.java       |  13 +--
 .../org/apache/syncope/common/lib/to/AnyTO.java    |  28 ++---
 .../apache/syncope/common/lib/to/DelegationTO.java |   6 +-
 .../org/apache/syncope/common/lib/to/JobTO.java    |  13 +--
 .../org/apache/syncope/common/lib/to/ReportTO.java |  23 ++--
 .../apache/syncope/common/lib/to/SchedTaskTO.java  |  33 +++---
 .../org/apache/syncope/common/lib/to/UserTO.java   |  53 +++------
 .../syncope/common/lib/types/AttrSchemaType.java   |   5 +-
 .../org/apache/syncope/common/lib/JSONTest.java    |   3 +-
 .../org/apache/syncope/common/lib/YAMLTest.java    |   3 +-
 .../common/lib/types/AttrSchemaTypeTest.java       |   4 +-
 .../rest/api/DateParamConverterProvider.java       |  24 ++--
 .../common/rest/api/beans/ExecDeleteQuery.java     |  78 +++++--------
 .../beans/{ExecQuery.java => ExecListQuery.java}   |  10 +-
 .../beans/{ExecuteQuery.java => ExecSpecs.java}    |  30 ++---
 .../common/rest/api/service/ExecutableService.java |  16 +--
 .../common/rest/api/service/TaskService.java       |   6 +-
 .../client/zookeeper/ZookeeperConfParamOps.java    |  12 +-
 .../client/zookeeper/ZookeeperDomainOps.java       |  14 +--
 .../client/zookeeper/ZookeeperServiceOps.java      |  12 +-
 .../zookeeper/ZookeeperTestContentLoader.java      |   4 +-
 .../client/self/SelfKeymasterClientContext.java    |  12 +-
 .../client/self/SelfKeymasterConfParamOps.java     |   4 +-
 .../core/logic/wa/GoogleMfaAuthTokenLogic.java     |   4 +-
 .../core/logic/wa/U2FRegistrationLogic.java        |   6 +-
 .../service/wa/GoogleMfaAuthTokenServiceImpl.java  |   4 +-
 .../rest/cxf/service/RemediationServiceImpl.java   |   8 +-
 .../core/logic/AbstractExecutableLogic.java        |  10 +-
 .../syncope/core/logic/AbstractJobLogic.java       |   3 +-
 .../syncope/core/logic/AccessTokenLogic.java       |   7 +-
 .../org/apache/syncope/core/logic/GroupLogic.java  |   4 +-
 .../org/apache/syncope/core/logic/ReportLogic.java |  11 +-
 .../org/apache/syncope/core/logic/TaskLogic.java   |  24 ++--
 .../core/rest/cxf/IdRepoRESTCXFContext.java        |  20 ++--
 .../core/rest/cxf/service/AbstractAnyService.java  |  22 ++--
 .../cxf/service/AbstractExecutableService.java     |   8 +-
 .../rest/cxf/service/AccessTokenServiceImpl.java   |  14 +--
 .../core/rest/cxf/service/SyncopeServiceImpl.java  |   4 +-
 .../core/rest/cxf/service/TaskServiceImpl.java     |   9 +-
 .../core/rest/cxf/service/UserServiceImpl.java     |   6 +-
 .../rest/cxf/service/AnyObjectServiceTest.java     |   4 +-
 .../rest/cxf/service/IdRepoRESTCXFTestContext.java |  17 +--
 .../syncope/core/persistence/api/dao/AnyDAO.java   |   4 +-
 .../core/persistence/api/dao/ReportExecDAO.java    |   9 +-
 .../syncope/core/persistence/api/dao/TaskDAO.java  |   4 +-
 .../core/persistence/api/dao/TaskExecDAO.java      |   8 +-
 .../core/persistence/api/entity/AccessToken.java   |   6 +-
 .../syncope/core/persistence/api/entity/Any.java   |  10 +-
 .../syncope/core/persistence/api/entity/Batch.java |   6 +-
 .../core/persistence/api/entity/Delegation.java    |  10 +-
 .../syncope/core/persistence/api/entity/Exec.java  |  10 +-
 .../persistence/api/entity/PlainAttrValue.java     |   6 +-
 .../core/persistence/api/entity/Remediation.java   |   6 +-
 .../persistence/api/entity/task/SchedTask.java     |   6 +-
 .../core/persistence/api/entity/user/User.java     |  12 +-
 .../persistence/jpa/dao/AbstractJPAJSONAnyDAO.java |   4 +-
 .../jpa/dao/AbstractJPAJSONLoggerDAO.java          |   4 +-
 .../persistence/jpa/dao/MyJPAJSONAnySearchDAO.java |   5 +-
 .../persistence/jpa/dao/PGJPAJSONAnySearchDAO.java |  31 ++++--
 .../src/main/resources/myjson/views.xml            |   6 +-
 .../src/test/resources/domains/MasterContent.xml   |  16 +--
 core/persistence-jpa/pom.xml                       |   1 +
 .../jpa/attrvalue/validation/BinaryValidator.java  |   4 +-
 .../jpa/content/ContentLoaderHandler.java          |   7 +-
 .../jpa/content/KeymasterConfParamLoader.java      |   4 +-
 .../jpa/content/XMLContentExporter.java            |   7 +-
 .../core/persistence/jpa/dao/AbstractAnyDAO.java   |  44 ++++----
 .../core/persistence/jpa/dao/AbstractDAO.java      |   7 --
 .../persistence/jpa/dao/JPAAccessTokenDAO.java     |   4 +-
 .../core/persistence/jpa/dao/JPAAnyMatchDAO.java   |   6 +-
 .../core/persistence/jpa/dao/JPAAnyObjectDAO.java  |   4 +-
 .../core/persistence/jpa/dao/JPAAnySearchDAO.java  |   6 +-
 .../core/persistence/jpa/dao/JPABatchDAO.java      |   4 +-
 .../core/persistence/jpa/dao/JPADelegationDAO.java |   6 +-
 .../core/persistence/jpa/dao/JPAGroupDAO.java      |   4 +-
 .../core/persistence/jpa/dao/JPAReportExecDAO.java |   7 +-
 .../core/persistence/jpa/dao/JPATaskDAO.java       |   7 +-
 .../core/persistence/jpa/dao/JPATaskExecDAO.java   |   7 +-
 .../core/persistence/jpa/dao/JPAUserDAO.java       |   4 +-
 .../core/persistence/jpa/entity/AbstractAny.java   |  29 ++---
 .../core/persistence/jpa/entity/AbstractExec.java  |  30 ++---
 .../jpa/entity/AbstractPlainAttrValue.java         |  19 ++--
 .../persistence/jpa/entity/JPAAccessToken.java     |  18 +--
 .../core/persistence/jpa/entity/JPABatch.java      |  21 +---
 .../core/persistence/jpa/entity/JPADelegation.java |  36 ++----
 .../persistence/jpa/entity/JPARemediation.java     |  18 +--
 .../jpa/entity/auth/JPAAuthProfile.java            |  49 ++++-----
 .../persistence/jpa/entity/task/JPASchedTask.java  |  22 +---
 .../core/persistence/jpa/entity/user/JPAUser.java  |  64 +++++------
 .../jpa/validation/entity/DelegationValidator.java |   2 +-
 .../main/resources/META-INF/spring-orm-oracle.xml  |  37 -------
 .../src/main/resources/oracle_indexes.xml          |  91 +++++++++++++++
 .../core/persistence/jpa/inner/AnySearchTest.java  |   4 +-
 .../persistence/jpa/inner/AuthProfileTest.java     |  12 +-
 .../persistence/jpa/inner/RemediationTest.java     |   8 +-
 .../core/persistence/jpa/inner/TaskExecTest.java   |  14 +--
 .../core/persistence/jpa/inner/UserTest.java       |  16 +--
 .../persistence/jpa/outer/AccessTokenTest.java     |   4 +-
 .../core/persistence/jpa/outer/ReportTest.java     |   6 +-
 .../core/persistence/jpa/outer/RoleTest.java       |   4 +-
 .../core/persistence/jpa/outer/TaskTest.java       |   8 +-
 .../core/persistence/jpa/outer/UserTest.java       |   4 +-
 .../src/test/resources/domains/MasterContent.xml   |   6 +-
 .../api/data/AccessTokenDataBinder.java            |  11 +-
 .../core/provisioning/api/jexl/JexlUtils.java      |   6 +-
 .../provisioning/api/jexl/SandboxUberspect.java    |   3 +-
 .../core/provisioning/api/job/JobManager.java      |   7 +-
 .../provisioning/api/serialization/POJOHelper.java |  15 ++-
 .../core/provisioning/api/utils/FormatUtils.java   | 102 ++++++++++-------
 .../provisioning/api/utils/FormatUtilsTest.java    |  53 ++++-----
 .../provisioning/java/DefaultAuditManager.java     |   6 +-
 .../provisioning/java/DefaultMappingManager.java   |   9 +-
 .../java/data/AbstractExecutableDatabinder.java}   |  27 ++---
 .../java/data/AccessTokenDataBinderImpl.java       |  46 ++++----
 .../java/data/ReportDataBinderImpl.java            |   7 +-
 .../provisioning/java/data/TaskDataBinderImpl.java |   7 +-
 .../provisioning/java/data/UserDataBinderImpl.java |   6 +-
 .../java/job/AbstractSchedTaskJobDelegate.java     |   6 +-
 .../provisioning/java/job/DefaultJobManager.java   |  58 ++++++----
 .../DefaultNotificationJobDelegate.java            |   6 +-
 .../java/job/report/DefaultReportJobDelegate.java  |  11 +-
 .../AbstractPropagationTaskExecutor.java           |   8 +-
 .../java/pushpull/AbstractPullResultHandler.java   |   6 +-
 .../SelfKeymasterInternalConfParamOps.java         |   4 +-
 .../rest/cxf/service/ConfParamServiceImpl.java     |   4 +-
 .../apache/syncope/core/logic/ConfParamLogic.java  |   4 +-
 .../core/persistence/jpa/entity/JPAConfParam.java  |   4 +-
 .../core/spring/security/AuthDataAccessor.java     |   4 +-
 core/starter/src/main/resources/core.properties    |   2 +-
 .../workflow/java/AbstractWorkflowAdapter.java     |   4 +-
 .../core/src/main/resources/core-oracle.properties |   2 +
 .../docker-compose/docker-compose-all.yml          |   2 +-
 .../resources/docker-compose/docker-compose-ha.yml |   4 +-
 .../docker-compose/docker-compose-postgresql.yml   |   2 +-
 .../main/resources/kubernetes/syncope/values.yaml  |   2 +-
 .../client/ElasticsearchClientFactoryBean.java     |   7 +-
 .../jpa/dao/ElasticsearchAnySearchDAO.java         |   3 +-
 .../java/job/ElasticsearchReindex.java             |   6 +-
 .../common/ui/panels/UserRequestFormPanel.java     |  67 ++++++-----
 .../org/apache/syncope/common/lib/to/JSONTest.java |   3 +-
 .../org/apache/syncope/common/lib/to/YAMLTest.java |   3 +-
 .../flowable/impl/FlowableBpmnProcessManager.java  |  10 +-
 .../core/flowable/impl/FlowableDeployUtils.java    |  10 +-
 .../resources/oidcc4ui/CodeConsumerResource.java   |   6 +-
 .../syncope/common/lib/oidc/OIDCLoginResponse.java |   8 +-
 .../apache/syncope/core/logic/OIDCC4UILogic.java   |   4 +-
 .../saml2sp4ui/AssertionConsumerResource.java      |   6 +-
 .../common/lib/saml2/SAML2LoginResponse.java       |  12 +-
 .../apache/syncope/core/logic/SAML2SP4UILogic.java |   3 +-
 .../syncope/client/console/pages/SCIMConfPage.java |   8 +-
 .../console/panels/SCIMConfGeneralPanel.java       | 122 ++++++++++-----------
 .../syncope/common/lib/scim/SCIMGeneralConf.java   |  42 +++----
 .../org/apache/syncope/core/logic/SCIMLogic.java   |   4 +-
 .../syncope/core/logic/scim/SCIMConfManager.java   |   4 +-
 .../apache/syncope/ext/scimv2/api/data/Meta.java   |  15 ++-
 .../syncope/ext/scimv2/cxf/AddETagFilter.java      |   6 +-
 .../ext/scimv2/cxf/SCIMJacksonJsonProvider.java    |  47 --------
 .../ext/scimv2/cxf/SCIMv2RESTCXFContext.java       |  20 ++--
 .../ext/scimv2/cxf/service/AbstractService.java    |   6 +-
 fit/console-reference/pom.xml                      |   7 ++
 fit/core-reference/pom.xml                         |   4 +-
 .../core/reference/DateToDateItemTransformer.java  |   7 +-
 .../core/reference/DateToLongItemTransformer.java  |   2 +-
 .../src/main/resources/core-oracle.properties      |   2 +
 .../src/main/resources/core-postgres.properties    |   2 +-
 .../org/apache/syncope/fit/AbstractITCase.java     |  10 +-
 .../syncope/fit/core/AbstractTaskITCase.java       |   4 +-
 .../org/apache/syncope/fit/core/AuditITCase.java   |   8 +-
 .../org/apache/syncope/fit/core/BatchITCase.java   |   4 +-
 .../apache/syncope/fit/core/DelegationITCase.java  |  14 +--
 .../apache/syncope/fit/core/DynRealmITCase.java    |   2 +-
 .../org/apache/syncope/fit/core/GroupITCase.java   |   2 +-
 .../org/apache/syncope/fit/core/JWTITCase.java     |   7 +-
 .../syncope/fit/core/LinkedAccountITCase.java      |  10 +-
 .../syncope/fit/core/NotificationTaskITCase.java   |   4 +-
 .../org/apache/syncope/fit/core/OpenAPIITCase.java |   2 +-
 .../syncope/fit/core/PropagationTaskITCase.java    |  41 ++++---
 .../org/apache/syncope/fit/core/ReportITCase.java  |  12 +-
 .../org/apache/syncope/fit/core/SCIMITCase.java    |  25 ++---
 .../apache/syncope/fit/core/SchedTaskITCase.java   |  19 ++--
 .../org/apache/syncope/fit/core/SearchITCase.java  |  18 ++-
 .../org/apache/syncope/fit/core/UserITCase.java    |  23 ++--
 .../fit/core/wa/GoogleMfaAuthAccountITCase.java    |   4 +-
 .../fit/core/wa/GoogleMfaAuthTokenITCase.java      |  11 +-
 .../syncope/fit/core/wa/U2FRegistrationITCase.java |  17 ++-
 .../syncope/fit/enduser/AbstractEnduserITCase.java |  10 +-
 fit/enduser-reference/pom.xml                      |   7 ++
 fit/wa-reference/pom.xml                           |   2 +
 .../apache/syncope/fit/sra/AbstractSRAITCase.java  |  10 +-
 .../org/apache/syncope/fit/sra/OIDCSRAITCase.java  |   4 +-
 pom.xml                                            |   2 +-
 .../apache/syncope/sra/actuate/SRASessions.java    |  14 +--
 .../java/org/apache/syncope/sra/AbstractTest.java  |   4 +-
 .../syncope/sra/SyncopeCoreTestingServer.java      |   4 +-
 .../BodyPropertyAddingGatewayFilterFactory.java    |   8 +-
 src/main/asciidoc/getting-started/obtain.adoc      |   4 +-
 .../reference-guide/configuration/dbms.adoc        |   4 +-
 .../starter/audit/SyncopeWAAuditTrailManager.java  |  10 +-
 .../wa/starter/config/SyncopeWAConfiguration.java  |   6 +-
 .../starter/events/SyncopeWAEventRepository.java   |  18 +--
 ...SyncopeWAGoogleMfaAuthCredentialRepository.java |   6 +-
 .../SyncopeWAGoogleMfaAuthTokenRepository.java     |  48 +++-----
 .../starter/u2f/SyncopeWAU2FDeviceRepository.java  |  32 ++----
 .../wa/starter/SyncopeCoreTestingServer.java       |   7 +-
 .../SyncopeWAGoogleMfaAuthTokenRepositoryTest.java |   9 +-
 274 files changed, 1928 insertions(+), 2000 deletions(-)

diff --git a/archetype/src/main/resources/archetype-resources/fit/pom.xml b/archetype/src/main/resources/archetype-resources/fit/pom.xml
index 83c6528..520aa0a 100644
--- a/archetype/src/main/resources/archetype-resources/fit/pom.xml
+++ b/archetype/src/main/resources/archetype-resources/fit/pom.xml
@@ -219,6 +219,13 @@ under the License.
                 <artifactId>h2</artifactId>
               </dependency>
             </dependencies>
+
+            <systemProperties>
+              <java.security.egd>file:/dev/./urandom</java.security.egd>
+              <java.util.secureRandomSeed>true</java.util.secureRandomSeed>
+
+              <h2.returnOffsetDateTime>true</h2.returnOffsetDateTime>
+            </systemProperties>
           </container>
           <configuration>
             <properties>
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java
index 90b83d4..d0e1c2a 100644
--- a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.client.console.pages;
 
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
 import java.io.InputStream;
 import java.util.ArrayList;
@@ -62,7 +62,7 @@ public class WA extends BasePage {
 
     private static final long serialVersionUID = 9200112197134882164L;
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     @SpringBean
     private ServiceOps serviceOps;
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/OIDC.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/OIDC.java
index 0c5a9b7..85e6e64 100644
--- a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/OIDC.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/OIDC.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.panels;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
 import java.io.IOException;
 import java.util.concurrent.atomic.AtomicReference;
@@ -44,11 +44,11 @@ import org.slf4j.LoggerFactory;
 
 public class OIDC extends Panel {
 
-    private static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 12898029694947L;
 
     private static final Logger LOG = LoggerFactory.getLogger(OIDC.class);
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private final BaseModal<String> viewModal = new BaseModal<>("viewModal") {
 
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/AMSessionDeserializer.java b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/AMSessionDeserializer.java
index 3bd9c4c..4eec9ef 100644
--- a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/AMSessionDeserializer.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/AMSessionDeserializer.java
@@ -27,8 +27,9 @@ import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
 import java.io.IOException;
 import java.io.StringWriter;
-import java.text.ParseException;
-import org.apache.commons.lang3.time.DateFormatUtils;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
 import org.apache.syncope.common.lib.AMSession;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -59,8 +60,8 @@ public class AMSessionDeserializer extends StdDeserializer<AMSession> {
             String authenticationDate = node.get("authentication_date_formatted").textValue();
             try {
                 waSession.setAuthenticationDate(
-                        DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.parse(authenticationDate));
-            } catch (ParseException e) {
+                        OffsetDateTime.parse(authenticationDate, DateTimeFormatter.ISO_OFFSET_DATE_TIME));
+            } catch (DateTimeParseException e) {
                 LOG.error("Unparsable date: {}", authenticationDate, e);
             }
         }
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/AMSessionRestClient.java b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/AMSessionRestClient.java
index 8f36d03..9961719 100644
--- a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/AMSessionRestClient.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/AMSessionRestClient.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.rest;
 
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
 import java.util.List;
 import javax.ws.rs.core.MediaType;
@@ -38,7 +39,8 @@ public abstract class AMSessionRestClient implements RestClient {
 
     protected static final Logger LOG = LoggerFactory.getLogger(AMSessionRestClient.class);
 
-    protected static final List<?> JAX_RS_PROVIDERS = List.of(new JacksonJsonProvider());
+    protected static final List<?> JAX_RS_PROVIDERS =
+            List.of(new JacksonJsonProvider(JsonMapper.builder().findAndAddModules().build()));
 
     protected final List<NetworkService> instances;
 
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/SRAStatisticsRestClient.java b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/SRAStatisticsRestClient.java
index fc8ad7b..a16b6fd 100644
--- a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/SRAStatisticsRestClient.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/SRAStatisticsRestClient.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.rest;
 
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
 import java.util.List;
 import javax.ws.rs.core.MediaType;
@@ -33,7 +34,8 @@ public final class SRAStatisticsRestClient {
 
     private static final Logger LOG = LoggerFactory.getLogger(SRAStatisticsRestClient.class);
 
-    private static final List<?> JAX_RS_PROVIDERS = List.of(new JacksonJsonProvider());
+    private static final List<?> JAX_RS_PROVIDERS =
+            List.of(new JacksonJsonProvider(JsonMapper.builder().findAndAddModules().build()));
 
     private static String getActuatorEndpoint(final List<NetworkService> instances) {
         return instances.get(0).getAddress() + "actuator/metrics/spring.cloud.gateway.requests";
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WASessionRestClient.java b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WASessionRestClient.java
index fd166c4..48f80e9 100644
--- a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WASessionRestClient.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WASessionRestClient.java
@@ -20,7 +20,7 @@ package org.apache.syncope.client.console.rest;
 
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fasterxml.jackson.databind.module.SimpleModule;
 import java.io.InputStream;
 import java.util.List;
@@ -35,15 +35,8 @@ public final class WASessionRestClient extends AMSessionRestClient {
 
     private static final long serialVersionUID = 22118820292494L;
 
-    private static final ObjectMapper MAPPER;
-
-    static {
-        MAPPER = new ObjectMapper();
-
-        SimpleModule module = new SimpleModule();
-        module.addDeserializer(AMSession.class, new AMSessionDeserializer());
-        MAPPER.registerModule(module);
-    }
+    private static final JsonMapper MAPPER = JsonMapper.builder().
+            addModule(new SimpleModule().addDeserializer(AMSession.class, new AMSessionDeserializer())).build();
 
     public WASessionRestClient(final List<NetworkService> instances) {
         super(instances);
@@ -66,9 +59,8 @@ public final class WASessionRestClient extends AMSessionRestClient {
             if (response.getStatus() == Response.Status.OK.getStatusCode()) {
                 JsonNode node = MAPPER.readTree((InputStream) response.getEntity());
                 if (node.has("activeSsoSessions")) {
-                    return MAPPER.readValue(MAPPER.treeAsTokens(node.get("activeSsoSessions")),
-                        new TypeReference<>() {
-                        });
+                    return MAPPER.readValue(MAPPER.treeAsTokens(node.get("activeSsoSessions")), new TypeReference<>() {
+                    });
                 }
             } else {
                 LOG.error("Unexpected response for SSO Sessions from {}: {}",
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/VirSchemaDetails.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/VirSchemaDetails.java
index 0718e71..2cfed81 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/VirSchemaDetails.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/VirSchemaDetails.java
@@ -56,7 +56,7 @@ public class VirSchemaDetails extends AbstractSchemaDetailsPanel {
                 new PropertyModel<>(schemaTO, "readonly"));
         add(readonly);
 
-        final AjaxDropDownChoicePanel<String> resource = new AjaxDropDownChoicePanel<>(
+        AjaxDropDownChoicePanel<String> resource = new AjaxDropDownChoicePanel<>(
                 "resource", getString("resource"), new PropertyModel<String>(schemaTO, "resource"), false).
                 setNullValid(false);
         resource.setChoices(ResourceRestClient.list().stream().map(EntityTO::getKey).collect(Collectors.toList()));
@@ -79,7 +79,7 @@ public class VirSchemaDetails extends AbstractSchemaDetailsPanel {
         }
         add(anyType);
 
-        final AjaxTextFieldPanel extAttrName = new AjaxTextFieldPanel(
+        AjaxTextFieldPanel extAttrName = new AjaxTextFieldPanel(
                 "extAttrName", getString("extAttrName"), new PropertyModel<>(schemaTO, "extAttrName"));
         extAttrName.setOutputMarkupId(true);
         extAttrName.addRequiredLabel();
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.java
index 07ddf96..f5db9e5 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.policies;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -68,7 +68,7 @@ public class ProvisioningPolicyModalPanel extends AbstractModalPanel<Provisionin
 
     private static final long serialVersionUID = 2988891313881271124L;
 
-    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private final IModel<Map<String, ImplementationTO>> implementations;
 
@@ -90,9 +90,9 @@ public class ProvisioningPolicyModalPanel extends AbstractModalPanel<Provisionin
             @Override
             protected Map<String, ImplementationTO> load() {
                 return ImplementationRestClient.list(policyTO instanceof PullPolicyTO
-                    ? IdMImplementationType.PULL_CORRELATION_RULE
-                    : IdMImplementationType.PUSH_CORRELATION_RULE).stream().
-                    collect(Collectors.toMap(EntityTO::getKey, Function.identity()));
+                        ? IdMImplementationType.PULL_CORRELATION_RULE
+                        : IdMImplementationType.PUSH_CORRELATION_RULE).stream().
+                        collect(Collectors.toMap(EntityTO::getKey, Function.identity()));
             }
         };
 
@@ -101,13 +101,13 @@ public class ProvisioningPolicyModalPanel extends AbstractModalPanel<Provisionin
             private static final long serialVersionUID = -8168676563540297301L;
 
             private final List<CorrelationRule> rules = policyTO.getCorrelationRules().keySet().stream().
-                map(anyType -> new CorrelationRule(
+                    map(anyType -> new CorrelationRule(
                     policyTO instanceof PullPolicyTO
-                        ? DefaultPullCorrelationRuleConf.class
-                        : DefaultPushCorrelationRuleConf.class,
+                            ? DefaultPullCorrelationRuleConf.class
+                            : DefaultPushCorrelationRuleConf.class,
                     anyType,
                     implementations.getObject().get(policyTO.getCorrelationRules().get(anyType)))).
-                collect(Collectors.toList());
+                    collect(Collectors.toList());
 
             @Override
             public List<CorrelationRule> getObject() {
@@ -128,8 +128,8 @@ public class ProvisioningPolicyModalPanel extends AbstractModalPanel<Provisionin
             @Override
             protected CorrelationRule newModelObject() {
                 return new CorrelationRule(policyTO instanceof PullPolicyTO
-                    ? DefaultPullCorrelationRuleConf.class
-                    : DefaultPushCorrelationRuleConf.class);
+                        ? DefaultPullCorrelationRuleConf.class
+                        : DefaultPushCorrelationRuleConf.class);
             }
 
             @Override
@@ -196,76 +196,76 @@ public class ProvisioningPolicyModalPanel extends AbstractModalPanel<Provisionin
             add(rule);
 
             PropertyModel<Boolean> orSchemasModel =
-                new PropertyModel<>(correlationRule.getObject().getDefaultRuleConf(), "orSchemas") {
+                    new PropertyModel<>(correlationRule.getObject().getDefaultRuleConf(), "orSchemas") {
 
-                    private static final long serialVersionUID = 807008909842554829L;
+                private static final long serialVersionUID = 807008909842554829L;
 
-                    @Override
-                    public Boolean getObject() {
-                        AbstractCorrelationRuleConf conf = correlationRule.getObject().getDefaultRuleConf();
-                        return conf instanceof DefaultPullCorrelationRuleConf
+                @Override
+                public Boolean getObject() {
+                    AbstractCorrelationRuleConf conf = correlationRule.getObject().getDefaultRuleConf();
+                    return conf instanceof DefaultPullCorrelationRuleConf
                             ? DefaultPullCorrelationRuleConf.class.cast(conf).isOrSchemas()
                             : conf instanceof DefaultPushCorrelationRuleConf
-                            ? DefaultPushCorrelationRuleConf.class.cast(conf).isOrSchemas()
-                            : false;
-                    }
+                                    ? DefaultPushCorrelationRuleConf.class.cast(conf).isOrSchemas()
+                                    : false;
+                }
 
-                    @Override
-                    public void setObject(final Boolean object) {
-                        AbstractCorrelationRuleConf conf = correlationRule.getObject().getDefaultRuleConf();
-                        if (conf instanceof DefaultPullCorrelationRuleConf) {
-                            DefaultPullCorrelationRuleConf.class.cast(conf).setOrSchemas(object);
-                        } else if (conf instanceof DefaultPushCorrelationRuleConf) {
-                            DefaultPushCorrelationRuleConf.class.cast(conf).setOrSchemas(object);
-                        }
+                @Override
+                public void setObject(final Boolean object) {
+                    AbstractCorrelationRuleConf conf = correlationRule.getObject().getDefaultRuleConf();
+                    if (conf instanceof DefaultPullCorrelationRuleConf) {
+                        DefaultPullCorrelationRuleConf.class.cast(conf).setOrSchemas(object);
+                    } else if (conf instanceof DefaultPushCorrelationRuleConf) {
+                        DefaultPushCorrelationRuleConf.class.cast(conf).setOrSchemas(object);
                     }
-                };
+                }
+            };
             AjaxCheckBoxPanel orSchemas = new AjaxCheckBoxPanel("orSchemas", "orSchemas", orSchemasModel, false);
             orSchemas.setOutputMarkupPlaceholderTag(true);
             add(orSchemas.setVisible(correlationRule.getObject().getDefaultRuleConf() != null));
 
             PropertyModel<List<String>> defaultRuleConfModel =
-                new PropertyModel<>(correlationRule.getObject().getDefaultRuleConf(), "schemas") {
+                    new PropertyModel<>(correlationRule.getObject().getDefaultRuleConf(), "schemas") {
 
-                    private static final long serialVersionUID = 3799387950428254072L;
+                private static final long serialVersionUID = 3799387950428254072L;
 
-                    private List<String> schemas() {
-                        AbstractCorrelationRuleConf conf = correlationRule.getObject().getDefaultRuleConf();
-                        return conf instanceof DefaultPullCorrelationRuleConf
+                private List<String> schemas() {
+                    AbstractCorrelationRuleConf conf = correlationRule.getObject().getDefaultRuleConf();
+                    return conf instanceof DefaultPullCorrelationRuleConf
                             ? DefaultPullCorrelationRuleConf.class.cast(conf).getSchemas()
                             : conf instanceof DefaultPushCorrelationRuleConf
-                            ? DefaultPushCorrelationRuleConf.class.cast(conf).getSchemas()
-                            : List.of();
-                    }
+                                    ? DefaultPushCorrelationRuleConf.class.cast(conf).getSchemas()
+                                    : List.of();
+                }
 
-                    @Override
-                    public List<String> getObject() {
-                        List<String> schemas = new ArrayList<>();
-                        if (correlationRule.getObject().getDefaultRuleConf() != null) {
-                            schemas.addAll(schemas());
-                        }
-                        return schemas;
+                @Override
+                public List<String> getObject() {
+                    List<String> schemas = new ArrayList<>();
+                    if (correlationRule.getObject().getDefaultRuleConf() != null) {
+                        schemas.addAll(schemas());
                     }
+                    return schemas;
+                }
 
-                    @Override
-                    public void setObject(final List<String> object) {
-                        if (correlationRule.getObject().getDefaultRuleConf() != null) {
-                            schemas().clear();
-                            schemas().addAll(object);
-                        }
+                @Override
+                public void setObject(final List<String> object) {
+                    if (correlationRule.getObject().getDefaultRuleConf() != null) {
+                        schemas().clear();
+                        schemas().addAll(object);
                     }
-                };
+                }
+            };
             AjaxPalettePanel<String> defaultRuleConf = new AjaxPalettePanel.Builder<String>().
                     setName("defaultRuleConf").build("defaultRuleConf",
                     defaultRuleConfModel, new AjaxPalettePanel.Builder.Query<>() {
 
-                    private static final long serialVersionUID = -7223078772249308813L;
+                private static final long serialVersionUID = -7223078772249308813L;
 
-                    @Override
-                    public List<String> execute(final String filter) {
-                        return getSchemas(correlationRule.getObject());
-                    }
-                });
+                @Override
+                public List<String> execute(final String filter) {
+                    return getSchemas(correlationRule.getObject());
+                }
+            });
             defaultRuleConf.hideLabel().setOutputMarkupPlaceholderTag(true);
             add(defaultRuleConf.setVisible(correlationRule.getObject().getDefaultRuleConf() != null));
 
@@ -371,7 +371,7 @@ public class ProvisioningPolicyModalPanel extends AbstractModalPanel<Provisionin
             if (impl != null) {
                 this.defaultRuleConf = null;
                 try {
-                    this.defaultRuleConf = OBJECT_MAPPER.readValue(impl.getBody(), ruleConfClass);
+                    this.defaultRuleConf = MAPPER.readValue(impl.getBody(), ruleConfClass);
                 } catch (Exception e) {
                     LOG.debug("Could not deserialize {} as {}", impl.getBody(), ruleConfClass.getName());
                 }
@@ -381,7 +381,7 @@ public class ProvisioningPolicyModalPanel extends AbstractModalPanel<Provisionin
         public ImplementationTO getImpl() {
             if (defaultRuleConf != null) {
                 try {
-                    this.impl.setBody(OBJECT_MAPPER.writeValueAsString(defaultRuleConf));
+                    this.impl.setBody(MAPPER.writeValueAsString(defaultRuleConf));
                 } catch (Exception e) {
                     LOG.error("Could not serialize {}", defaultRuleConf);
                 }
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
index 3fc6894..a50537a 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.topology;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
 import java.io.Serializable;
 import java.text.MessageFormat;
@@ -71,7 +71,7 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
 
     private static final long serialVersionUID = -2025535531121434056L;
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private final WebMarkupContainer container;
 
@@ -230,7 +230,7 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
                 modal.setFormModel(model);
 
                 target.add(modal.setContent(new ConnectorWizardBuilder(modelObject, pageRef).
-                    build(BaseModal.CONTENT_ID, AjaxWizard.Mode.CREATE)));
+                        build(BaseModal.CONTENT_ID, AjaxWizard.Mode.CREATE)));
 
                 modal.header(new Model<>(MessageFormat.format(getString("connector.new"), node.getKey())));
                 modal.show(true);
@@ -285,7 +285,7 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
                 modal.setFormModel(model);
 
                 target.add(modal.setContent(new ResourceWizardBuilder(modelObject, pageRef).
-                    build(BaseModal.CONTENT_ID, AjaxWizard.Mode.CREATE)));
+                        build(BaseModal.CONTENT_ID, AjaxWizard.Mode.CREATE)));
 
                 modal.header(new Model<>(MessageFormat.format(getString("resource.new"), node.getKey())));
                 modal.show(true);
@@ -312,14 +312,14 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
                 modal.setFormModel(model);
 
                 target.add(modal.setContent(new ConnectorWizardBuilder(connInstance, pageRef).
-                    build(BaseModal.CONTENT_ID,
-                        SyncopeConsoleSession.get().
-                            owns(IdMEntitlement.CONNECTOR_UPDATE, connInstance.getAdminRealm())
-                            ? AjaxWizard.Mode.EDIT
-                            : AjaxWizard.Mode.READONLY)));
+                        build(BaseModal.CONTENT_ID,
+                                SyncopeConsoleSession.get().
+                                        owns(IdMEntitlement.CONNECTOR_UPDATE, connInstance.getAdminRealm())
+                                ? AjaxWizard.Mode.EDIT
+                                : AjaxWizard.Mode.READONLY)));
 
                 modal.header(
-                    new Model<>(MessageFormat.format(getString("connector.edit"), connInstance.getDisplayName())));
+                        new Model<>(MessageFormat.format(getString("connector.edit"), connInstance.getDisplayName())));
                 modal.show(true);
             }
 
@@ -340,12 +340,12 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
                 ConnInstanceTO modelObject = ConnectorRestClient.read(node.getKey());
 
                 target.add(historyModal.setContent(new AuditHistoryModal<>(
-                    historyModal,
-                    AuditElements.EventCategoryType.LOGIC,
-                    "ConnectorLogic",
-                    modelObject,
-                    IdMEntitlement.CONNECTOR_UPDATE,
-                    pageRef) {
+                        historyModal,
+                        AuditElements.EventCategoryType.LOGIC,
+                        "ConnectorLogic",
+                        modelObject,
+                        IdMEntitlement.CONNECTOR_UPDATE,
+                        pageRef) {
 
                     private static final long serialVersionUID = -3225348282675513648L;
 
@@ -366,7 +366,7 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
                 }));
 
                 historyModal.header(
-                    new Model<>(MessageFormat.format(getString("connector.menu.history"), node.getDisplayName())));
+                        new Model<>(MessageFormat.format(getString("connector.menu.history"), node.getDisplayName())));
 
                 historyModal.show(true);
             }
@@ -420,11 +420,11 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
                 modal.setFormModel(model);
 
                 target.add(modal.setContent(new ResourceWizardBuilder(resource, pageRef).
-                    build(BaseModal.CONTENT_ID,
-                        SyncopeConsoleSession.get().
-                            owns(IdMEntitlement.RESOURCE_UPDATE, connInstance.getAdminRealm())
-                            ? AjaxWizard.Mode.EDIT
-                            : AjaxWizard.Mode.READONLY)));
+                        build(BaseModal.CONTENT_ID,
+                                SyncopeConsoleSession.get().
+                                        owns(IdMEntitlement.RESOURCE_UPDATE, connInstance.getAdminRealm())
+                                ? AjaxWizard.Mode.EDIT
+                                : AjaxWizard.Mode.READONLY)));
 
                 modal.header(new Model<>(MessageFormat.format(getString("resource.edit"), node.getKey())));
                 modal.show(true);
@@ -446,9 +446,9 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
             public void onClick(final AjaxRequestTarget target) {
                 ResourceTO modelObject = ResourceRestClient.read(node.getKey());
                 target.add(propTaskModal.setContent(
-                    new ResourceStatusModal(propTaskModal, pageRef, modelObject)));
+                        new ResourceStatusModal(propTaskModal, pageRef, modelObject)));
                 propTaskModal.header(
-                    new Model<>(MessageFormat.format(getString("resource.reconciliation"), node.getKey())));
+                        new Model<>(MessageFormat.format(getString("resource.reconciliation"), node.getKey())));
                 propTaskModal.show(true);
             }
 
@@ -470,7 +470,7 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
                 ConnInstanceTO connInstance = ConnectorRestClient.read(resource.getConnector());
 
                 if (SyncopeConsoleSession.get().
-                    owns(IdMEntitlement.RESOURCE_UPDATE, connInstance.getAdminRealm())) {
+                        owns(IdMEntitlement.RESOURCE_UPDATE, connInstance.getAdminRealm())) {
 
                     provisionModal.addSubmitButton();
                 } else {
@@ -481,7 +481,7 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
                 provisionModal.setFormModel(model);
 
                 target.add(provisionModal.setContent(
-                    new ResourceProvisionPanel(provisionModal, resource, connInstance.getAdminRealm(), pageRef)));
+                        new ResourceProvisionPanel(provisionModal, resource, connInstance.getAdminRealm(), pageRef)));
 
                 provisionModal.header(new Model<>(MessageFormat.format(getString("resource.edit"), node.getKey())));
                 provisionModal.show(true);
@@ -524,9 +524,9 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
             @SuppressWarnings("unchecked")
             public void onClick(final AjaxRequestTarget target) {
                 target.add(propTaskModal.setContent(
-                    new PropagationTasks(propTaskModal, node.getKey(), pageRef)));
+                        new PropagationTasks(propTaskModal, node.getKey(), pageRef)));
                 propTaskModal.header(
-                    new Model<>(MessageFormat.format(getString("task.propagation.list"), node.getKey())));
+                        new Model<>(MessageFormat.format(getString("task.propagation.list"), node.getKey())));
                 propTaskModal.show(true);
             }
 
@@ -585,12 +585,12 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
                 ResourceTO modelObject = ResourceRestClient.read(node.getKey());
 
                 target.add(historyModal.setContent(new AuditHistoryModal<>(
-                    historyModal,
-                    AuditElements.EventCategoryType.LOGIC,
-                    "ResourceLogic",
-                    modelObject,
-                    IdMEntitlement.RESOURCE_UPDATE,
-                    pageRef) {
+                        historyModal,
+                        AuditElements.EventCategoryType.LOGIC,
+                        "ResourceLogic",
+                        modelObject,
+                        IdMEntitlement.RESOURCE_UPDATE,
+                        pageRef) {
 
                     private static final long serialVersionUID = -3712506022627033811L;
 
@@ -611,7 +611,7 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
                 }));
 
                 historyModal.header(
-                    new Model<>(MessageFormat.format(getString("resource.menu.history"), node.getDisplayName())));
+                        new Model<>(MessageFormat.format(getString("resource.menu.history"), node.getDisplayName())));
 
                 historyModal.show(true);
             }
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/topology/TopologyWebSocketBehavior.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/topology/TopologyWebSocketBehavior.java
index af58261..64c9637 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/topology/TopologyWebSocketBehavior.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/topology/TopologyWebSocketBehavior.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.client.console.topology;
 
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
@@ -49,7 +49,7 @@ public class TopologyWebSocketBehavior extends WebSocketBehavior {
 
     private static final Logger LOG = LoggerFactory.getLogger(TopologyWebSocketBehavior.class);
 
-    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private static final String CONNECTOR_TEST_TIMEOUT_PARAMETER = "connector.test.timeout";
 
@@ -129,7 +129,7 @@ public class TopologyWebSocketBehavior extends WebSocketBehavior {
     @Override
     protected void onMessage(final WebSocketRequestHandler handler, final TextMessage message) {
         try {
-            JsonNode obj = OBJECT_MAPPER.readTree(message.getText());
+            JsonNode obj = MAPPER.readTree(message.getText());
             switch (Topology.SupportedOperation.valueOf(obj.get("kind").asText())) {
                 case CHECK_CONNECTOR:
                     String ckey = obj.get("target").asText();
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/any/MergeLinkedAccountsWizardBuilder.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/any/MergeLinkedAccountsWizardBuilder.java
index 408e5ea..7f3e4a7 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/any/MergeLinkedAccountsWizardBuilder.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/any/MergeLinkedAccountsWizardBuilder.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.util.List;
 import java.util.HashMap;
 import java.util.Map;
@@ -55,7 +55,7 @@ public class MergeLinkedAccountsWizardBuilder extends BaseAjaxWizardBuilder<User
 
     private static final long serialVersionUID = -9142332740863374891L;
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private final UserDirectoryPanel parentPanel;
 
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/BaseSession.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/BaseSession.java
index 589b8b8..acd67b4 100644
--- a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/BaseSession.java
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/BaseSession.java
@@ -20,7 +20,6 @@ package org.apache.syncope.client.ui.commons;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.Future;
-import org.apache.commons.lang3.time.FastDateFormat;
 import org.apache.syncope.client.lib.SyncopeClient;
 
 public interface BaseSession {
@@ -64,7 +63,7 @@ public interface BaseSession {
 
     <T> void resetClient(Class<T> service);
 
-    FastDateFormat getDateFormat();
+    DateOps.Format getDateFormat();
 
     /**
      * Extract and localize (if translation available) the actual message from the given exception; then, report it
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/DateOps.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/DateOps.java
new file mode 100644
index 0000000..f68187b
--- /dev/null
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/DateOps.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.ui.commons;
+
+import java.io.Serializable;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.util.Date;
+import java.util.Optional;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.FastDateFormat;
+import org.apache.wicket.model.IModel;
+
+public final class DateOps {
+
+    public static class Format implements Serializable {
+
+        private static final long serialVersionUID = 27103019852866L;
+
+        private final FastDateFormat fdf;
+
+        public Format(final FastDateFormat fdf) {
+            this.fdf = fdf;
+        }
+
+        public String format(final Date date) {
+            return Optional.ofNullable(date).map(fdf::format).orElse(StringUtils.EMPTY);
+        }
+
+        public String format(final OffsetDateTime date) {
+            return Optional.ofNullable(date).map(v -> fdf.format(convert(date))).orElse(StringUtils.EMPTY);
+        }
+    }
+
+    public static class WrappedDateModel implements IModel<Date>, Serializable {
+
+        private static final long serialVersionUID = 31027882183172L;
+
+        private final IModel<OffsetDateTime> wrapped;
+
+        public WrappedDateModel(final IModel<OffsetDateTime> wrapped) {
+            this.wrapped = wrapped;
+        }
+
+        @Override
+        public Date getObject() {
+            return convert(wrapped.getObject());
+        }
+
+        @Override
+        public void setObject(final Date object) {
+            wrapped.setObject(convert(object));
+        }
+    }
+
+    public static final ZoneOffset DEFAULT_OFFSET = OffsetDateTime.now().getOffset();
+
+    public static Date convert(final OffsetDateTime date) {
+        return Optional.ofNullable(date).map(v -> new Date(v.toInstant().toEpochMilli())).orElse(null);
+    }
+
+    public static OffsetDateTime convert(final Date date) {
+        return Optional.ofNullable(date).map(v -> v.toInstant().atOffset(DEFAULT_OFFSET)).orElse(null);
+    }
+
+    private DateOps() {
+        // private constructor for static utility class
+    }
+}
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/MIMETypesLoader.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/MIMETypesLoader.java
index 34d1df5..fc825ee 100644
--- a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/MIMETypesLoader.java
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/MIMETypesLoader.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.client.ui.commons;
 
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -33,7 +33,7 @@ public class MIMETypesLoader {
 
     protected static final Logger LOG = LoggerFactory.getLogger(MIMETypesLoader.class);
 
-    protected static final ObjectMapper MAPPER = new ObjectMapper();
+    protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     protected Map<String, String> mimeTypesMap;
 
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxDateFieldPanel.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxDateFieldPanel.java
index ee9815d..7804952 100644
--- a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxDateFieldPanel.java
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxDateFieldPanel.java
@@ -30,10 +30,11 @@ public class AjaxDateFieldPanel extends DateFieldPanel {
     private static final long serialVersionUID = 1919852712185883648L;
 
     public AjaxDateFieldPanel(
-            final String id, 
-            final String name, 
+            final String id,
+            final String name,
             final IModel<Date> model,
             final FastDateFormat datePattern) {
+
         super(id, name, model, datePattern);
 
         field = new AjaxDatePicker("field", model, getLocale(), datePattern.getPattern());
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/DateFieldPanel.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/DateFieldPanel.java
index 0fc4207..73e5cd9 100644
--- a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/DateFieldPanel.java
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/DateFieldPanel.java
@@ -154,7 +154,6 @@ public abstract class DateFieldPanel extends FieldPanel<Date> {
     @Override
     public void renderHead(final IHeaderResponse response) {
         super.renderHead(response);
-        response.render(JavaScriptHeaderItem.forReference(
-                new KendoCultureResourceReference(getLocale())));
+        response.render(JavaScriptHeaderItem.forReference(new KendoCultureResourceReference(getLocale())));
     }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/PreferenceManager.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/PreferenceManager.java
index 6d66bc5..907339d 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/PreferenceManager.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/PreferenceManager.java
@@ -18,8 +18,8 @@
  */
 package org.apache.syncope.client.console;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.IOException;
 import java.io.Serializable;
 import java.io.StringWriter;
@@ -46,7 +46,7 @@ public final class PreferenceManager implements Serializable {
 
     private static final int ONE_YEAR_TIME = 60 * 60 * 24 * 365;
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private static final TypeReference<Map<String, String>> MAP_TYPE_REF = new TypeReference<>() {
     };
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
index 4633004..35045f0 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
@@ -48,6 +48,7 @@ import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
 import org.apache.syncope.client.lib.batch.BatchRequest;
 import org.apache.syncope.client.ui.commons.BaseSession;
 import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.DateOps;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.info.PlatformInfo;
@@ -425,7 +426,7 @@ public class SyncopeConsoleSession extends AuthenticatedWebSession implements Ba
     }
 
     @Override
-    public FastDateFormat getDateFormat() {
-        return FastDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, getLocale());
+    public DateOps.Format getDateFormat() {
+        return new DateOps.Format(FastDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, getLocale()));
     }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
index 937279c..c550937 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
@@ -30,7 +30,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.fasterxml.jackson.databind.ser.std.StdSerializer;
 import java.io.IOException;
 import java.io.Serializable;
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeMap;
@@ -134,7 +134,7 @@ public abstract class AuditHistoryDetails<T extends Serializable> extends Multil
             current.setDate(((AnyTO) currentEntity).getCreationDate());
         } else {
             current.setWho(SyncopeConsoleSession.get().getSelfTO().getUsername());
-            current.setDate(new Date());
+            current.setDate(OffsetDateTime.now());
         }
         try {
             current.setBefore(MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(currentEntity));
@@ -166,8 +166,8 @@ public abstract class AuditHistoryDetails<T extends Serializable> extends Multil
             public void onClick(final AjaxRequestTarget target) {
                 try {
                     String json = selected.getBefore() == null
-                        ? MAPPER.readTree(selected.getOutput()).get("entity").toPrettyString()
-                        : selected.getBefore();
+                            ? MAPPER.readTree(selected.getOutput()).get("entity").toPrettyString()
+                            : selected.getBefore();
                     restore(json, target);
 
                     mlp.prev(target);
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/batch/BatchContent.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/batch/BatchContent.java
index 9f20b2a..c30b89c 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/batch/BatchContent.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/batch/BatchContent.java
@@ -56,7 +56,7 @@ import org.apache.syncope.common.lib.types.ResourceAssociationAction;
 import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
 import org.apache.syncope.common.lib.types.StatusRType;
 import org.apache.syncope.common.lib.types.TaskType;
-import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
+import org.apache.syncope.common.rest.api.beans.ExecSpecs;
 import org.apache.syncope.common.rest.api.service.AnyObjectService;
 import org.apache.syncope.common.rest.api.service.AnyService;
 import org.apache.syncope.common.rest.api.service.GroupService;
@@ -137,7 +137,7 @@ public class BatchContent<T extends Serializable, S> extends MultilevelPanel.Sec
 
                                 try {
                                     batchExecutor.getClass().getMethod("deleteExecution", String.class).
-                                        invoke(batchExecutor, exec.getKey());
+                                            invoke(batchExecutor, exec.getKey());
                                     results.put(exec.getKey(), ExecStatus.SUCCESS.name());
                                 } catch (Exception e) {
                                     LOG.error("Error deleting execution {}", exec.getKey(), e);
@@ -150,16 +150,16 @@ public class BatchContent<T extends Serializable, S> extends MultilevelPanel.Sec
                             // Group bean information by anyKey
                             Map<String, List<StatusBean>> beans = new HashMap<>();
                             items.stream().map(StatusBean.class::cast).
-                                forEachOrdered(sb -> {
-                                    final List<StatusBean> sblist;
-                                    if (beans.containsKey(sb.getKey())) {
-                                        sblist = beans.get(sb.getKey());
-                                    } else {
-                                        sblist = new ArrayList<>();
-                                        beans.put(sb.getKey(), sblist);
-                                    }
-                                    sblist.add(sb);
-                                });
+                                    forEachOrdered(sb -> {
+                                        final List<StatusBean> sblist;
+                                        if (beans.containsKey(sb.getKey())) {
+                                            sblist = beans.get(sb.getKey());
+                                        } else {
+                                            sblist = new ArrayList<>();
+                                            beans.put(sb.getKey(), sblist);
+                                        }
+                                        sblist.add(sb);
+                                    });
 
                             results = new HashMap<>();
                             beans.forEach((key, value) -> {
@@ -168,32 +168,32 @@ public class BatchContent<T extends Serializable, S> extends MultilevelPanel.Sec
                                 switch (action) {
                                     case DEPROVISION:
                                         results.putAll(anyRestClient.deassociate(
-                                            ResourceDeassociationAction.DEPROVISION, etag, key, value));
+                                                ResourceDeassociationAction.DEPROVISION, etag, key, value));
                                         break;
 
                                     case UNASSIGN:
                                         results.putAll(anyRestClient.deassociate(
-                                            ResourceDeassociationAction.UNASSIGN, etag, key, value));
+                                                ResourceDeassociationAction.UNASSIGN, etag, key, value));
                                         break;
 
                                     case UNLINK:
                                         results.putAll(anyRestClient.deassociate(
-                                            ResourceDeassociationAction.UNLINK, etag, key, value));
+                                                ResourceDeassociationAction.UNLINK, etag, key, value));
                                         break;
 
                                     case ASSIGN:
                                         results.putAll(anyRestClient.associate(
-                                            ResourceAssociationAction.ASSIGN, etag, key, value));
+                                                ResourceAssociationAction.ASSIGN, etag, key, value));
                                         break;
 
                                     case LINK:
                                         results.putAll(anyRestClient.associate(
-                                            ResourceAssociationAction.LINK, etag, key, value));
+                                                ResourceAssociationAction.LINK, etag, key, value));
                                         break;
 
                                     case PROVISION:
                                         results.putAll(anyRestClient.associate(
-                                            ResourceAssociationAction.PROVISION, etag, key, value));
+                                                ResourceAssociationAction.PROVISION, etag, key, value));
                                         break;
 
                                     case SUSPEND:
@@ -214,10 +214,10 @@ public class BatchContent<T extends Serializable, S> extends MultilevelPanel.Sec
                             GroupService batchGroupService = batch.getService(GroupService.class);
                             AnyObjectService batchAnyObjectService = batch.getService(AnyObjectService.class);
                             AnyService<?> batchAnyService = singleItem instanceof UserTO
-                                ? batchUserService
-                                : singleItem instanceof GroupTO
-                                ? batchGroupService
-                                : batchAnyObjectService;
+                                    ? batchUserService
+                                    : singleItem instanceof GroupTO
+                                            ? batchGroupService
+                                            : batchAnyObjectService;
                             TaskService batchTaskService = batch.getService(TaskService.class);
                             ReportService batchReportService = batch.getService(ReportService.class);
 
@@ -231,7 +231,7 @@ public class BatchContent<T extends Serializable, S> extends MultilevelPanel.Sec
                                         UserUR req = new UserUR();
                                         req.setKey(user.getKey());
                                         req.setMustChangePassword(new BooleanReplacePatchItem.Builder().
-                                            value(!user.isMustChangePassword()).build());
+                                                value(!user.isMustChangePassword()).build());
 
                                         batchUserService.update(req);
                                     });
@@ -242,11 +242,11 @@ public class BatchContent<T extends Serializable, S> extends MultilevelPanel.Sec
                                         UserTO user = (UserTO) item;
 
                                         StatusR req = new StatusR.Builder().
-                                            key(user.getKey()).
-                                            type(StatusRType.SUSPEND).
-                                            onSyncope(true).
-                                            resources(user.getResources()).
-                                            build();
+                                                key(user.getKey()).
+                                                type(StatusRType.SUSPEND).
+                                                onSyncope(true).
+                                                resources(user.getResources()).
+                                                build();
 
                                         batchUserService.status(req);
                                     });
@@ -257,11 +257,11 @@ public class BatchContent<T extends Serializable, S> extends MultilevelPanel.Sec
                                         UserTO user = (UserTO) item;
 
                                         StatusR req = new StatusR.Builder().
-                                            key(user.getKey()).
-                                            type(StatusRType.REACTIVATE).
-                                            onSyncope(true).
-                                            resources(user.getResources()).
-                                            build();
+                                                key(user.getKey()).
+                                                type(StatusRType.REACTIVATE).
+                                                onSyncope(true).
+                                                resources(user.getResources()).
+                                                build();
 
                                         batchUserService.status(req);
                                     });
@@ -278,8 +278,8 @@ public class BatchContent<T extends Serializable, S> extends MultilevelPanel.Sec
                                             TaskTO task = (TaskTO) item;
 
                                             batchTaskService.delete(
-                                                TaskType.fromTOClass(task.getClass()),
-                                                task.getKey());
+                                                    TaskType.fromTOClass(task.getClass()),
+                                                    task.getKey());
                                         } else if (singleItem instanceof ReportTO) {
                                             ReportTO report = (ReportTO) item;
 
@@ -296,7 +296,7 @@ public class BatchContent<T extends Serializable, S> extends MultilevelPanel.Sec
                                         TaskTO task = (TaskTO) item;
 
                                         batchTaskService.execute(
-                                            new ExecuteQuery.Builder().dryRun(true).key(task.getKey()).build());
+                                                new ExecSpecs.Builder().dryRun(true).key(task.getKey()).build());
                                     });
                                     break;
 
@@ -305,13 +305,13 @@ public class BatchContent<T extends Serializable, S> extends MultilevelPanel.Sec
                                         if (singleItem instanceof TaskTO) {
                                             TaskTO task = (TaskTO) item;
 
-                                            batchTaskService.execute(new ExecuteQuery.Builder().
-                                                dryRun(false).key(task.getKey()).build());
+                                            batchTaskService.execute(
+                                                    new ExecSpecs.Builder().dryRun(false).key(task.getKey()).build());
                                         } else if (singleItem instanceof ReportTO) {
                                             ReportTO report = (ReportTO) item;
 
-                                            batchReportService.execute(new ExecuteQuery.Builder().
-                                                key(report.getKey()).build());
+                                            batchReportService.execute(
+                                                    new ExecSpecs.Builder().key(report.getKey()).build());
                                         }
                                     });
                                     break;
@@ -320,15 +320,15 @@ public class BatchContent<T extends Serializable, S> extends MultilevelPanel.Sec
                             }
 
                             results = CastUtils.cast(Map.class.cast(
-                                batchExecutor.getClass().getMethod("batch",
-                                    BatchRequest.class).invoke(batchExecutor, batch)));
+                                    batchExecutor.getClass().getMethod("batch",
+                                            BatchRequest.class).invoke(batchExecutor, batch)));
 
                             if (singleItem instanceof AnyTO) {
                                 AbstractAnyRestClient<? extends AnyTO> anyRestClient = singleItem instanceof UserTO
-                                    ? UserRestClient.class.cast(batchExecutor)
-                                    : singleItem instanceof GroupTO
-                                    ? GroupRestClient.class.cast(batchExecutor)
-                                    : AnyObjectRestClient.class.cast(batchExecutor);
+                                        ? UserRestClient.class.cast(batchExecutor)
+                                        : singleItem instanceof GroupTO
+                                                ? GroupRestClient.class.cast(batchExecutor)
+                                                : AnyObjectRestClient.class.cast(batchExecutor);
                                 for (int i = 0; i < items.size(); i++) {
                                     String key = ((AnyTO) items.get(i)).getKey();
                                     if (!deletedAnys.contains(key)) {
@@ -342,10 +342,10 @@ public class BatchContent<T extends Serializable, S> extends MultilevelPanel.Sec
                         newColumnList.add(newColumnList.size(), new BatchResponseColumn<>(results, keyFieldName));
 
                         container.addOrReplace(new AjaxFallbackDefaultDataTable<>(
-                            "selectedObjects",
-                            newColumnList,
-                            dataProvider,
-                            Integer.MAX_VALUE).setVisible(!items.isEmpty()));
+                                "selectedObjects",
+                                newColumnList,
+                                dataProvider,
+                                Integer.MAX_VALUE).setVisible(!items.isEmpty()));
 
                         actionPanel.setEnabled(false);
                         actionPanel.setVisible(false);
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/chartjs/ChartJSPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/chartjs/ChartJSPanel.java
index e751a16..eba2768 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/chartjs/ChartJSPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/chartjs/ChartJSPanel.java
@@ -20,7 +20,7 @@ package org.apache.syncope.client.console.chartjs;
 
 import com.fasterxml.jackson.annotation.JsonInclude.Include;
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.IModel;
@@ -33,7 +33,8 @@ public class ChartJSPanel extends Panel {
 
     private static final Logger LOG = LoggerFactory.getLogger(ChartJSPanel.class);
 
-    private static final ObjectMapper MAPPER = new ObjectMapper().setSerializationInclusion(Include.NON_NULL);
+    private static final JsonMapper MAPPER = JsonMapper.builder().
+            findAndAddModules().serializationInclusion(Include.NON_NULL).build();
 
     private final IModel<? extends Chart<?>> model;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java
index d918732..49d69ea 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java
@@ -105,9 +105,9 @@ public class AnyDataProvider<A extends AnyTO> extends DirectoryDataProvider<A> {
             }
 
             if (filtered) {
-                result = fiql == null
-                        ? List.of()
-                        : restClient.search(realm, fiql, currentPage + 1, paginatorRows, getSort(), type);
+                result = Optional.ofNullable(fiql).
+                        map(s -> restClient.search(realm, s, currentPage + 1, paginatorRows, getSort(), type)).
+                        orElseGet(() -> List.of());
             } else {
                 result = restClient.search(realm, null, currentPage + 1, paginatorRows, getSort(), type);
             }
@@ -115,9 +115,8 @@ public class AnyDataProvider<A extends AnyTO> extends DirectoryDataProvider<A> {
             LOG.error("While searching with FIQL {}", fiql, e);
             SyncopeConsoleSession.get().onException(e);
 
-            Optional<AjaxRequestTarget> target = RequestCycle.get().find(AjaxRequestTarget.class);
-            target.ifPresent(ajaxRequestTarget
-                    -> ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(ajaxRequestTarget));
+            RequestCycle.get().find(AjaxRequestTarget.class).
+                    ifPresent(target -> ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target));
         }
 
         return result.iterator();
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/DateFormatROModel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/DateFormatROModel.java
deleted file mode 100644
index 12f2d95..0000000
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/DateFormatROModel.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.client.console.commons;
-
-import java.util.Date;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.PropertyModel;
-
-public class DateFormatROModel implements IModel<String> {
-
-    private static final long serialVersionUID = 6677274580927636121L;
-
-    private final PropertyModel model;
-
-    public DateFormatROModel(final PropertyModel model) {
-        this.model = model;
-    }
-
-    @Override
-    public String getObject() {
-        return model.getObject() == null
-                ? ""
-                : SyncopeConsoleSession.get().getDateFormat().format((Date) model.getObject());
-    }
-
-    @Override
-    public void setObject(final String object) {
-    }
-
-    @Override
-    public void detach() {
-    }
-}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/AnyLayoutUtils.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/AnyLayoutUtils.java
index 66cd932..4b3e01b 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/AnyLayoutUtils.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/AnyLayoutUtils.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.layout;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.util.List;
@@ -43,7 +43,7 @@ public final class AnyLayoutUtils {
 
     private static final RoleRestClient ROLE_REST_CLIENT = new RoleRestClient();
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private static void setUserIfEmpty(final AnyLayout anyLayout) {
         if (anyLayout.getUser() == null) {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AccessTokenDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AccessTokenDirectoryPanel.java
index e235ccc..b0b2630 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AccessTokenDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AccessTokenDirectoryPanel.java
@@ -95,14 +95,15 @@ public class AccessTokenDirectoryPanel
 
             @Override
             public void populateItem(
-                final Item<ICellPopulator<AccessTokenTO>> cellItem,
-                final String componentId,
-                final IModel<AccessTokenTO> model) {
+                    final Item<ICellPopulator<AccessTokenTO>> cellItem,
+                    final String componentId,
+                    final IModel<AccessTokenTO> model) {
 
                 try {
                     SignedJWT jwt = SignedJWT.parse(model.getObject().getBody());
-                    cellItem.add(new Label(componentId,
-                        SyncopeConsoleSession.get().getDateFormat().format(jwt.getJWTClaimsSet().getIssueTime())));
+                    cellItem.add(new Label(
+                            componentId,
+                            SyncopeConsoleSession.get().getDateFormat().format(jwt.getJWTClaimsSet().getIssueTime())));
                 } catch (ParseException e) {
                     LOG.error("Could not parse JWT {}", model.getObject().getBody(), e);
                     cellItem.add(new Label(componentId, StringUtils.EMPTY));
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java
index 48d70ba..c0f9af0 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java
@@ -21,6 +21,7 @@ package org.apache.syncope.client.console.panels;
 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
 import java.io.Serializable;
 import java.lang.reflect.Field;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
@@ -182,7 +183,9 @@ public abstract class AnyDirectoryPanel<A extends AnyTO, E extends AbstractAnyRe
                 && (field.getType().equals(Boolean.class) || field.getType().equals(boolean.class))) {
 
             columns.add(new BooleanPropertyColumn<>(new ResourceModel(name, name), name, name));
-        } else if (field != null && !field.isSynthetic() && field.getType().equals(Date.class)) {
+        } else if (field != null && !field.isSynthetic()
+                && (field.getType().equals(Date.class) || field.getType().equals(OffsetDateTime.class))) {
+
             columns.add(new DatePropertyColumn<>(new ResourceModel(name, name), name, name));
         } else {
             columns.add(new PropertyColumn<>(new ResourceModel(name, name), name, name));
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
index 9a8f70c..7ff6dd2 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
@@ -21,12 +21,13 @@ package org.apache.syncope.client.console.panels;
 import java.io.Serializable;
 import java.lang.reflect.Field;
 import java.lang.reflect.ParameterizedType;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
-import org.apache.commons.lang3.time.FastDateFormat;
+import org.apache.commons.lang3.time.DateFormatUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.console.panels.search.AnyObjectSearchPanel;
 import org.apache.syncope.client.console.panels.search.GroupSearchPanel;
@@ -43,8 +44,8 @@ import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPa
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
 import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.ui.commons.DateOps;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxGridFieldPanel;
-import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.Schema;
 import org.apache.syncope.common.lib.report.SearchCondition;
 import org.apache.syncope.common.lib.search.AbstractFiqlSearchConditionBuilder;
@@ -106,8 +107,8 @@ public class BeanPanel<T extends Serializable> extends Panel {
 
                 if (BeanPanel.this.getDefaultModelObject() != null) {
                     ReflectionUtils.doWithFields(BeanPanel.this.getDefaultModelObject().getClass(),
-                        field -> result.add(field.getName()),
-                        field -> !field.isSynthetic() && !BeanPanel.this.excluded.contains(field.getName()));
+                            field -> result.add(field.getName()),
+                            field -> !field.isSynthetic() && !BeanPanel.this.excluded.contains(field.getName()));
                 }
 
                 return result;
@@ -118,7 +119,7 @@ public class BeanPanel<T extends Serializable> extends Panel {
 
             private static final long serialVersionUID = 9101744072914090143L;
 
-            @SuppressWarnings({"unchecked", "rawtypes"})
+            @SuppressWarnings({ "unchecked", "rawtypes" })
             @Override
             protected void populateItem(final ListItem<String> item) {
                 String fieldName = item.getModelObject();
@@ -146,20 +147,20 @@ public class BeanPanel<T extends Serializable> extends Panel {
                     switch (scondAnnot.type()) {
                         case "USER":
                             panel = new UserSearchPanel.Builder(
-                                new ListModel<>(clauses)).required(false).build("value");
+                                    new ListModel<>(clauses)).required(false).build("value");
                             builder = SyncopeClient.getUserSearchConditionBuilder();
                             break;
 
                         case "GROUP":
                             panel = new GroupSearchPanel.Builder(
-                                new ListModel<>(clauses)).required(false).build("value");
+                                    new ListModel<>(clauses)).required(false).build("value");
                             builder = SyncopeClient.getGroupSearchConditionBuilder();
                             break;
 
                         default:
                             panel = new AnyObjectSearchPanel.Builder(
-                                scondAnnot.type(),
-                                new ListModel<>(clauses)).required(false).build("value");
+                                    scondAnnot.type(),
+                                    new ListModel<>(clauses)).required(false).build("value");
                             builder = SyncopeClient.getAnyObjectSearchConditionBuilder(null);
                     }
 
@@ -170,7 +171,7 @@ public class BeanPanel<T extends Serializable> extends Panel {
                     Class<?> listItemType = String.class;
                     if (field.getGenericType() instanceof ParameterizedType) {
                         listItemType = (Class<?>) ((ParameterizedType) field.getGenericType()).
-                            getActualTypeArguments()[0];
+                                getActualTypeArguments()[0];
                     }
 
                     if (listItemType.equals(String.class) && schemaAnnot != null) {
@@ -180,17 +181,17 @@ public class BeanPanel<T extends Serializable> extends Panel {
                             switch (type) {
                                 case PLAIN:
                                     choices.addAll(
-                                        SchemaRestClient.getSchemas(SchemaType.PLAIN, schemaAnnot.anyTypeKind()));
+                                            SchemaRestClient.getSchemas(SchemaType.PLAIN, schemaAnnot.anyTypeKind()));
                                     break;
 
                                 case DERIVED:
                                     choices.addAll(
-                                        SchemaRestClient.getSchemas(SchemaType.DERIVED, schemaAnnot.anyTypeKind()));
+                                            SchemaRestClient.getSchemas(SchemaType.DERIVED, schemaAnnot.anyTypeKind()));
                                     break;
 
                                 case VIRTUAL:
                                     choices.addAll(
-                                        SchemaRestClient.getSchemas(SchemaType.VIRTUAL, schemaAnnot.anyTypeKind()));
+                                            SchemaRestClient.getSchemas(SchemaType.VIRTUAL, schemaAnnot.anyTypeKind()));
                                     break;
 
                                 default:
@@ -198,25 +199,25 @@ public class BeanPanel<T extends Serializable> extends Panel {
                         }
 
                         panel = new AjaxPalettePanel.Builder<>().setName(fieldName).build(
-                            "value",
-                            new PropertyModel<>(bean.getObject(), fieldName),
-                            new ListModel<>(choices.stream().map(EntityTO::getKey).collect(Collectors.toList()))).
-                            hideLabel();
+                                "value",
+                                new PropertyModel<>(bean.getObject(), fieldName),
+                                new ListModel<>(choices.stream().map(EntityTO::getKey).collect(Collectors.toList()))).
+                                hideLabel();
                     } else if (listItemType.isEnum()) {
                         panel = new AjaxPalettePanel.Builder<>().setName(fieldName).build(
-                            "value",
-                            new PropertyModel<>(bean.getObject(), fieldName),
-                            new ListModel(List.of(listItemType.getEnumConstants()))).hideLabel();
+                                "value",
+                                new PropertyModel<>(bean.getObject(), fieldName),
+                                new ListModel(List.of(listItemType.getEnumConstants()))).hideLabel();
                     } else {
                         panel = new MultiFieldPanel.Builder<>(
-                            new PropertyModel<>(bean.getObject(), fieldName)).build(
-                            "value",
-                            fieldName,
-                            buildSinglePanel(bean.getObject(), listItemType, fieldName, "panel")).hideLabel();
+                                new PropertyModel<>(bean.getObject(), fieldName)).build(
+                                "value",
+                                fieldName,
+                                buildSinglePanel(bean.getObject(), listItemType, fieldName, "panel")).hideLabel();
                     }
                 } else if (Map.class.equals(field.getType())) {
                     panel = new AjaxGridFieldPanel(
-                        "value", fieldName, new PropertyModel<>(bean, fieldName)).hideLabel();
+                            "value", fieldName, new PropertyModel<>(bean, fieldName)).hideLabel();
                 } else {
                     panel = buildSinglePanel(bean.getObject(), field.getType(), fieldName, "value").hideLabel();
                 }
@@ -240,7 +241,10 @@ public class BeanPanel<T extends Serializable> extends Panel {
                     id, fieldName, (Class<Number>) ClassUtils.resolvePrimitiveIfNecessary(type), model);
         } else if (Date.class.equals(type)) {
             result = new AjaxDateTimeFieldPanel(id, fieldName, model,
-                    FastDateFormat.getInstance(SyncopeConstants.DEFAULT_DATE_PATTERN));
+                    DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT);
+        } else if (OffsetDateTime.class.equals(type)) {
+            result = new AjaxDateTimeFieldPanel(id, fieldName, new DateOps.WrappedDateModel(model),
+                    DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT);
         } else if (type.isEnum()) {
             result = new AjaxDropDownChoicePanel(id, fieldName, model).setChoices(List.of(type.getEnumConstants()));
         } else {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DirectoryPanel.java
index 85f0a51..8ad5594 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DirectoryPanel.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.panels;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
 import java.io.Serializable;
 import java.util.Collection;
@@ -59,7 +59,7 @@ public abstract class DirectoryPanel<
 
     protected static final Logger LOG = LoggerFactory.getLogger(DirectoryPanel.class);
 
-    protected static final ObjectMapper MAPPER = new ObjectMapper();
+    protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     protected E restClient;
 
@@ -278,7 +278,7 @@ public abstract class DirectoryPanel<
 
         // take care of restClient handle: maybe not useful to keep into
         AjaxDataTablePanel.Builder<T, String> resultTableBuilder = new AjaxDataTablePanel.Builder<>(
-            dataProvider, page.getPageReference()) {
+                dataProvider, page.getPageReference()) {
 
             private static final long serialVersionUID = 2205322679547329123L;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java
index e6a60ca..ff434d5 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.client.console.panels;
 
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.IOException;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
@@ -49,7 +49,7 @@ public class ImplementationModalPanel extends AbstractModalPanel<ImplementationT
 
     private static final long serialVersionUID = 5283548960927517342L;
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private final ImplementationTO implementation;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardAttrStep.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardAttrStep.java
index de61f0f..5f83d17 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardAttrStep.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardAttrStep.java
@@ -21,7 +21,7 @@ package org.apache.syncope.client.console.panels;
 import java.util.List;
 import javax.ws.rs.core.MediaType;
 import org.apache.commons.lang3.BooleanUtils;
-import org.apache.commons.lang3.time.FastDateFormat;
+import org.apache.commons.lang3.time.DateFormatUtils;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
@@ -30,7 +30,6 @@ import org.apache.syncope.client.console.wicket.markup.html.form.BinaryFieldPane
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
 import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
-import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -96,7 +95,7 @@ public class ParametersWizardAttrStep extends WizardStep {
             case Date:
                 panel = new AjaxDateTimeFieldPanel(
                         id, valueHeaderName, new Model<>(),
-                        FastDateFormat.getInstance(SyncopeConstants.DEFAULT_DATE_PATTERN));
+                        DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT);
                 break;
 
             case Boolean:
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java
index ad11b02..79fdac6 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java
@@ -32,6 +32,7 @@ import java.util.function.Consumer;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.DateFormatUtils;
 import org.apache.commons.lang3.time.FastDateFormat;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.ui.commons.Constants;
@@ -244,15 +245,15 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
                     case GROUP_MEMBER:
                     case RESOURCE:
                         return List.of(
-                            SearchClause.Comparator.EQUALS,
-                            SearchClause.Comparator.NOT_EQUALS);
+                                SearchClause.Comparator.EQUALS,
+                                SearchClause.Comparator.NOT_EQUALS);
 
                     case RELATIONSHIP:
                         return List.of(
-                            SearchClause.Comparator.IS_NOT_NULL,
-                            SearchClause.Comparator.IS_NULL,
-                            SearchClause.Comparator.EQUALS,
-                            SearchClause.Comparator.NOT_EQUALS);
+                                SearchClause.Comparator.IS_NOT_NULL,
+                                SearchClause.Comparator.IS_NULL,
+                                SearchClause.Comparator.EQUALS,
+                                SearchClause.Comparator.NOT_EQUALS);
 
                     case CUSTOM:
                         return customizer.comparators();
@@ -286,19 +287,19 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
 
                     case ROLE_MEMBERSHIP:
                         return roleNames.getObject().stream().
-                            sorted().collect(Collectors.toList());
+                                sorted().collect(Collectors.toList());
 
                     case PRIVILEGE:
                         return privilegeNames.getObject().stream().
-                            sorted().collect(Collectors.toList());
+                                sorted().collect(Collectors.toList());
 
                     case RESOURCE:
                         return resourceNames.getObject().stream().
-                            sorted().collect(Collectors.toList());
+                                sorted().collect(Collectors.toList());
 
                     case RELATIONSHIP:
                         return RelationshipTypeRestClient.list().stream().
-                            map(RelationshipTypeTO::getKey).collect(Collectors.toList());
+                                map(RelationshipTypeTO::getKey).collect(Collectors.toList());
 
                     case CUSTOM:
                         return customizer.properties();
@@ -815,7 +816,7 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
 
             @Override
             public SearchClause.Comparator getObject(
-                final String id, final IModel<? extends List<? extends SearchClause.Comparator>> choices) {
+                    final String id, final IModel<? extends List<? extends SearchClause.Comparator>> choices) {
 
                 if (id == null) {
                     return SearchClause.Comparator.EQUALS;
@@ -885,14 +886,14 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
             final SearchClause searchClause,
             final AjaxTextFieldPanel property) {
 
-        PlainSchemaTO plainSchemaTO = anames.getObject().get(property.getModelObject());
-        if (plainSchemaTO == null) {
+        PlainSchemaTO plainSchema = anames.getObject().get(property.getModelObject());
+        if (plainSchema == null) {
             PlainSchemaTO defaultPlainTO = new PlainSchemaTO();
             defaultPlainTO.setType(AttrSchemaType.String);
-            plainSchemaTO = dnames.getObject().getOrDefault(property.getModelObject(), defaultPlainTO);
+            plainSchema = dnames.getObject().getOrDefault(property.getModelObject(), defaultPlainTO);
         }
 
-        switch (plainSchemaTO.getType()) {
+        switch (plainSchema.getType()) {
             case Boolean:
                 value = new AjaxTextFieldPanel(
                         "value",
@@ -904,10 +905,9 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
                 break;
 
             case Date:
-                FastDateFormat fdf = FastDateFormat.getInstance(
-                        plainSchemaTO.getConversionPattern() == null
-                        ? SyncopeConstants.DEFAULT_DATE_PATTERN
-                        : plainSchemaTO.getConversionPattern());
+                FastDateFormat fdf = plainSchema.getConversionPattern() == null
+                        ? DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT
+                        : FastDateFormat.getInstance(plainSchema.getConversionPattern());
 
                 value = new AjaxDateTimeFieldPanel(
                         "value",
@@ -936,7 +936,7 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
                             super.setObject(object);
                         }
                     }
-                }, FastDateFormat.getInstance(SyncopeConstants.DEFAULT_DATE_PATTERN));
+                }, DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT);
                 break;
 
             case Enum:
@@ -945,10 +945,10 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
                         "value",
                         new PropertyModel(searchClause, "value"),
                         true);
-                ((AjaxDropDownChoicePanel<String>) value).setChoices(SchemaUtils.getEnumeratedValues(plainSchemaTO));
+                ((AjaxDropDownChoicePanel<String>) value).setChoices(SchemaUtils.getEnumeratedValues(plainSchema));
 
-                if (StringUtils.isNotBlank(plainSchemaTO.getEnumerationKeys())) {
-                    Map<String, String> valueMap = SchemaUtils.getEnumeratedKeyValues(plainSchemaTO);
+                if (StringUtils.isNotBlank(plainSchema.getEnumerationKeys())) {
+                    Map<String, String> valueMap = SchemaUtils.getEnumeratedKeyValues(plainSchema);
                     ((AjaxDropDownChoicePanel) value).setChoiceRenderer(new IChoiceRenderer<String>() {
 
                         private static final long serialVersionUID = -3724971416312135885L;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java
index 7bad87d..46b96f0 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.policies;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
@@ -50,7 +50,7 @@ public class PolicyRuleWizardBuilder extends BaseAjaxWizardBuilder<PolicyRuleWra
 
     private static final long serialVersionUID = 5945391813567245081L;
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private final String policy;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java
index 0f96fe0..191a5ec 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.reports;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.Serializable;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.ui.commons.Constants;
@@ -49,14 +49,11 @@ public class ReportletWizardBuilder extends BaseAjaxWizardBuilder<ReportletWrapp
 
     private static final long serialVersionUID = 5945391813567245081L;
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private final String report;
 
-    public ReportletWizardBuilder(
-            final String report,
-            final ReportletWrapper reportlet,
-            final PageReference pageRef) {
+    public ReportletWizardBuilder(final String report, final ReportletWrapper reportlet, final PageReference pageRef) {
         super(reportlet, pageRef);
         this.report = report;
     }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ExecutionRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ExecutionRestClient.java
index dbff175..75b7224 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ExecutionRestClient.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ExecutionRestClient.java
@@ -18,8 +18,8 @@
  */
 package org.apache.syncope.client.console.rest;
 
-import org.apache.syncope.client.ui.commons.rest.RestClient;
 import java.util.Date;
+import org.apache.syncope.client.ui.commons.rest.RestClient;
 import java.util.List;
 import java.util.Map;
 import org.apache.syncope.client.lib.batch.BatchRequest;
@@ -28,7 +28,7 @@ import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
 
 public interface ExecutionRestClient extends RestClient {
 
-    void startExecution(String executionCollectorKey, Date start);
+    void startExecution(String executionCollectorKey, Date startAt);
 
     void deleteExecution(String executionKey);
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerConfRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerConfRestClient.java
index 65a2b4f..ef29eda 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerConfRestClient.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerConfRestClient.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.client.console.rest;
 
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -47,7 +47,7 @@ public class LoggerConfRestClient implements RestClient, LoggerConfOp {
 
     private static final Logger LOG = LoggerFactory.getLogger(LoggerConfRestClient.class);
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private final List<NetworkService> instances;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
index 318ccdb..a7af135 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
@@ -30,6 +30,7 @@ import javax.ws.rs.core.Response;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.lib.batch.BatchRequest;
+import org.apache.syncope.client.ui.commons.DateOps;
 import org.apache.syncope.common.lib.to.ExecTO;
 import org.apache.syncope.common.lib.to.JobTO;
 import org.apache.syncope.common.lib.to.ReportTO;
@@ -39,8 +40,8 @@ import org.apache.syncope.common.lib.types.ReportExecExportFormat;
 import org.apache.syncope.common.lib.types.ReportTemplateFormat;
 import org.apache.syncope.common.rest.api.batch.BatchRequestItem;
 import org.apache.syncope.common.rest.api.batch.BatchResponseItem;
-import org.apache.syncope.common.rest.api.beans.ExecQuery;
-import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
+import org.apache.syncope.common.rest.api.beans.ExecListQuery;
+import org.apache.syncope.common.rest.api.beans.ExecSpecs;
 import org.apache.syncope.common.rest.api.service.ReportService;
 import org.apache.syncope.common.rest.api.service.ReportTemplateService;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
@@ -88,8 +89,9 @@ public class ReportRestClient extends BaseRestClient
     }
 
     @Override
-    public void startExecution(final String reportKey, final Date start) {
-        getService(ReportService.class).execute(new ExecuteQuery.Builder().key(reportKey).startAt(start).build());
+    public void startExecution(final String reportKey, final Date startAt) {
+        getService(ReportService.class).execute(new ExecSpecs.Builder().key(reportKey).
+                startAt(DateOps.convert(startAt)).build());
     }
 
     @Override
@@ -110,15 +112,14 @@ public class ReportRestClient extends BaseRestClient
     public List<ExecTO> listExecutions(
             final String taskKey, final int page, final int size, final SortParam<String> sort) {
 
-        return getService(ReportService.class).
-                listExecutions(new ExecQuery.Builder().key(taskKey).page(page).size(size).
-                        orderBy(toOrderBy(sort)).build()).getResult();
+        return getService(ReportService.class).listExecutions(new ExecListQuery.Builder().
+                key(taskKey).page(page).size(size).orderBy(toOrderBy(sort)).build()).getResult();
     }
 
     @Override
     public int countExecutions(final String taskKey) {
         return getService(ReportService.class).
-                listExecutions(new ExecQuery.Builder().key(taskKey).page(1).size(0).build()).getTotalCount();
+                listExecutions(new ExecListQuery.Builder().key(taskKey).page(1).size(0).build()).getTotalCount();
     }
 
     @Override
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
index 6b39a0a..e32c100 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Map;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.lib.batch.BatchRequest;
+import org.apache.syncope.client.ui.commons.DateOps;
 import org.apache.syncope.common.lib.to.TaskTO;
 import org.apache.syncope.common.lib.to.NotificationTaskTO;
 import org.apache.syncope.common.lib.to.PropagationTaskTO;
@@ -40,8 +41,8 @@ import org.apache.syncope.common.lib.types.JobAction;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.rest.api.batch.BatchRequestItem;
 import org.apache.syncope.common.rest.api.batch.BatchResponseItem;
-import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
-import org.apache.syncope.common.rest.api.beans.ExecQuery;
+import org.apache.syncope.common.rest.api.beans.ExecListQuery;
+import org.apache.syncope.common.rest.api.beans.ExecSpecs;
 import org.apache.syncope.common.rest.api.beans.TaskQuery;
 import org.apache.syncope.common.rest.api.service.TaskService;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
@@ -91,7 +92,7 @@ public class TaskRestClient extends BaseRestClient implements ExecutionRestClien
     @Override
     public int countExecutions(final String taskKey) {
         return getService(TaskService.class).
-                listExecutions(new ExecQuery.Builder().key(taskKey).page(1).size(0).build()).getTotalCount();
+                listExecutions(new ExecListQuery.Builder().key(taskKey).page(1).size(0).build()).getTotalCount();
     }
 
     public static List<PropagationTaskTO> listPropagationTasks(
@@ -145,7 +146,7 @@ public class TaskRestClient extends BaseRestClient implements ExecutionRestClien
 
     @SuppressWarnings("unchecked")
     public static <T extends TaskTO> List<T> list(
-        final Class<T> reference, final int page, final int size, final SortParam<String> sort) {
+            final Class<T> reference, final int page, final int size, final SortParam<String> sort) {
 
         return (List<T>) getService(TaskService.class).
                 search(new TaskQuery.Builder(getTaskType(reference)).page(page).size(size).
@@ -154,11 +155,11 @@ public class TaskRestClient extends BaseRestClient implements ExecutionRestClien
 
     @SuppressWarnings("unchecked")
     public static <T extends TaskTO> List<T> list(
-        final String resource,
-        final Class<T> reference,
-        final int page,
-        final int size,
-        final SortParam<String> sort) {
+            final String resource,
+            final Class<T> reference,
+            final int page,
+            final int size,
+            final SortParam<String> sort) {
 
         return (List<T>) getService(TaskService.class).
                 search(new TaskQuery.Builder(getTaskType(reference)).page(page).size(size).resource(resource).
@@ -170,7 +171,7 @@ public class TaskRestClient extends BaseRestClient implements ExecutionRestClien
             final String taskKey, final int page, final int size, final SortParam<String> sort) {
 
         return getService(TaskService.class).
-                listExecutions(new ExecQuery.Builder().key(taskKey).page(page).size(size).
+                listExecutions(new ExecListQuery.Builder().key(taskKey).page(page).size(size).
                         orderBy(toOrderBy(sort)).build()).getResult();
     }
 
@@ -207,13 +208,13 @@ public class TaskRestClient extends BaseRestClient implements ExecutionRestClien
     }
 
     @Override
-    public void startExecution(final String taskKey, final Date start) {
-        startExecution(taskKey, start, false);
+    public void startExecution(final String taskKey, final Date startAt) {
+        startExecution(taskKey, startAt, false);
     }
 
-    public static void startExecution(final String taskKey, final Date start, final boolean dryRun) {
-        getService(TaskService.class).execute(
-                new ExecuteQuery.Builder().key(taskKey).startAt(start).dryRun(dryRun).build());
+    public static void startExecution(final String taskKey, final Date startAt, final boolean dryRun) {
+        getService(TaskService.class).execute(new ExecSpecs.Builder().key(taskKey).
+                startAt(DateOps.convert(startAt)).dryRun(dryRun).build());
     }
 
     @Override
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TaskAttributesDetailsView.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TaskAttributesDetailsView.java
index bacb6a6..4d5b476 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TaskAttributesDetailsView.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TaskAttributesDetailsView.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.client.console.tasks;
 
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.IOException;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
@@ -39,7 +39,7 @@ public class TaskAttributesDetailsView extends MultilevelPanel.SecondLevel {
 
     private static final Logger LOG = LoggerFactory.getLogger(AnyPropagationTasks.class);
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     public TaskAttributesDetailsView(final PropagationTaskTO taskTO) {
         super();
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/DatePropertyColumn.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/DatePropertyColumn.java
index 8d93623..83c1e68 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/DatePropertyColumn.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/DatePropertyColumn.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table;
 
+import java.time.OffsetDateTime;
 import java.util.Date;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
@@ -46,8 +47,10 @@ public class DatePropertyColumn<T> extends PropertyColumn<T, String> {
         IModel<?> date = getDataModel(rowModel);
 
         String convertedDate = "";
-        if (date.getObject() instanceof Date) {
-            convertedDate = SyncopeConsoleSession.get().getDateFormat().format(date.getObject());
+        if (date.getObject() instanceof OffsetDateTime) {
+            convertedDate = SyncopeConsoleSession.get().getDateFormat().format((OffsetDateTime) date.getObject());
+        } else if (date.getObject() instanceof Date) {
+            convertedDate = SyncopeConsoleSession.get().getDateFormat().format((Date) date.getObject());
         }
         item.add(new Label(componentId, convertedDate));
     }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/LoadWidget.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/LoadWidget.java
index ce3430e..a049674 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/LoadWidget.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/LoadWidget.java
@@ -54,8 +54,9 @@ public class LoadWidget extends BaseWidget {
         line.getOptions().setMultiTooltipTemplate("<%= datasetLabel %>");
 
         systeminfo.getLoad().forEach(instant -> {
-            line.getData().getLabels().add(DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.
-                    format(systeminfo.getStartTime() + instant.getUptime()));
+            line.getData().getLabels().add(
+                    DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.format(
+                            systeminfo.getStartTime() + instant.getUptime()));
 
             cpuValues.add(instant.getSystemLoadAverage() * 1000);
             memValues.add(instant.getTotalMemory());
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/ProgressesPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/ProgressesPanel.java
index 4398be4..d95b593 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/ProgressesPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/ProgressesPanel.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.widgets;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.wicket.markup.html.basic.Label;
@@ -30,7 +30,7 @@ public class ProgressesPanel extends Panel {
 
     private static final long serialVersionUID = 7837262802315339565L;
 
-    public ProgressesPanel(final String id, final Date lastUpdate, final List<ProgressBean> progressBeans) {
+    public ProgressesPanel(final String id, final OffsetDateTime lastUpdate, final List<ProgressBean> progressBeans) {
         super(id);
 
         add(new Label("lastUpdate", SyncopeConsoleSession.get().getDateFormat().format(lastUpdate)));
@@ -47,5 +47,4 @@ public class ProgressesPanel extends Panel {
         progresses.setOutputMarkupId(true);
         add(progresses);
     }
-
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/ReconciliationWidget.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/ReconciliationWidget.java
index 4726792..90307ca 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/ReconciliationWidget.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/ReconciliationWidget.java
@@ -21,10 +21,10 @@ package org.apache.syncope.client.console.widgets;
 import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
 import java.io.IOException;
 import java.io.InputStream;
+import java.time.OffsetDateTime;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -210,7 +210,7 @@ public class ReconciliationWidget extends BaseWidget {
             execResult = parseReconciliationReportExec();
         } catch (Exception e) {
             LOG.error("Could not parse the reconciliation report result", e);
-            execResult = Pair.of(List.of(), new ReconciliationReport(new Date()));
+            execResult = Pair.of(List.of(), new ReconciliationReport(OffsetDateTime.now()));
         }
         final List<ProgressBean> progressBeans = execResult.getLeft();
         final ReconciliationReport report = execResult.getRight();
@@ -311,7 +311,8 @@ public class ReconciliationWidget extends BaseWidget {
             }
         }
 
-        return Pair.of(beans, Optional.ofNullable(report).orElseGet(() -> new ReconciliationReport(new Date())));
+        return Pair.of(beans, Optional.ofNullable(report).
+                orElseGet(() -> new ReconciliationReport(OffsetDateTime.now())));
     }
 
     private class AnysReconciliationPanel extends DirectoryPanel<Any, Any, AnysReconciliationProvider, BaseRestClient> {
@@ -361,12 +362,12 @@ public class ReconciliationWidget extends BaseWidget {
 
                 @Override
                 public void populateItem(
-                    final Item<ICellPopulator<Any>> cellItem,
-                    final String componentId,
-                    final IModel<Any> rowModel) {
+                        final Item<ICellPopulator<Any>> cellItem,
+                        final String componentId,
+                        final IModel<Any> rowModel) {
 
                     cellItem.add(new Label(componentId,
-                        rowModel.getObject().getKey()
+                            rowModel.getObject().getKey()
                             + (StringUtils.isBlank(rowModel.getObject().getName())
                             ? StringUtils.EMPTY
                             : ' ' + rowModel.getObject().getName())));
@@ -387,16 +388,16 @@ public class ReconciliationWidget extends BaseWidget {
 
                     @Override
                     public void populateItem(
-                        final Item<ICellPopulator<Any>> cellItem,
-                        final String componentId,
-                        final IModel<Any> rowModel) {
+                            final Item<ICellPopulator<Any>> cellItem,
+                            final String componentId,
+                            final IModel<Any> rowModel) {
 
                         Any any = rowModel.getObject();
 
                         Optional<Missing> missing = any.getMissing().stream().
-                            filter(object -> resource.equals(object.getResource())).findFirst();
+                                filter(object -> resource.equals(object.getResource())).findFirst();
                         List<Misaligned> misaligned = any.getMisaligned().stream().
-                            filter(object -> resource.equals(object.getResource())).collect(Collectors.toList());
+                                filter(object -> resource.equals(object.getResource())).collect(Collectors.toList());
 
                         Component content;
                         if (missing.isEmpty()) {
@@ -410,14 +411,14 @@ public class ReconciliationWidget extends BaseWidget {
                                     @Override
                                     public void onClick(final AjaxRequestTarget target, final Any ignore) {
                                         modal.header(Model.of(
-                                            rowModel.getObject().getType()
+                                                rowModel.getObject().getType()
                                                 + ' ' + rowModel.getObject().getKey()
                                                 + ' ' + rowModel.getObject().getName()));
                                         modal.setContent(new ReconDetailsModalPanel(
-                                            modal,
-                                            resource,
-                                            misaligned,
-                                            ReconciliationWidget.this.pageRef));
+                                                modal,
+                                                resource,
+                                                misaligned,
+                                                ReconciliationWidget.this.pageRef));
                                         modal.show(true);
                                         target.add(modal);
                                     }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/reconciliation/ReconciliationReport.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/reconciliation/ReconciliationReport.java
index 5e6a15f..6853f8d 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/reconciliation/ReconciliationReport.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/reconciliation/ReconciliationReport.java
@@ -19,16 +19,15 @@
 package org.apache.syncope.client.console.widgets.reconciliation;
 
 import java.io.Serializable;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
-import java.util.Optional;
 
 public class ReconciliationReport implements Serializable {
 
     private static final long serialVersionUID = 931063230006747313L;
 
-    private final Date run;
+    private final OffsetDateTime run;
 
     private Anys users;
 
@@ -36,16 +35,12 @@ public class ReconciliationReport implements Serializable {
 
     private final List<Anys> anyObjects = new ArrayList<>();
 
-    public ReconciliationReport(final Date run) {
-        if (run != null) {
-            this.run = new Date(run.getTime());
-        } else {
-            this.run = null;
-        }
+    public ReconciliationReport(final OffsetDateTime run) {
+        this.run = run;
     }
 
-    public Date getRun() {
-        return Optional.ofNullable(run).map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getRun() {
+        return run;
     }
 
     public Anys getUsers() {
@@ -67,5 +62,4 @@ public class ReconciliationReport implements Serializable {
     public List<Anys> getAnyObjects() {
         return anyObjects;
     }
-
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/reconciliation/ReconciliationReportParser.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/reconciliation/ReconciliationReportParser.java
index 704d569..d430040 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/reconciliation/ReconciliationReportParser.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/reconciliation/ReconciliationReportParser.java
@@ -19,8 +19,8 @@
 package org.apache.syncope.client.console.widgets.reconciliation;
 
 import java.io.InputStream;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
@@ -40,7 +40,7 @@ public final class ReconciliationReportParser {
         XML_INPUT_FACTORY.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
     }
 
-    public static ReconciliationReport parse(final Date run, final InputStream in)
+    public static ReconciliationReport parse(final OffsetDateTime run, final InputStream in)
             throws XMLStreamException, NumberFormatException {
 
         XMLStreamReader streamReader = XML_INPUT_FACTORY.createXMLStreamReader(in);
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/DelegationWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/DelegationWizardBuilder.java
index 2e01051..72397d5 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/DelegationWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/DelegationWizardBuilder.java
@@ -23,7 +23,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.time.FastDateFormat;
+import org.apache.commons.lang3.time.DateFormatUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.rest.DelegationRestClient;
 import org.apache.syncope.client.console.rest.UserRestClient;
@@ -31,7 +31,6 @@ import org.apache.syncope.client.ui.commons.Constants;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.DelegationTO;
 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
 import org.apache.wicket.PageReference;
@@ -142,14 +141,14 @@ public class DelegationWizardBuilder extends BaseAjaxWizardBuilder<DelegationTO>
                     "start",
                     "start",
                     new PropertyModel<>(modelObject, "start"),
-                    FastDateFormat.getInstance(SyncopeConstants.DEFAULT_DATE_PATTERN)).
+                    DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT).
                     addRequiredLabel());
 
             add(new AjaxDateTimeFieldPanel(
                     "end",
                     "end",
                     new PropertyModel<>(modelObject, "end"),
-                    FastDateFormat.getInstance(SyncopeConstants.DEFAULT_DATE_PATTERN)));
+                    DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT));
         }
     }
 
@@ -172,23 +171,23 @@ public class DelegationWizardBuilder extends BaseAjaxWizardBuilder<DelegationTO>
                     setAllowOrder(true).
                     build("roles",
                             new PropertyModel<>(modelObject, "roles"),
-                        new AjaxPalettePanel.Builder.Query<>() {
+                            new AjaxPalettePanel.Builder.Query<>() {
 
-                            private static final long serialVersionUID = 3900199363626636719L;
+                        private static final long serialVersionUID = 3900199363626636719L;
 
-                            @Override
-                            public List<String> execute(final String filter) {
-                                if (StringUtils.isEmpty(filter) || "*".equals(filter)) {
-                                    return allRoles.size() > Constants.MAX_ROLE_LIST_SIZE
+                        @Override
+                        public List<String> execute(final String filter) {
+                            if (StringUtils.isEmpty(filter) || "*".equals(filter)) {
+                                return allRoles.size() > Constants.MAX_ROLE_LIST_SIZE
                                         ? allRoles.subList(0, Constants.MAX_ROLE_LIST_SIZE)
                                         : allRoles;
 
-                                }
-                                return allRoles.stream().
+                            }
+                            return allRoles.stream().
                                     filter(role -> StringUtils.containsIgnoreCase(role, filter)).
                                     collect(Collectors.toList());
-                            }
-                        }).
+                        }
+                    }).
                     hideLabel().
                     setOutputMarkupId(true));
         }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrsWizardStep.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrsWizardStep.java
index 083ef4a..fd6a061 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrsWizardStep.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrsWizardStep.java
@@ -29,6 +29,7 @@ import java.util.stream.Collectors;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.DateFormatUtils;
 import org.apache.commons.lang3.time.FastDateFormat;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
@@ -202,10 +203,10 @@ public abstract class AbstractAttrsWizardStep<S extends SchemaTO> extends Wizard
 
             case Date:
                 String datePattern = plainSchema.getConversionPattern() == null
-                        ? SyncopeConstants.DEFAULT_DATE_PATTERN
+                        ? DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.getPattern()
                         : plainSchema.getConversionPattern();
 
-                if (datePattern.contains("H")) {
+                if (StringUtils.containsIgnoreCase(datePattern, "H")) {
                     panel = new AjaxDateTimeFieldPanel(
                             "panel",
                             plainSchema.getLabel(SyncopeConsoleSession.get().getLocale()),
diff --git a/client/idrepo/console/src/test/java/org/apache/syncope/client/console/layout/AnyLayoutTest.java b/client/idrepo/console/src/test/java/org/apache/syncope/client/console/layout/AnyLayoutTest.java
index f13fe52..dbf75e3 100644
--- a/client/idrepo/console/src/test/java/org/apache/syncope/client/console/layout/AnyLayoutTest.java
+++ b/client/idrepo/console/src/test/java/org/apache/syncope/client/console/layout/AnyLayoutTest.java
@@ -22,7 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.util.Arrays;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -30,7 +30,7 @@ import org.junit.jupiter.api.Test;
 
 public class AnyLayoutTest {
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     @Test
     public void issueSYNCOPE1554() throws JsonProcessingException {
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/PreferenceManager.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/PreferenceManager.java
index 7bfbc28..d65ce99 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/PreferenceManager.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/PreferenceManager.java
@@ -18,8 +18,8 @@
  */
 package org.apache.syncope.client.enduser;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.IOException;
 import java.io.Serializable;
 import java.io.StringWriter;
@@ -47,7 +47,7 @@ public final class PreferenceManager implements Serializable {
 
     private static final int ONE_YEAR_TIME = 60 * 60 * 24 * 365;
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private static final TypeReference<Map<String, String>> MAP_TYPE_REF = new TypeReference<>() {
     };
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
index f5bca47..6faf88a 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
@@ -20,7 +20,6 @@ package org.apache.syncope.client.enduser;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.apache.commons.lang3.time.FastDateFormat;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
@@ -52,6 +51,8 @@ import java.util.concurrent.Callable;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Future;
 import java.util.stream.Collectors;
+import org.apache.commons.lang3.time.FastDateFormat;
+import org.apache.syncope.client.ui.commons.DateOps;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 
 public class SyncopeEnduserSession extends AuthenticatedWebSession implements BaseSession {
@@ -344,7 +345,7 @@ public class SyncopeEnduserSession extends AuthenticatedWebSession implements Ba
     }
 
     @Override
-    public FastDateFormat getDateFormat() {
-        return FastDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, getLocale());
+    public DateOps.Format getDateFormat() {
+        return new DateOps.Format(FastDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, getLocale()));
     }
 }
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeWebApplication.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeWebApplication.java
index 72849f1..7592ee8 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeWebApplication.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeWebApplication.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.client.enduser;
 
 import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.giffing.wicket.spring.boot.starter.app.WicketBootStandardWebApplication;
 import de.agilecoders.wicket.core.Bootstrap;
 import de.agilecoders.wicket.core.settings.BootstrapSettings;
@@ -75,7 +75,7 @@ public class SyncopeWebApplication extends WicketBootStandardWebApplication {
     public static final List<Locale> SUPPORTED_LOCALES = List.of(
             Locale.ENGLISH, Locale.ITALIAN, new Locale("pt", "BR"), new Locale("ru"), Locale.JAPANESE);
 
-    protected static final ObjectMapper MAPPER = new ObjectMapper();
+    protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     public static SyncopeWebApplication get() {
         return (SyncopeWebApplication) WebApplication.get();
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfRegistration.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfRegistration.java
index 67096a3..dd9a075 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfRegistration.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/SelfRegistration.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.client.enduser.pages;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import org.apache.syncope.client.enduser.SyncopeWebApplication;
 import org.apache.syncope.client.enduser.SyncopeEnduserSession;
 import org.apache.syncope.client.enduser.layout.UserFormLayoutInfo;
@@ -37,7 +37,7 @@ public class SelfRegistration extends BasePage {
 
     public static final String NEW_USER_PARAM = "newUser";
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     public SelfRegistration(final PageParameters parameters) {
         super(parameters, SELF_REGISTRATION);
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/PlainAttrs.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/PlainAttrs.java
index 5f8fa38..f3cca34 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/PlainAttrs.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/PlainAttrs.java
@@ -33,7 +33,6 @@ import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
 import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.Attributable;
 import org.apache.syncope.common.lib.EntityTOUtils;
-import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.wicket.AttributeModifier;
@@ -45,6 +44,7 @@ import org.apache.wicket.markup.html.list.ListItem;
 import org.apache.wicket.markup.html.list.ListView;
 import org.apache.wicket.model.util.ListModel;
 import java.util.stream.Collectors;
+import org.apache.commons.lang3.time.DateFormatUtils;
 import org.apache.syncope.client.enduser.SyncopeEnduserSession;
 import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
@@ -94,29 +94,29 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
             protected void populateItem(final ListItem<MembershipTO> item) {
                 MembershipTO membershipTO = item.getModelObject();
                 item.add(new Accordion("membershipPlainSchemas", List.of(new AbstractTab(
-                    new StringResourceModel(
-                        "attributes.membership.accordion",
-                        PlainAttrs.this,
-                        Model.of(membershipTO))) {
+                        new StringResourceModel(
+                                "attributes.membership.accordion",
+                                PlainAttrs.this,
+                                Model.of(membershipTO))) {
 
                     private static final long serialVersionUID = 1037272333056449378L;
 
                     @Override
                     public WebMarkupContainer getPanel(final String panelId) {
                         return new PlainSchemasMemberships(
-                            panelId,
-                            membershipTO.getGroupName(),
-                            membershipSchemas.get(membershipTO.getGroupKey()),
-                            new LoadableDetachableModel<>() { // SYNCOPE-1439
+                                panelId,
+                                membershipTO.getGroupName(),
+                                membershipSchemas.get(membershipTO.getGroupKey()),
+                                new LoadableDetachableModel<>() { // SYNCOPE-1439
 
-                                private static final long serialVersionUID = 526768546610546553L;
+                            private static final long serialVersionUID = 526768546610546553L;
 
-                                @Override
-                                protected Attributable load() {
-                                    return membershipTO;
-                                }
+                            @Override
+                            protected Attributable load() {
+                                return membershipTO;
+                            }
 
-                            });
+                        });
                     }
                 }), Model.of(-1)).setOutputMarkupId(true));
             }
@@ -192,38 +192,38 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    protected FieldPanel getFieldPanel(final PlainSchemaTO schemaTO, final String groupName) {
-        final boolean required = schemaTO.getMandatoryCondition().equalsIgnoreCase("true");
-        final boolean readOnly = schemaTO.isReadonly() || renderAsReadonly(schemaTO.getKey(), groupName);
-        final AttrSchemaType type = schemaTO.getType();
-        final boolean jexlHelp = false;
+    protected FieldPanel getFieldPanel(final PlainSchemaTO plainSchema, final String groupName) {
+        boolean required = plainSchema.getMandatoryCondition().equalsIgnoreCase("true");
+        boolean readOnly = plainSchema.isReadonly() || renderAsReadonly(plainSchema.getKey(), groupName);
+        AttrSchemaType type = plainSchema.getType();
+        boolean jexlHelp = false;
 
         FieldPanel panel;
         switch (type) {
             case Boolean:
                 panel = new AjaxCheckBoxPanel(
                         "panel",
-                        schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()),
+                        plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()),
                         new Model<>(),
                         true);
                 panel.setRequired(required);
                 break;
 
             case Date:
-                String datePattern = schemaTO.getConversionPattern() == null
-                        ? SyncopeConstants.DEFAULT_DATE_PATTERN
-                        : schemaTO.getConversionPattern();
+                String datePattern = plainSchema.getConversionPattern() == null
+                        ? DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.getPattern()
+                        : plainSchema.getConversionPattern();
 
-                if (datePattern.contains("H")) {
+                if (StringUtils.containsIgnoreCase(datePattern, "H")) {
                     panel = new AjaxDateTimeFieldPanel(
                             "panel",
-                            schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()),
+                            plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()),
                             new Model<>(),
                             FastDateFormat.getInstance(datePattern));
                 } else {
                     panel = new AjaxDateFieldPanel(
                             "panel",
-                            schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()),
+                            plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()),
                             new Model<>(),
                             FastDateFormat.getInstance(datePattern));
                 }
@@ -236,15 +236,15 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
 
             case Enum:
                 panel = new AjaxDropDownChoicePanel<>("panel",
-                        schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()), new Model<>(), true);
-                ((AjaxDropDownChoicePanel<String>) panel).setChoices(SchemaUtils.getEnumeratedValues(schemaTO));
+                        plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()), new Model<>(), true);
+                ((AjaxDropDownChoicePanel<String>) panel).setChoices(SchemaUtils.getEnumeratedValues(plainSchema));
 
-                if (StringUtils.isNotBlank(schemaTO.getEnumerationKeys())) {
+                if (StringUtils.isNotBlank(plainSchema.getEnumerationKeys())) {
                     ((AjaxDropDownChoicePanel) panel).setChoiceRenderer(new IChoiceRenderer<String>() {
 
                         private static final long serialVersionUID = -3724971416312135885L;
 
-                        private final Map<String, String> valueMap = SchemaUtils.getEnumeratedKeyValues(schemaTO);
+                        private final Map<String, String> valueMap = SchemaUtils.getEnumeratedKeyValues(plainSchema);
 
                         @Override
                         public String getDisplayValue(final String value) {
@@ -272,7 +272,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
             case Long:
                 panel = new AjaxSpinnerFieldPanel.Builder<Long>().enableOnChange().build(
                         "panel",
-                        schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()),
+                        plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()),
                         Long.class,
                         new Model<>());
 
@@ -284,7 +284,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
             case Double:
                 panel = new AjaxSpinnerFieldPanel.Builder<Double>().enableOnChange().step(0.1).build(
                         "panel",
-                        schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()),
+                        plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()),
                         Double.class,
                         new Model<>());
 
@@ -296,9 +296,9 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
             case Binary:
                 panel = new BinaryFieldPanel(
                         "panel",
-                        schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()),
+                        plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()),
                         new Model<>(),
-                        schemaTO.getMimeType(),
+                        plainSchema.getMimeType(),
                         fileKey);
                 if (required) {
                     panel.addRequiredLabel();
@@ -307,7 +307,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
 
             case Encrypted:
                 panel = new EncryptedFieldPanel("panel",
-                        schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()), new Model<>(), true);
+                        plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()), new Model<>(), true);
 
                 if (required) {
                     panel.addRequiredLabel();
@@ -316,7 +316,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
 
             default:
                 panel = new AjaxTextFieldPanel("panel",
-                        schemaTO.getLabel(SyncopeEnduserSession.get().getLocale()), new Model<>(), true);
+                        plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()), new Model<>(), true);
 
                 if (jexlHelp) {
                     AjaxTextFieldPanel.class.cast(panel).enableJexlHelp();
@@ -328,11 +328,12 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
         }
 
         panel.setReadOnly(readOnly);
-        panel.setMarkupId(StringUtils.isBlank(groupName) ? schemaTO.getKey() : groupName + '.' + schemaTO.getKey());
+        panel.setMarkupId(StringUtils.isBlank(groupName)
+                ? plainSchema.getKey() : groupName + '.' + plainSchema.getKey());
 
         Label label = (Label) panel.get(AbstractFieldPanel.LABEL);
         label.add(new AttributeModifier("for", FORM_SUFFIX
-                + (StringUtils.isBlank(groupName) ? schemaTO.getKey() : groupName + '.' + schemaTO.getKey())));
+                + (StringUtils.isBlank(groupName) ? plainSchema.getKey() : groupName + '.' + plainSchema.getKey())));
 
         return panel;
     }
@@ -350,14 +351,14 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
             super(id);
 
             add(new ListView<>("schemas",
-                new ListModel<>(new ArrayList<>(
-                    attributableTO.getObject().getPlainAttrs().stream().sorted(attrComparator).
-                        collect(Collectors.toList())))) {
+                    new ListModel<>(new ArrayList<>(
+                            attributableTO.getObject().getPlainAttrs().stream().sorted(attrComparator).
+                                    collect(Collectors.toList())))) {
 
                 private static final long serialVersionUID = 5306618783986001008L;
 
                 @Override
-                @SuppressWarnings({"unchecked", "rawtypes"})
+                @SuppressWarnings({ "unchecked", "rawtypes" })
                 protected void populateItem(final ListItem<Attr> item) {
                     Attr attrTO = item.getModelObject();
                     PlainSchemaTO schema = schemas.get(attrTO.getSchema());
@@ -371,14 +372,14 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
                     AbstractFieldPanel<?> panel = getFieldPanel(schemas.get(attrTO.getSchema()));
                     if (schemas.get(attrTO.getSchema()).isMultivalue()) {
                         panel = new MultiFieldPanel.Builder<>(
-                            new PropertyModel<>(
-                                attributableTO.getObject().getPlainAttr(attrTO.getSchema()), "values"))
-                            .build("panel", attrTO.getSchema(), FieldPanel.class.cast(panel));
+                                new PropertyModel<>(
+                                        attributableTO.getObject().getPlainAttr(attrTO.getSchema()), "values"))
+                                .build("panel", attrTO.getSchema(), FieldPanel.class.cast(panel));
                         // SYNCOPE-1215 the entire multifield panel must be readonly, not only its field
                         ((MultiFieldPanel) panel).setReadOnly(schema == null ? false : schema.isReadonly());
                     } else {
                         FieldPanel.class.cast(panel).setNewModel(attrTO.getValues()).
-                            setReadOnly(schema == null ? false : schema.isReadonly());
+                                setReadOnly(schema == null ? false : schema.isReadonly());
                     }
 
                     item.add(panel);
@@ -403,7 +404,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
                 private static final long serialVersionUID = 9101744072914090143L;
 
                 @Override
-                @SuppressWarnings({"unchecked", "rawtypes"})
+                @SuppressWarnings({ "unchecked", "rawtypes" })
                 protected void populateItem(final ListItem<Attr> item) {
                     Attr attrTO = item.getModelObject();
                     PlainSchemaTO schema = schemas.get(attrTO.getSchema());
@@ -417,20 +418,19 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
                     AbstractFieldPanel<?> panel = getFieldPanel(schemas.get(attrTO.getSchema()));
                     if (schemas.get(attrTO.getSchema()).isMultivalue()) {
                         panel = new MultiFieldPanel.Builder<>(
-                            new PropertyModel<>(attrTO, "values")).build(
-                            "panel",
-                            attrTO.getSchema(),
-                            FieldPanel.class.cast(panel));
+                                new PropertyModel<>(attrTO, "values")).build(
+                                "panel",
+                                attrTO.getSchema(),
+                                FieldPanel.class.cast(panel));
                         // SYNCOPE-1215 the entire multifield panel must be readonly, not only its field
                         ((MultiFieldPanel) panel).setReadOnly(schema == null ? false : schema.isReadonly());
                     } else {
                         FieldPanel.class.cast(panel).setNewModel(attrTO.getValues()).
-                            setReadOnly(schema == null ? false : schema.isReadonly());
+                                setReadOnly(schema == null ? false : schema.isReadonly());
                     }
                     item.add(panel);
                 }
             });
         }
     }
-
 }
diff --git a/client/idrepo/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java b/client/idrepo/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
index e1d2a4c..148c625 100644
--- a/client/idrepo/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
+++ b/client/idrepo/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
@@ -21,7 +21,7 @@ package org.apache.syncope.client.lib;
 import org.apache.syncope.client.lib.batch.BatchRequest;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Base64;
@@ -70,7 +70,7 @@ public class SyncopeClient {
 
     protected static final String HEADER_SPLIT_PROPERTY = "org.apache.cxf.http.header.split";
 
-    protected static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+    protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     protected final MediaType mediaType;
 
@@ -155,7 +155,7 @@ public class SyncopeClient {
                 () -> webClient.header(HttpHeaders.AUTHORIZATION, "Basic " + Base64.getEncoder().encodeToString(
                         (restClientFactory.getUsername() + ":" + restClientFactory.getPassword()).getBytes())));
 
-        return OBJECT_MAPPER.readTree((InputStream) webClient.get().getEntity());
+        return MAPPER.readTree((InputStream) webClient.get().getEntity());
     }
 
     public Pair<String, String> gitAndBuildInfo() {
@@ -170,7 +170,7 @@ public class SyncopeClient {
 
     public PlatformInfo platform() {
         try {
-            return OBJECT_MAPPER.treeToValue(info().get("platform"), PlatformInfo.class);
+            return MAPPER.treeToValue(info().get("platform"), PlatformInfo.class);
         } catch (IOException e) {
             throw new RuntimeException("While getting Platform Info", e);
         }
@@ -178,7 +178,7 @@ public class SyncopeClient {
 
     public SystemInfo system() {
         try {
-            return OBJECT_MAPPER.treeToValue(info().get("system"), SystemInfo.class);
+            return MAPPER.treeToValue(info().get("system"), SystemInfo.class);
         } catch (IOException e) {
             throw new RuntimeException("While getting System Info", e);
         }
@@ -186,7 +186,7 @@ public class SyncopeClient {
 
     public NumbersInfo numbers() {
         try {
-            return OBJECT_MAPPER.treeToValue(info().get("numbers"), NumbersInfo.class);
+            return MAPPER.treeToValue(info().get("numbers"), NumbersInfo.class);
         } catch (IOException e) {
             throw new RuntimeException("While getting Numbers Info", e);
         }
@@ -366,15 +366,14 @@ public class SyncopeClient {
         }
 
         try {
-            return Triple.of(
-                    OBJECT_MAPPER.readValue(
-                            response.getHeaderString(RESTHeaders.OWNED_ENTITLEMENTS),
-                        new TypeReference<>() {
-                        }),
-                    OBJECT_MAPPER.readValue(
+            return Triple.of(MAPPER.readValue(
+                    response.getHeaderString(RESTHeaders.OWNED_ENTITLEMENTS),
+                    new TypeReference<>() {
+            }),
+                    MAPPER.readValue(
                             response.getHeaderString(RESTHeaders.DELEGATIONS),
-                        new TypeReference<>() {
-                        }),
+                            new TypeReference<>() {
+                    }),
                     response.readEntity(UserTO.class));
         } catch (IOException e) {
             throw new IllegalStateException(e);
diff --git a/client/idrepo/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java b/client/idrepo/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
index 04c6338..ab5abac 100644
--- a/client/idrepo/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
+++ b/client/idrepo/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
@@ -29,7 +29,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.cxf.configuration.jsse.TLSClientParameters;
 import org.apache.cxf.ext.logging.LoggingFeature;
 import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
-import org.apache.syncope.common.lib.jackson.SyncopeObjectMapper;
+import org.apache.syncope.common.lib.jackson.SyncopeJsonMapper;
 import org.apache.syncope.common.lib.jackson.SyncopeXmlMapper;
 import org.apache.syncope.common.lib.jackson.SyncopeYAMLMapper;
 import org.apache.syncope.common.rest.api.DateParamConverterProvider;
@@ -87,7 +87,7 @@ public class SyncopeClientFactoryBean {
     private JAXRSClientFactoryBean restClientFactoryBean;
 
     protected static JacksonJsonProvider defaultJsonProvider() {
-        return new JacksonJsonProvider(new SyncopeObjectMapper());
+        return new JacksonJsonProvider(new SyncopeJsonMapper());
     }
 
     protected static JacksonXMLProvider defaultXmlProvider() {
@@ -139,9 +139,7 @@ public class SyncopeClientFactoryBean {
     }
 
     public JacksonXMLProvider getXmlProvider() {
-        return xmlProvider == null
-                ? defaultXmlProvider()
-                : xmlProvider;
+        return Optional.ofNullable(xmlProvider).orElseGet(SyncopeClientFactoryBean::defaultXmlProvider);
     }
 
     public void setXmlProvider(final JacksonXMLProvider xmlProvider) {
@@ -149,9 +147,7 @@ public class SyncopeClientFactoryBean {
     }
 
     public JacksonYAMLProvider getYamlProvider() {
-        return yamlProvider == null
-                ? defaultYamlProvider()
-                : yamlProvider;
+        return Optional.ofNullable(yamlProvider).orElseGet(SyncopeClientFactoryBean::defaultYamlProvider);
     }
 
     public void setYamlProvider(final JacksonYAMLProvider yamlProvider) {
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/AMSession.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/AMSession.java
index 1636555..34ba088 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/AMSession.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/AMSession.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.common.lib;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import org.apache.syncope.common.lib.to.EntityTO;
 
 public class AMSession implements EntityTO {
@@ -27,7 +27,7 @@ public class AMSession implements EntityTO {
 
     private String key;
 
-    private Date authenticationDate;
+    private OffsetDateTime authenticationDate;
 
     private String principal;
 
@@ -43,11 +43,11 @@ public class AMSession implements EntityTO {
         this.key = key;
     }
 
-    public Date getAuthenticationDate() {
+    public OffsetDateTime getAuthenticationDate() {
         return authenticationDate;
     }
 
-    public void setAuthenticationDate(final Date authenticationDate) {
+    public void setAuthenticationDate(final OffsetDateTime authenticationDate) {
         this.authenticationDate = authenticationDate;
     }
 
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/GoogleMfaAuthAccount.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/GoogleMfaAuthAccount.java
index 8a185bc..fc01b3d 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/GoogleMfaAuthAccount.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/GoogleMfaAuthAccount.java
@@ -18,10 +18,9 @@
  */
 package org.apache.syncope.common.lib.wa;
 
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
-import java.util.Optional;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.commons.lang3.builder.ToStringBuilder;
@@ -35,7 +34,7 @@ public class GoogleMfaAuthAccount implements BaseBean {
 
         private final GoogleMfaAuthAccount instance = new GoogleMfaAuthAccount();
 
-        public GoogleMfaAuthAccount.Builder registrationDate(final Date date) {
+        public GoogleMfaAuthAccount.Builder registrationDate(final OffsetDateTime date) {
             instance.setRegistrationDate(date);
             return this;
         }
@@ -80,7 +79,7 @@ public class GoogleMfaAuthAccount implements BaseBean {
 
     private List<Integer> scratchCodes = new ArrayList<>(0);
 
-    private Date registrationDate;
+    private OffsetDateTime registrationDate;
 
     public String getName() {
         return name;
@@ -122,14 +121,12 @@ public class GoogleMfaAuthAccount implements BaseBean {
         this.scratchCodes = scratchCodes;
     }
 
-    public Date getRegistrationDate() {
-        return Optional.ofNullable(this.registrationDate).
-                map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getRegistrationDate() {
+        return registrationDate;
     }
 
-    public void setRegistrationDate(final Date registrationDate) {
-        this.registrationDate = Optional.ofNullable(registrationDate).
-                map(date -> new Date(date.getTime())).orElse(null);
+    public void setRegistrationDate(final OffsetDateTime registrationDate) {
+        this.registrationDate = registrationDate;
     }
 
     @Override
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/GoogleMfaAuthToken.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/GoogleMfaAuthToken.java
index a19d6ec..055f41b 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/GoogleMfaAuthToken.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/GoogleMfaAuthToken.java
@@ -18,8 +18,7 @@
  */
 package org.apache.syncope.common.lib.wa;
 
-import java.util.Date;
-import java.util.Optional;
+import java.time.OffsetDateTime;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.commons.lang3.builder.ToStringBuilder;
@@ -33,8 +32,8 @@ public class GoogleMfaAuthToken implements BaseBean {
 
         private final GoogleMfaAuthToken instance = new GoogleMfaAuthToken();
 
-        public GoogleMfaAuthToken.Builder issueDate(final Date issued) {
-            instance.setIssueDate(issued);
+        public GoogleMfaAuthToken.Builder issueDate(final OffsetDateTime issueDate) {
+            instance.setIssueDate(issueDate);
             return this;
         }
 
@@ -50,7 +49,7 @@ public class GoogleMfaAuthToken implements BaseBean {
 
     private int otp;
 
-    private Date issueDate;
+    private OffsetDateTime issueDate;
 
     public int getOtp() {
         return otp;
@@ -60,14 +59,12 @@ public class GoogleMfaAuthToken implements BaseBean {
         this.otp = otp;
     }
 
-    public Date getIssueDate() {
-        return Optional.ofNullable(this.issueDate).
-                map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getIssueDate() {
+        return issueDate;
     }
 
-    public void setIssueDate(final Date issueDate) {
-        this.issueDate = Optional.ofNullable(issueDate).
-                map(date -> new Date(date.getTime())).orElse(null);
+    public void setIssueDate(final OffsetDateTime issueDate) {
+        this.issueDate = issueDate;
     }
 
     @Override
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/U2FDevice.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/U2FDevice.java
index 106b9b6..54abb47 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/U2FDevice.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/U2FDevice.java
@@ -18,8 +18,7 @@
  */
 package org.apache.syncope.common.lib.wa;
 
-import java.util.Date;
-import java.util.Optional;
+import java.time.OffsetDateTime;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.commons.lang3.builder.ToStringBuilder;
@@ -33,7 +32,7 @@ public class U2FDevice implements BaseBean {
 
         private final U2FDevice instance = new U2FDevice();
 
-        public U2FDevice.Builder issueDate(final Date issued) {
+        public U2FDevice.Builder issueDate(final OffsetDateTime issued) {
             instance.setIssueDate(issued);
             return this;
         }
@@ -57,7 +56,7 @@ public class U2FDevice implements BaseBean {
 
     private String record;
 
-    private Date issueDate;
+    private OffsetDateTime issueDate;
 
     public String getRecord() {
         return record;
@@ -75,14 +74,12 @@ public class U2FDevice implements BaseBean {
         this.id = id;
     }
 
-    public Date getIssueDate() {
-        return Optional.ofNullable(this.issueDate).
-                map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getIssueDate() {
+        return issueDate;
     }
 
-    public void setIssueDate(final Date issueDate) {
-        this.issueDate = Optional.ofNullable(issueDate).
-                map(date -> new Date(date.getTime())).orElse(null);
+    public void setIssueDate(final OffsetDateTime issueDate) {
+        this.issueDate = issueDate;
     }
 
     @Override
diff --git a/common/am/lib/src/test/java/org/apache/syncope/common/lib/JSONTest.java b/common/am/lib/src/test/java/org/apache/syncope/common/lib/JSONTest.java
index 14d547d..adb47a8 100644
--- a/common/am/lib/src/test/java/org/apache/syncope/common/lib/JSONTest.java
+++ b/common/am/lib/src/test/java/org/apache/syncope/common/lib/JSONTest.java
@@ -19,10 +19,11 @@
 package org.apache.syncope.common.lib;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.syncope.common.lib.jackson.SyncopeJsonMapper;
 
 public class JSONTest extends SerializationTest {
 
-    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+    private static final ObjectMapper OBJECT_MAPPER = new SyncopeJsonMapper();
 
     @Override
     protected ObjectMapper objectMapper() {
diff --git a/common/am/lib/src/test/java/org/apache/syncope/common/lib/YAMLTest.java b/common/am/lib/src/test/java/org/apache/syncope/common/lib/YAMLTest.java
index 5ff4900..093322a 100644
--- a/common/am/lib/src/test/java/org/apache/syncope/common/lib/YAMLTest.java
+++ b/common/am/lib/src/test/java/org/apache/syncope/common/lib/YAMLTest.java
@@ -20,10 +20,11 @@ package org.apache.syncope.common.lib;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
+import org.apache.syncope.common.lib.jackson.SyncopeYAMLMapper;
 
 public class YAMLTest extends SerializationTest {
 
-    private static final YAMLMapper YAML_MAPPER = new YAMLMapper();
+    private static final YAMLMapper YAML_MAPPER = new SyncopeYAMLMapper();
 
     @Override
     protected ObjectMapper objectMapper() {
diff --git a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/U2FDeviceQuery.java b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/U2FDeviceQuery.java
index 5e9f930..55422cc 100644
--- a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/U2FDeviceQuery.java
+++ b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/U2FDeviceQuery.java
@@ -21,7 +21,7 @@ package org.apache.syncope.common.rest.api.beans;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.enums.ParameterIn;
 import io.swagger.v3.oas.annotations.media.Schema;
-import java.util.Date;
+import java.time.OffsetDateTime;
 import javax.ws.rs.QueryParam;
 
 public class U2FDeviceQuery extends AbstractQuery {
@@ -45,7 +45,7 @@ public class U2FDeviceQuery extends AbstractQuery {
             return this;
         }
 
-        public U2FDeviceQuery.Builder expirationDate(final Date date) {
+        public U2FDeviceQuery.Builder expirationDate(final OffsetDateTime date) {
             getInstance().setExpirationDate(date);
             return this;
         }
@@ -53,7 +53,7 @@ public class U2FDeviceQuery extends AbstractQuery {
 
     private Long id;
 
-    private Date expirationDate;
+    private OffsetDateTime expirationDate;
 
     private String owner;
 
@@ -69,13 +69,13 @@ public class U2FDeviceQuery extends AbstractQuery {
     }
 
     @Parameter(name = "expirationDate", in = ParameterIn.QUERY, schema =
-            @Schema(implementation = Date.class))
-    public Date getExpirationDate() {
+            @Schema(implementation = OffsetDateTime.class))
+    public OffsetDateTime getExpirationDate() {
         return expirationDate;
     }
 
     @QueryParam("expirationDate")
-    public void setExpirationDate(final Date expirationDate) {
+    public void setExpirationDate(final OffsetDateTime expirationDate) {
         this.expirationDate = expirationDate;
     }
 
diff --git a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/wa/GoogleMfaAuthTokenService.java b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/wa/GoogleMfaAuthTokenService.java
index f070460..40a1d9e 100644
--- a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/wa/GoogleMfaAuthTokenService.java
+++ b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/wa/GoogleMfaAuthTokenService.java
@@ -18,20 +18,20 @@
  */
 package org.apache.syncope.common.rest.api.service.wa;
 
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.security.SecurityRequirements;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import java.time.OffsetDateTime;
 import javax.validation.constraints.NotNull;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
-import java.util.Date;
-import io.swagger.v3.oas.annotations.security.SecurityRequirement;
-import io.swagger.v3.oas.annotations.security.SecurityRequirements;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import javax.ws.rs.PUT;
 import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.wa.GoogleMfaAuthToken;
 import org.apache.syncope.common.rest.api.RESTHeaders;
@@ -48,7 +48,7 @@ public interface GoogleMfaAuthTokenService extends JAXRSService {
     @Path("tokens")
     @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    void delete(@QueryParam("expirationDate") Date expirationDate);
+    void delete(@QueryParam("expirationDate") OffsetDateTime expirationDate);
 
     @DELETE
     @Path("tokens/{owner}/{otp}")
diff --git a/common/idm/lib/src/main/java/org/apache/syncope/common/lib/to/RemediationTO.java b/common/idm/lib/src/main/java/org/apache/syncope/common/lib/to/RemediationTO.java
index 8f7528a..41441e2 100644
--- a/common/idm/lib/src/main/java/org/apache/syncope/common/lib/to/RemediationTO.java
+++ b/common/idm/lib/src/main/java/org/apache/syncope/common/lib/to/RemediationTO.java
@@ -19,8 +19,7 @@
 package org.apache.syncope.common.lib.to;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import java.util.Date;
-import java.util.Optional;
+import java.time.OffsetDateTime;
 import javax.ws.rs.PathParam;
 import org.apache.syncope.common.lib.request.AnyCR;
 import org.apache.syncope.common.lib.request.AnyUR;
@@ -44,7 +43,7 @@ public class RemediationTO implements EntityTO {
 
     private String error;
 
-    private Date instant;
+    private OffsetDateTime instant;
 
     private String pullTask;
 
@@ -118,12 +117,12 @@ public class RemediationTO implements EntityTO {
     }
 
     @Schema(accessMode = Schema.AccessMode.READ_ONLY)
-    public Date getInstant() {
-        return Optional.ofNullable(instant).map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getInstant() {
+        return instant;
     }
 
-    public void setInstant(final Date instant) {
-        this.instant = Optional.ofNullable(instant).map(date -> new Date(date.getTime())).orElse(null);
+    public void setInstant(final OffsetDateTime instant) {
+        this.instant = instant;
     }
 
     @Schema(accessMode = Schema.AccessMode.READ_ONLY)
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java
index c2ff132..0be18e0 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java
@@ -41,8 +41,6 @@ public final class SyncopeConstants {
         "yyyy-MM-dd HH:mm:ss.S", // explicitly added to import date into MySql repository
         "yyyy-MM-dd" };
 
-    public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZ";
-
     public static final String UUID_REGEX = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
 
     public static final Pattern UUID_PATTERN = Pattern.compile(UUID_REGEX);
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/audit/AuditEntry.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/audit/AuditEntry.java
index 4fe9aa2..34ef1aa 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/audit/AuditEntry.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/audit/AuditEntry.java
@@ -21,8 +21,8 @@ package org.apache.syncope.common.lib.audit;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
@@ -35,7 +35,7 @@ public class AuditEntry implements BaseBean {
 
     private String who;
 
-    private Date date;
+    private OffsetDateTime date;
 
     private AuditLoggerName logger;
 
@@ -57,16 +57,12 @@ public class AuditEntry implements BaseBean {
     }
 
     @Schema(accessMode = Schema.AccessMode.READ_ONLY)
-    public Date getDate() {
-        return date == null
-                ? null
-                : new Date(date.getTime());
+    public OffsetDateTime getDate() {
+        return date;
     }
 
-    public void setDate(final Date date) {
-        this.date = date == null
-                ? null
-                : new Date(date.getTime());
+    public void setDate(final OffsetDateTime date) {
+        this.date = date;
     }
 
     @Schema(accessMode = Schema.AccessMode.READ_ONLY)
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/jackson/SyncopeObjectMapper.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/jackson/SyncopeJsonMapper.java
similarity index 93%
rename from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/jackson/SyncopeObjectMapper.java
rename to common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/jackson/SyncopeJsonMapper.java
index a8cce7e..403403e 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/jackson/SyncopeObjectMapper.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/jackson/SyncopeJsonMapper.java
@@ -20,8 +20,8 @@ package org.apache.syncope.common.lib.jackson;
 
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.File;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -32,11 +32,11 @@ import java.util.Map;
  * Jackson ObjectMapper that unwraps singleton map values and enable default
  * typing for handling abstract types serialization.
  */
-public class SyncopeObjectMapper extends ObjectMapper {
+public class SyncopeJsonMapper extends JsonMapper {
 
     private static final long serialVersionUID = -317191546835195103L;
 
-    public SyncopeObjectMapper() {
+    public SyncopeJsonMapper() {
         super();
 
         findAndRegisterModules();
@@ -51,7 +51,7 @@ public class SyncopeObjectMapper extends ObjectMapper {
      * @param value the potential Map to unwrap
      * @return the unwrapped map or the original value
      */
-    private Object unwrapMap(final Object value) {
+    protected Object unwrapMap(final Object value) {
         if (value instanceof Map) {
             Map<?, ?> map = (Map<?, ?>) value;
             if (map.size() == 1) {
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java
index 23adbea..17aacc0 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java
@@ -20,10 +20,9 @@ package org.apache.syncope.common.lib.report;
 
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
-import java.util.Optional;
 import org.apache.syncope.common.lib.types.TraceLevel;
 
 public class StaticReportletConf extends AbstractReportletConf {
@@ -36,7 +35,7 @@ public class StaticReportletConf extends AbstractReportletConf {
 
     private Double doubleField;
 
-    private Date dateField;
+    private OffsetDateTime dateField;
 
     private TraceLevel traceLevel;
 
@@ -50,12 +49,12 @@ public class StaticReportletConf extends AbstractReportletConf {
         super(name);
     }
 
-    public Date getDateField() {
-        return Optional.ofNullable(dateField).map(field -> new Date(field.getTime())).orElse(null);
+    public OffsetDateTime getDateField() {
+        return dateField;
     }
 
-    public void setDateField(final Date dateField) {
-        this.dateField = Optional.ofNullable(dateField).map(field -> new Date(field.getTime())).orElse(null);
+    public void setDateField(final OffsetDateTime dateField) {
+        this.dateField = dateField;
     }
 
     public Double getDoubleField() {
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractStartEndBean.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractStartEndBean.java
index f88e54a..c4cb83d 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractStartEndBean.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractStartEndBean.java
@@ -19,8 +19,7 @@
 package org.apache.syncope.common.lib.to;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import java.util.Date;
-import java.util.Optional;
+import java.time.OffsetDateTime;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.commons.lang3.builder.ToStringBuilder;
@@ -31,26 +30,26 @@ public class AbstractStartEndBean implements BaseBean {
 
     private static final long serialVersionUID = 2399577415544539917L;
 
-    private Date start;
+    private OffsetDateTime start;
 
-    private Date end;
+    private OffsetDateTime end;
 
     @Schema(accessMode = Schema.AccessMode.READ_ONLY)
-    public Date getStart() {
-        return Optional.ofNullable(start).map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getStart() {
+        return start;
     }
 
-    public void setStart(final Date start) {
-        this.start = Optional.ofNullable(start).map(date -> new Date(date.getTime())).orElse(null);
+    public void setStart(final OffsetDateTime start) {
+        this.start = start;
     }
 
     @Schema(accessMode = Schema.AccessMode.READ_ONLY)
-    public Date getEnd() {
-        return Optional.ofNullable(end).map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getEnd() {
+        return end;
     }
 
-    public void setEnd(final Date end) {
-        this.end = Optional.ofNullable(end).map(date -> new Date(date.getTime())).orElse(null);
+    public void setEnd(final OffsetDateTime end) {
+        this.end = end;
     }
 
     @Override
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AccessTokenTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AccessTokenTO.java
index ec9cb05..358af83 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AccessTokenTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AccessTokenTO.java
@@ -18,8 +18,7 @@
  */
 package org.apache.syncope.common.lib.to;
 
-import java.util.Date;
-import java.util.Optional;
+import java.time.OffsetDateTime;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 
@@ -31,7 +30,7 @@ public class AccessTokenTO implements EntityTO {
 
     private String body;
 
-    private Date expirationTime;
+    private OffsetDateTime expirationTime;
 
     private String owner;
 
@@ -53,12 +52,12 @@ public class AccessTokenTO implements EntityTO {
         this.body = body;
     }
 
-    public Date getExpirationTime() {
-        return Optional.ofNullable(expirationTime).map(time -> new Date(time.getTime())).orElse(null);
+    public OffsetDateTime getExpirationTime() {
+        return expirationTime;
     }
 
-    public void setExpirationTime(final Date expirationTime) {
-        this.expirationTime = Optional.ofNullable(expirationTime).map(time -> new Date(time.getTime())).orElse(null);
+    public void setExpirationTime(final OffsetDateTime expirationTime) {
+        this.expirationTime = expirationTime;
     }
 
     public String getOwner() {
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
index bdc9a8a..fbe5b14 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
@@ -26,8 +26,8 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.TreeSet;
 import java.util.List;
 import java.util.Optional;
@@ -53,7 +53,7 @@ public abstract class AnyTO implements EntityTO, RealmMember {
      */
     private String creator;
 
-    private Date creationDate;
+    private OffsetDateTime creationDate;
 
     /**
      * Context information about create.
@@ -65,7 +65,7 @@ public abstract class AnyTO implements EntityTO, RealmMember {
      */
     private String lastModifier;
 
-    private Date lastChangeDate;
+    private OffsetDateTime lastChangeDate;
 
     /**
      * Context information about last change.
@@ -107,12 +107,12 @@ public abstract class AnyTO implements EntityTO, RealmMember {
         this.creator = creator;
     }
 
-    public Date getCreationDate() {
-        return Optional.ofNullable(creationDate).map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getCreationDate() {
+        return creationDate;
     }
 
-    public void setCreationDate(final Date creationDate) {
-        this.creationDate = Optional.ofNullable(creationDate).map(date -> new Date(date.getTime())).orElse(null);
+    public void setCreationDate(final OffsetDateTime creationDate) {
+        this.creationDate = creationDate;
     }
 
     public String getCreationContext() {
@@ -131,12 +131,12 @@ public abstract class AnyTO implements EntityTO, RealmMember {
         this.lastModifier = lastModifier;
     }
 
-    public Date getLastChangeDate() {
-        return Optional.ofNullable(lastChangeDate).map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getLastChangeDate() {
+        return lastChangeDate;
     }
 
-    public void setLastChangeDate(final Date lastChangeDate) {
-        this.lastChangeDate = Optional.ofNullable(lastChangeDate).map(date -> new Date(date.getTime())).orElse(null);
+    public void setLastChangeDate(final OffsetDateTime lastChangeDate) {
+        this.lastChangeDate = lastChangeDate;
     }
 
     public String getLastChangeContext() {
@@ -149,9 +149,11 @@ public abstract class AnyTO implements EntityTO, RealmMember {
 
     @JsonIgnore
     public String getETagValue() {
-        Date etagDate = getLastChangeDate() == null
+        OffsetDateTime etagDate = getLastChangeDate() == null
                 ? getCreationDate() : getLastChangeDate();
-        return Optional.ofNullable(etagDate).map(date -> String.valueOf(date.getTime())).orElse(StringUtils.EMPTY);
+        return Optional.ofNullable(etagDate).
+                map(date -> String.valueOf(date.toInstant().toEpochMilli())).
+                orElse(StringUtils.EMPTY);
     }
 
     @Override
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/DelegationTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/DelegationTO.java
index 36c75b7..a9a7457 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/DelegationTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/DelegationTO.java
@@ -21,7 +21,7 @@ package org.apache.syncope.common.lib.to;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.Set;
 import java.util.TreeSet;
 import javax.ws.rs.PathParam;
@@ -77,13 +77,13 @@ public class DelegationTO extends AbstractStartEndBean implements EntityTO {
 
     @Schema(accessMode = Schema.AccessMode.READ_WRITE)
     @Override
-    public Date getStart() {
+    public OffsetDateTime getStart() {
         return super.getStart();
     }
 
     @Schema(accessMode = Schema.AccessMode.READ_WRITE)
     @Override
-    public Date getEnd() {
+    public OffsetDateTime getEnd() {
         return super.getEnd();
     }
 
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/JobTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/JobTO.java
index 58d9fce..da0ecea 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/JobTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/JobTO.java
@@ -18,8 +18,7 @@
  */
 package org.apache.syncope.common.lib.to;
 
-import java.util.Date;
-import java.util.Optional;
+import java.time.OffsetDateTime;
 import org.apache.syncope.common.lib.BaseBean;
 import org.apache.syncope.common.lib.types.JobType;
 
@@ -37,7 +36,7 @@ public class JobTO implements BaseBean {
 
     private boolean scheduled;
 
-    private Date start;
+    private OffsetDateTime start;
 
     private String status;
 
@@ -81,12 +80,12 @@ public class JobTO implements BaseBean {
         this.scheduled = scheduled;
     }
 
-    public Date getStart() {
-        return Optional.ofNullable(start).map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getStart() {
+        return start;
     }
 
-    public void setStart(final Date start) {
-        this.start = Optional.ofNullable(start).map(date -> new Date(date.getTime())).orElse(null);
+    public void setStart(final OffsetDateTime start) {
+        this.start = start;
     }
 
     public String getStatus() {
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/ReportTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/ReportTO.java
index 364ea00..0bb1055 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/ReportTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/ReportTO.java
@@ -20,10 +20,9 @@ package org.apache.syncope.common.lib.to;
 
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
-import java.util.Optional;
 import javax.ws.rs.PathParam;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
@@ -44,9 +43,9 @@ public class ReportTO extends AbstractStartEndBean implements NamedEntityTO {
 
     private String latestExecStatus;
 
-    private Date lastExec;
+    private OffsetDateTime lastExec;
 
-    private Date nextExec;
+    private OffsetDateTime nextExec;
 
     private boolean active;
 
@@ -103,20 +102,20 @@ public class ReportTO extends AbstractStartEndBean implements NamedEntityTO {
         this.latestExecStatus = latestExecStatus;
     }
 
-    public Date getLastExec() {
-        return Optional.ofNullable(lastExec).map(exec -> new Date(exec.getTime())).orElse(null);
+    public OffsetDateTime getLastExec() {
+        return lastExec;
     }
 
-    public void setLastExec(final Date lastExec) {
-        this.lastExec = Optional.ofNullable(lastExec).map(exec -> new Date(exec.getTime())).orElse(null);
+    public void setLastExec(final OffsetDateTime lastExec) {
+        this.lastExec = lastExec;
     }
 
-    public Date getNextExec() {
-        return Optional.ofNullable(nextExec).map(exec -> new Date(exec.getTime())).orElse(null);
+    public OffsetDateTime getNextExec() {
+        return nextExec;
     }
 
-    public void setNextExec(final Date nextExec) {
-        this.nextExec = Optional.ofNullable(nextExec).map(exec -> new Date(exec.getTime())).orElse(null);
+    public void setNextExec(final OffsetDateTime nextExec) {
+        this.nextExec = nextExec;
     }
 
     public boolean isActive() {
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/SchedTaskTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/SchedTaskTO.java
index 75d7b40..49a8549 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/SchedTaskTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/SchedTaskTO.java
@@ -21,8 +21,7 @@ package org.apache.syncope.common.lib.to;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
-import java.util.Date;
-import java.util.Optional;
+import java.time.OffsetDateTime;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 
@@ -31,7 +30,7 @@ public class SchedTaskTO extends TaskTO implements NamedEntityTO {
 
     private static final long serialVersionUID = -5722284116974636425L;
 
-    private Date startAt;
+    private OffsetDateTime startAt;
 
     private String cronExpression;
 
@@ -41,9 +40,9 @@ public class SchedTaskTO extends TaskTO implements NamedEntityTO {
 
     private String description;
 
-    private Date lastExec;
+    private OffsetDateTime lastExec;
 
-    private Date nextExec;
+    private OffsetDateTime nextExec;
 
     private boolean active = true;
 
@@ -55,12 +54,12 @@ public class SchedTaskTO extends TaskTO implements NamedEntityTO {
         return getClass().getName();
     }
 
-    public Date getStartAt() {
-        return Optional.ofNullable(startAt).map(at -> new Date(at.getTime())).orElse(null);
+    public OffsetDateTime getStartAt() {
+        return startAt;
     }
 
-    public void setStartAt(final Date start) {
-        this.startAt = Optional.ofNullable(start).map(date -> new Date(date.getTime())).orElse(null);
+    public void setStartAt(final OffsetDateTime startAt) {
+        this.startAt = startAt;
     }
 
     public String getCronExpression() {
@@ -80,21 +79,21 @@ public class SchedTaskTO extends TaskTO implements NamedEntityTO {
     }
 
     @Schema(accessMode = Schema.AccessMode.READ_ONLY)
-    public Date getLastExec() {
-        return Optional.ofNullable(lastExec).map(exec -> new Date(exec.getTime())).orElse(null);
+    public OffsetDateTime getLastExec() {
+        return lastExec;
     }
 
-    public void setLastExec(final Date lastExec) {
-        this.lastExec = Optional.ofNullable(lastExec).map(exec -> new Date(exec.getTime())).orElse(null);
+    public void setLastExec(final OffsetDateTime lastExec) {
+        this.lastExec = lastExec;
     }
 
     @Schema(accessMode = Schema.AccessMode.READ_ONLY)
-    public Date getNextExec() {
-        return Optional.ofNullable(nextExec).map(exec -> new Date(exec.getTime())).orElse(null);
+    public OffsetDateTime getNextExec() {
+        return nextExec;
     }
 
-    public void setNextExec(final Date nextExec) {
-        this.nextExec = Optional.ofNullable(nextExec).map(exec -> new Date(exec.getTime())).orElse(null);
+    public void setNextExec(final OffsetDateTime nextExec) {
+        this.nextExec = nextExec;
     }
 
     public String getDescription() {
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
index 0417837..4c547d7 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
@@ -23,8 +23,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
@@ -42,13 +42,13 @@ public class UserTO extends AnyTO implements GroupableRelatableTO {
 
     private String token;
 
-    private Date tokenExpireTime;
+    private OffsetDateTime tokenExpireTime;
 
     private String username;
 
-    private Date lastLoginDate;
+    private OffsetDateTime lastLoginDate;
 
-    private Date changePwdDate;
+    private OffsetDateTime changePwdDate;
 
     private Integer failedLogins;
 
@@ -112,19 +112,12 @@ public class UserTO extends AnyTO implements GroupableRelatableTO {
         this.token = token;
     }
 
-    public Date getTokenExpireTime() {
-        if (tokenExpireTime != null) {
-            return new Date(tokenExpireTime.getTime());
-        }
-        return null;
+    public OffsetDateTime getTokenExpireTime() {
+        return tokenExpireTime;
     }
 
-    public void setTokenExpireTime(final Date tokenExpireTime) {
-        if (tokenExpireTime != null) {
-            this.tokenExpireTime = new Date(tokenExpireTime.getTime());
-        } else {
-            this.tokenExpireTime = null;
-        }
+    public void setTokenExpireTime(final OffsetDateTime tokenExpireTime) {
+        this.tokenExpireTime = tokenExpireTime;
     }
 
     @JsonProperty(required = true)
@@ -136,42 +129,28 @@ public class UserTO extends AnyTO implements GroupableRelatableTO {
         this.username = username;
     }
 
-    public Date getChangePwdDate() {
-        if (changePwdDate != null) {
-            return new Date(changePwdDate.getTime());
-        }
-        return null;
+    public OffsetDateTime getChangePwdDate() {
+        return changePwdDate;
     }
 
     public Integer getFailedLogins() {
         return failedLogins;
     }
 
-    public Date getLastLoginDate() {
-        if (lastLoginDate != null) {
-            return new Date(lastLoginDate.getTime());
-        }
-        return null;
+    public OffsetDateTime getLastLoginDate() {
+        return lastLoginDate;
     }
 
-    public void setChangePwdDate(final Date changePwdDate) {
-        if (changePwdDate != null) {
-            this.changePwdDate = new Date(changePwdDate.getTime());
-        } else {
-            this.changePwdDate = null;
-        }
+    public void setChangePwdDate(final OffsetDateTime changePwdDate) {
+        this.changePwdDate = changePwdDate;
     }
 
     public void setFailedLogins(final Integer failedLogins) {
         this.failedLogins = failedLogins;
     }
 
-    public void setLastLoginDate(final Date lastLoginDate) {
-        if (lastLoginDate != null) {
-            this.lastLoginDate = new Date(lastLoginDate.getTime());
-        } else {
-            this.lastLoginDate = null;
-        }
+    public void setLastLoginDate(final OffsetDateTime lastLoginDate) {
+        this.lastLoginDate = lastLoginDate;
     }
 
     public String getSecurityQuestion() {
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/AttrSchemaType.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/AttrSchemaType.java
index 86fd8a8..283cf47 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/AttrSchemaType.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/AttrSchemaType.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.common.lib.types;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.stream.Stream;
 import org.apache.commons.lang3.ClassUtils;
 
@@ -28,7 +28,7 @@ public enum AttrSchemaType {
     Long(Long.class),
     Double(Double.class),
     Boolean(Boolean.class),
-    Date(Date.class),
+    Date(OffsetDateTime.class),
     Enum(Enum.class),
     Binary(byte[].class),
     Encrypted(byte[].class);
@@ -56,5 +56,4 @@ public enum AttrSchemaType {
                 : ClassUtils.isAssignable(type, item.getType(), true)).
                 findFirst().orElse(AttrSchemaType.String);
     }
-
 }
diff --git a/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/JSONTest.java b/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/JSONTest.java
index 14d547d..adb47a8 100644
--- a/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/JSONTest.java
+++ b/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/JSONTest.java
@@ -19,10 +19,11 @@
 package org.apache.syncope.common.lib;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.syncope.common.lib.jackson.SyncopeJsonMapper;
 
 public class JSONTest extends SerializationTest {
 
-    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+    private static final ObjectMapper OBJECT_MAPPER = new SyncopeJsonMapper();
 
     @Override
     protected ObjectMapper objectMapper() {
diff --git a/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/YAMLTest.java b/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/YAMLTest.java
index 5ff4900..093322a 100644
--- a/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/YAMLTest.java
+++ b/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/YAMLTest.java
@@ -20,10 +20,11 @@ package org.apache.syncope.common.lib;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
+import org.apache.syncope.common.lib.jackson.SyncopeYAMLMapper;
 
 public class YAMLTest extends SerializationTest {
 
-    private static final YAMLMapper YAML_MAPPER = new YAMLMapper();
+    private static final YAMLMapper YAML_MAPPER = new SyncopeYAMLMapper();
 
     @Override
     protected ObjectMapper objectMapper() {
diff --git a/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/types/AttrSchemaTypeTest.java b/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/types/AttrSchemaTypeTest.java
index eb447cf..71963ca 100644
--- a/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/types/AttrSchemaTypeTest.java
+++ b/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/types/AttrSchemaTypeTest.java
@@ -20,7 +20,7 @@ package org.apache.syncope.common.lib.types;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.junit.jupiter.api.Test;
 
@@ -46,7 +46,7 @@ public class AttrSchemaTypeTest {
 
     @Test
     void checkDate() {
-        assertEquals(AttrSchemaType.Date, AttrSchemaType.getAttrSchemaTypeByClass(Date.class));
+        assertEquals(AttrSchemaType.Date, AttrSchemaType.getAttrSchemaTypeByClass(OffsetDateTime.class));
     }
 
     @Test
diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/DateParamConverterProvider.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/DateParamConverterProvider.java
index 1a826fd..0d2c943 100644
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/DateParamConverterProvider.java
+++ b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/DateParamConverterProvider.java
@@ -20,31 +20,28 @@ package org.apache.syncope.common.rest.api;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
-import java.text.ParseException;
-import java.util.Date;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
 import javax.ws.rs.ext.ParamConverter;
 import javax.ws.rs.ext.ParamConverterProvider;
-import org.apache.commons.lang3.time.FastDateFormat;
-import org.apache.syncope.common.lib.SyncopeConstants;
 
 public class DateParamConverterProvider implements ParamConverterProvider {
 
-    private static final FastDateFormat DATE_FORMAT = FastDateFormat.getInstance(SyncopeConstants.DEFAULT_DATE_PATTERN);
-
-    private static class DateParamConverter implements ParamConverter<Date> {
+    private static class DateParamConverter implements ParamConverter<OffsetDateTime> {
 
         @Override
-        public Date fromString(final String value) {
+        public OffsetDateTime fromString(final String value) {
             try {
-                return DATE_FORMAT.parse(value);
-            } catch (final ParseException e) {
+                return OffsetDateTime.parse(value, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+            } catch (DateTimeParseException e) {
                 throw new IllegalArgumentException("Unparsable date: " + value, e);
             }
         }
 
         @Override
-        public String toString(final Date value) {
-            return DATE_FORMAT.format(value);
+        public String toString(final OffsetDateTime value) {
+            return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value);
         }
     }
 
@@ -53,11 +50,10 @@ public class DateParamConverterProvider implements ParamConverterProvider {
     public <T> ParamConverter<T> getConverter(
             final Class<T> rawType, final Type genericType, final Annotation[] annotations) {
 
-        if (Date.class.equals(rawType)) {
+        if (OffsetDateTime.class.equals(rawType)) {
             return (ParamConverter<T>) new DateParamConverter();
         }
 
         return null;
     }
-
 }
diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecDeleteQuery.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecDeleteQuery.java
index 664a705..a3e6f0e 100644
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecDeleteQuery.java
+++ b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecDeleteQuery.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.common.rest.api.beans;
 
 import java.io.Serializable;
-import java.util.Date;
+import java.time.OffsetDateTime;
 import javax.validation.constraints.NotNull;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.QueryParam;
@@ -37,22 +37,22 @@ public class ExecDeleteQuery implements Serializable {
             return this;
         }
 
-        public Builder startedBefore(final Date date) {
+        public Builder startedBefore(final OffsetDateTime date) {
             instance.setStartedBefore(date);
             return this;
         }
 
-        public Builder startedAfter(final Date date) {
+        public Builder startedAfter(final OffsetDateTime date) {
             instance.setStartedAfter(date);
             return this;
         }
 
-        public Builder endedBefore(final Date date) {
+        public Builder endedBefore(final OffsetDateTime date) {
             instance.setEndedBefore(date);
             return this;
         }
 
-        public Builder endedAfter(final Date date) {
+        public Builder endedAfter(final OffsetDateTime date) {
             instance.setEndedAfter(date);
             return this;
         }
@@ -64,13 +64,13 @@ public class ExecDeleteQuery implements Serializable {
 
     private String key;
 
-    private Date startedBefore;
+    private OffsetDateTime startedBefore;
 
-    private Date startedAfter;
+    private OffsetDateTime startedAfter;
 
-    private Date endedBefore;
+    private OffsetDateTime endedBefore;
 
-    private Date endedAfter;
+    private OffsetDateTime endedAfter;
 
     public String getKey() {
         return key;
@@ -82,67 +82,39 @@ public class ExecDeleteQuery implements Serializable {
         this.key = key;
     }
 
-    public Date getStartedBefore() {
-        if (startedBefore != null) {
-            return new Date(startedBefore.getTime());
-        }
-        return null;
+    public OffsetDateTime getStartedBefore() {
+        return startedBefore;
     }
 
     @QueryParam("startedBefore")
-    public void setStartedBefore(final Date startedBefore) {
-        if (startedBefore != null) {
-            this.startedBefore = new Date(startedBefore.getTime());
-        } else {
-            this.startedBefore = null;
-        }
+    public void setStartedBefore(final OffsetDateTime startedBefore) {
+        this.startedBefore = startedBefore;
     }
 
-    public Date getStartedAfter() {
-        if (startedAfter != null) {
-            return new Date(startedAfter.getTime());
-        }
-        return null;
+    public OffsetDateTime getStartedAfter() {
+        return startedAfter;
     }
 
     @QueryParam("startedAfter")
-    public void setStartedAfter(final Date startedAfter) {
-        if (startedAfter != null) {
-            this.startedAfter = new Date(startedAfter.getTime());
-        } else {
-            this.startedAfter = null;
-        }
+    public void setStartedAfter(final OffsetDateTime startedAfter) {
+        this.startedAfter = startedAfter;
     }
 
-    public Date getEndedBefore() {
-        if (endedBefore != null) {
-            return new Date(endedBefore.getTime());
-        }
-        return null;
+    public OffsetDateTime getEndedBefore() {
+        return endedBefore;
     }
 
     @QueryParam("endedBefore")
-    public void setEndedBefore(final Date endedBefore) {
-        if (endedBefore != null) {
-            this.endedBefore = new Date(endedBefore.getTime());
-        } else {
-            this.endedBefore = null;
-        }
+    public void setEndedBefore(final OffsetDateTime endedBefore) {
+        this.endedBefore = endedBefore;
     }
 
-    public Date getEndedAfter() {
-        if (endedAfter != null) {
-            return new Date(endedAfter.getTime());
-        }
-        return null;
+    public OffsetDateTime getEndedAfter() {
+        return endedAfter;
     }
 
     @QueryParam("endedAfter")
-    public void setEndedAfter(final Date endedAfter) {
-        if (endedAfter != null) {
-            this.endedAfter = new Date(endedAfter.getTime());
-        } else {
-            this.endedAfter = null;
-        }
+    public void setEndedAfter(final OffsetDateTime endedAfter) {
+        this.endedAfter = endedAfter;
     }
 }
diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecQuery.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecListQuery.java
similarity index 90%
rename from common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecQuery.java
rename to common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecListQuery.java
index e307d3e..9176691 100644
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecQuery.java
+++ b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecListQuery.java
@@ -23,15 +23,15 @@ import javax.ws.rs.PathParam;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 
-public class ExecQuery extends AbstractQuery {
+public class ExecListQuery extends AbstractQuery {
 
     private static final long serialVersionUID = -8792519310029596796L;
 
-    public static class Builder extends AbstractQuery.Builder<ExecQuery, Builder> {
+    public static class Builder extends AbstractQuery.Builder<ExecListQuery, Builder> {
 
         @Override
-        protected ExecQuery newInstance() {
-            return new ExecQuery();
+        protected ExecListQuery newInstance() {
+            return new ExecListQuery();
         }
 
         public Builder key(final String key) {
@@ -63,7 +63,7 @@ public class ExecQuery extends AbstractQuery {
         if (getClass() != obj.getClass()) {
             return false;
         }
-        ExecQuery other = (ExecQuery) obj;
+        ExecListQuery other = (ExecListQuery) obj;
         return new EqualsBuilder().
                 appendSuper(super.equals(obj)).
                 append(key, other.key).
diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecuteQuery.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecSpecs.java
similarity index 75%
rename from common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecuteQuery.java
rename to common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecSpecs.java
index 2a3ca7f..fe993d4 100644
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecuteQuery.java
+++ b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ExecSpecs.java
@@ -19,29 +19,28 @@
 package org.apache.syncope.common.rest.api.beans;
 
 import java.io.Serializable;
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.Optional;
-
 import javax.validation.constraints.NotNull;
 import javax.ws.rs.DefaultValue;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.QueryParam;
 
-public class ExecuteQuery implements Serializable {
+public class ExecSpecs implements Serializable {
 
     private static final long serialVersionUID = 3846547401120638351L;
 
     public static class Builder {
 
-        private final ExecuteQuery instance = new ExecuteQuery();
+        private final ExecSpecs instance = new ExecSpecs();
 
         public Builder key(final String key) {
             instance.setKey(key);
             return this;
         }
 
-        public Builder startAt(final Date date) {
-            instance.setStartAt(date);
+        public Builder startAt(final OffsetDateTime startAt) {
+            instance.setStartAt(startAt);
             return this;
         }
 
@@ -50,14 +49,14 @@ public class ExecuteQuery implements Serializable {
             return this;
         }
 
-        public ExecuteQuery build() {
+        public ExecSpecs build() {
             return instance;
         }
     }
 
     private String key;
 
-    private Date startAt;
+    private OffsetDateTime startAt;
 
     private Boolean dryRun;
 
@@ -71,20 +70,13 @@ public class ExecuteQuery implements Serializable {
         this.key = key;
     }
 
-    public Date getStartAt() {
-        if (startAt != null) {
-            return new Date(startAt.getTime());
-        }
-        return null;
+    public OffsetDateTime getStartAt() {
+        return startAt;
     }
 
     @QueryParam("startAt")
-    public void setStartAt(final Date startAt) {
-        if (startAt != null) {
-            this.startAt = new Date(startAt.getTime());
-        } else {
-            this.startAt = null;
-        }
+    public void setStartAt(final OffsetDateTime startAt) {
+        this.startAt = startAt;
     }
 
     public Boolean getDryRun() {
diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ExecutableService.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ExecutableService.java
index 808aae8..f242d56 100644
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ExecutableService.java
+++ b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ExecutableService.java
@@ -40,8 +40,8 @@ import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.types.JobAction;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.beans.ExecDeleteQuery;
-import org.apache.syncope.common.rest.api.beans.ExecQuery;
-import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
+import org.apache.syncope.common.rest.api.beans.ExecListQuery;
+import org.apache.syncope.common.rest.api.beans.ExecSpecs;
 
 public interface ExecutableService extends JAXRSService {
 
@@ -54,7 +54,7 @@ public interface ExecutableService extends JAXRSService {
     @GET
     @Path("{key}/executions")
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    PagedResult<ExecTO> listExecutions(@BeanParam ExecQuery query);
+    PagedResult<ExecTO> listExecutions(@BeanParam ExecListQuery query);
 
     /**
      * Returns the list of recently completed executions, ordered by end date descendent.
@@ -80,7 +80,7 @@ public interface ExecutableService extends JAXRSService {
     void deleteExecution(@NotNull @PathParam("executionKey") String executionKey);
 
     /**
-     * Deletes the executions belonging matching the given query.
+     * Deletes the executions matching the given query.
      *
      * @param query query conditions
      * @return batch results as Response entity
@@ -94,15 +94,15 @@ public interface ExecutableService extends JAXRSService {
     Response deleteExecutions(@BeanParam ExecDeleteQuery query);
 
     /**
-     * Executes the executable matching the given query.
+     * Executes the executable matching the given specs.
      *
-     * @param query query conditions
-     * @return execution report for the executable matching the given query
+     * @param specs conditions to exec
+     * @return execution report for the executable matching the given specs
      */
     @POST
     @Path("{key}/execute")
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    ExecTO execute(@BeanParam ExecuteQuery query);
+    ExecTO execute(@BeanParam ExecSpecs specs);
 
     /**
      * Returns job (running or scheduled) for the executable matching the given key.
diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
index dcaa2c7..bd8d708 100644
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
+++ b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
@@ -27,7 +27,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses;
 import io.swagger.v3.oas.annotations.security.SecurityRequirement;
 import io.swagger.v3.oas.annotations.security.SecurityRequirements;
 import io.swagger.v3.oas.annotations.tags.Tag;
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import javax.validation.constraints.NotNull;
 import javax.ws.rs.BeanParam;
@@ -158,7 +158,7 @@ public interface TaskService extends ExecutableService {
     @Path("PROPAGATION/purge")
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
     Response purgePropagations(
-            @QueryParam("since") Date since, 
-            @QueryParam("statuses") List<ExecStatus> statuses, 
+            @QueryParam("since") OffsetDateTime since,
+            @QueryParam("statuses") List<ExecStatus> statuses,
             @QueryParam("resources") List<String> resources);
 }
diff --git a/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperConfParamOps.java b/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperConfParamOps.java
index a331d40..aca5814 100644
--- a/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperConfParamOps.java
+++ b/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperConfParamOps.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.common.keymaster.client.zookeeper;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.util.Map;
 import java.util.Optional;
 import java.util.TreeMap;
@@ -34,15 +34,15 @@ import org.slf4j.LoggerFactory;
  */
 public class ZookeeperConfParamOps implements ConfParamOps {
 
-    private static final Logger LOG = LoggerFactory.getLogger(ConfParamOps.class);
+    protected static final Logger LOG = LoggerFactory.getLogger(ConfParamOps.class);
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
-    private static final String CONF_PATH = "/conf";
+    protected static final String CONF_PATH = "/conf";
 
-    private final CuratorFramework client;
+    protected final CuratorFramework client;
 
-    private static String buildConfPath(final String... parts) {
+    protected static String buildConfPath(final String... parts) {
         return CONF_PATH + '/' + String.join("/", parts);
     }
 
diff --git a/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperDomainOps.java b/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperDomainOps.java
index 1bc1bbd..4d77665 100644
--- a/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperDomainOps.java
+++ b/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperDomainOps.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.common.keymaster.client.zookeeper;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -42,17 +42,17 @@ import org.springframework.beans.factory.annotation.Autowired;
  */
 public class ZookeeperDomainOps implements DomainOps, InitializingBean {
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    protected static final Logger LOG = LoggerFactory.getLogger(DomainOps.class);
 
-    private static final Logger LOG = LoggerFactory.getLogger(DomainOps.class);
+    protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
-    private static final String DOMAIN_PATH = "/domains";
+    protected static final String DOMAIN_PATH = "/domains";
 
     @Autowired
-    private CuratorFramework client;
+    protected CuratorFramework client;
 
     @Autowired(required = false)
-    private DomainWatcher watcher;
+    protected DomainWatcher watcher;
 
     @Override
     public void afterPropertiesSet() throws Exception {
@@ -93,7 +93,7 @@ public class ZookeeperDomainOps implements DomainOps, InitializingBean {
         }
     }
 
-    private static String buildDomainPath(final String... parts) {
+    protected static String buildDomainPath(final String... parts) {
         String prefix = DOMAIN_PATH;
         String suffix = StringUtils.EMPTY;
         if (parts != null && parts.length > 0) {
diff --git a/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperServiceOps.java b/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperServiceOps.java
index cf5c0ef..175e2a5 100644
--- a/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperServiceOps.java
+++ b/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperServiceOps.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.common.keymaster.client.zookeeper;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
@@ -37,16 +37,16 @@ import org.springframework.beans.factory.annotation.Autowired;
  */
 public class ZookeeperServiceOps implements ServiceOps {
 
-    private static final Logger LOG = LoggerFactory.getLogger(ServiceOps.class);
+    protected static final Logger LOG = LoggerFactory.getLogger(ServiceOps.class);
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
-    private static final String SERVICE_PATH = "/services";
+    protected static final String SERVICE_PATH = "/services";
 
     @Autowired
-    private CuratorFramework client;
+    protected CuratorFramework client;
 
-    private static String buildServicePath(final NetworkService.Type serviceType, final String... parts) {
+    protected static String buildServicePath(final NetworkService.Type serviceType, final String... parts) {
         String prefix = SERVICE_PATH + '/' + serviceType.name();
         String suffix = StringUtils.EMPTY;
         if (parts != null && parts.length > 0) {
diff --git a/common/keymaster/client-zookeeper/src/test/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperTestContentLoader.java b/common/keymaster/client-zookeeper/src/test/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperTestContentLoader.java
index b820878..307ebeb 100644
--- a/common/keymaster/client-zookeeper/src/test/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperTestContentLoader.java
+++ b/common/keymaster/client-zookeeper/src/test/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperTestContentLoader.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.common.keymaster.client.zookeeper;
 
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.util.Iterator;
 import java.util.Map;
 import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
@@ -28,7 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 
 public class ZookeeperTestContentLoader implements InitializingBean {
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     @Autowired
     private ConfParamOps confParamOps;
diff --git a/common/keymaster/self/client-self/src/main/java/org/apache/syncope/common/keymaster/client/self/SelfKeymasterClientContext.java b/common/keymaster/self/client-self/src/main/java/org/apache/syncope/common/keymaster/client/self/SelfKeymasterClientContext.java
index 8c33190..29199d5 100644
--- a/common/keymaster/self/client-self/src/main/java/org/apache/syncope/common/keymaster/client/self/SelfKeymasterClientContext.java
+++ b/common/keymaster/self/client-self/src/main/java/org/apache/syncope/common/keymaster/client/self/SelfKeymasterClientContext.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.common.keymaster.client.self;
 
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
 import java.util.List;
 import java.util.regex.Pattern;
@@ -66,8 +67,9 @@ public class SelfKeymasterClientContext {
         restClientFactoryBean.setThreadSafe(true);
         restClientFactoryBean.setInheritHeaders(true);
         restClientFactoryBean.setFeatures(List.of(new LoggingFeature()));
-        restClientFactoryBean.setProviders(
-                List.of(new JacksonJsonProvider(), new SelfKeymasterClientExceptionMapper()));
+        restClientFactoryBean.setProviders(List.of(
+                new JacksonJsonProvider(JsonMapper.builder().findAndAddModules().build()),
+                new SelfKeymasterClientExceptionMapper()));
         return restClientFactoryBean;
     }
 
@@ -75,7 +77,7 @@ public class SelfKeymasterClientContext {
     @Bean
     @ConditionalOnMissingBean(name = "selfConfParamOps")
     public ConfParamOps selfConfParamOps(@Qualifier("selfKeymasterRESTClientFactoryBean")
-                                         final JAXRSClientFactoryBean selfKeymasterRESTClientFactoryBean) {
+            final JAXRSClientFactoryBean selfKeymasterRESTClientFactoryBean) {
         return new SelfKeymasterConfParamOps(selfKeymasterRESTClientFactoryBean);
     }
 
@@ -83,7 +85,7 @@ public class SelfKeymasterClientContext {
     @Bean
     @ConditionalOnMissingBean(name = "selfServiceOps")
     public ServiceOps selfServiceOps(@Qualifier("selfKeymasterRESTClientFactoryBean")
-                                     final JAXRSClientFactoryBean selfKeymasterRESTClientFactoryBean) {
+            final JAXRSClientFactoryBean selfKeymasterRESTClientFactoryBean) {
         return new SelfKeymasterServiceOps(selfKeymasterRESTClientFactoryBean, 5);
     }
 
@@ -91,7 +93,7 @@ public class SelfKeymasterClientContext {
     @Bean
     @ConditionalOnMissingBean(name = "domainOps")
     public DomainOps domainOps(@Qualifier("selfKeymasterRESTClientFactoryBean")
-                               final JAXRSClientFactoryBean selfKeymasterRESTClientFactoryBean) {
+            final JAXRSClientFactoryBean selfKeymasterRESTClientFactoryBean) {
         return new SelfKeymasterDomainOps(selfKeymasterRESTClientFactoryBean);
     }
 }
diff --git a/common/keymaster/self/client-self/src/main/java/org/apache/syncope/common/keymaster/client/self/SelfKeymasterConfParamOps.java b/common/keymaster/self/client-self/src/main/java/org/apache/syncope/common/keymaster/client/self/SelfKeymasterConfParamOps.java
index 770a442..472d2a4 100644
--- a/common/keymaster/self/client-self/src/main/java/org/apache/syncope/common/keymaster/client/self/SelfKeymasterConfParamOps.java
+++ b/common/keymaster/self/client-self/src/main/java/org/apache/syncope/common/keymaster/client/self/SelfKeymasterConfParamOps.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.common.keymaster.client.self;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -37,7 +37,7 @@ public class SelfKeymasterConfParamOps extends SelfKeymasterOps implements ConfP
 
     private static final Logger LOG = LoggerFactory.getLogger(ConfParamOps.class);
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     public SelfKeymasterConfParamOps(final JAXRSClientFactoryBean clientFactory) {
         super(clientFactory);
diff --git a/core/am/logic/src/main/java/org/apache/syncope/core/logic/wa/GoogleMfaAuthTokenLogic.java b/core/am/logic/src/main/java/org/apache/syncope/core/logic/wa/GoogleMfaAuthTokenLogic.java
index e83d1bc..31a9c74 100644
--- a/core/am/logic/src/main/java/org/apache/syncope/core/logic/wa/GoogleMfaAuthTokenLogic.java
+++ b/core/am/logic/src/main/java/org/apache/syncope/core/logic/wa/GoogleMfaAuthTokenLogic.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.logic.wa;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -47,7 +47,7 @@ public class GoogleMfaAuthTokenLogic extends AbstractAuthProfileLogic {
     }
 
     @PreAuthorize("hasRole('" + IdRepoEntitlement.ANONYMOUS + "')")
-    public void delete(final Date expirationDate) {
+    public void delete(final OffsetDateTime expirationDate) {
         authProfileDAO.findAll(-1, -1).forEach(profile -> removeTokenAndSave(
                 profile, token -> token.getIssueDate().compareTo(expirationDate) >= 0));
     }
diff --git a/core/am/logic/src/main/java/org/apache/syncope/core/logic/wa/U2FRegistrationLogic.java b/core/am/logic/src/main/java/org/apache/syncope/core/logic/wa/U2FRegistrationLogic.java
index c32787a..cb4e376 100644
--- a/core/am/logic/src/main/java/org/apache/syncope/core/logic/wa/U2FRegistrationLogic.java
+++ b/core/am/logic/src/main/java/org/apache/syncope/core/logic/wa/U2FRegistrationLogic.java
@@ -18,8 +18,8 @@
  */
 package org.apache.syncope.core.logic.wa;
 
+import java.time.OffsetDateTime;
 import java.util.Comparator;
-import java.util.Date;
 import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
@@ -64,7 +64,7 @@ public class U2FRegistrationLogic extends AbstractAuthProfileLogic {
     }
 
     @PreAuthorize("hasRole('" + IdRepoEntitlement.ANONYMOUS + "')")
-    public void delete(final Long id, final Date expirationDate) {
+    public void delete(final Long id, final OffsetDateTime expirationDate) {
         List<AuthProfile> profiles = authProfileDAO.findAll(-1, -1);
         profiles.forEach(profile -> {
             List<U2FDevice> devices = profile.getU2FRegisteredDevices();
@@ -86,7 +86,7 @@ public class U2FRegistrationLogic extends AbstractAuthProfileLogic {
     public Pair<Integer, List<U2FDevice>> search(
             final Integer page,
             final Integer itemsPerPage, final Long id,
-            final Date expirationDate,
+            final OffsetDateTime expirationDate,
             final List<OrderByClause> orderByClauses) {
 
         List<Comparator<U2FDevice>> comparatorList = orderByClauses.
diff --git a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/wa/GoogleMfaAuthTokenServiceImpl.java b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/wa/GoogleMfaAuthTokenServiceImpl.java
index b3b328d..6c9a337 100644
--- a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/wa/GoogleMfaAuthTokenServiceImpl.java
+++ b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/wa/GoogleMfaAuthTokenServiceImpl.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.rest.cxf.service.wa;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.wa.GoogleMfaAuthToken;
@@ -37,7 +37,7 @@ public class GoogleMfaAuthTokenServiceImpl extends AbstractService implements Go
     }
 
     @Override
-    public void delete(final Date expirationDate) {
+    public void delete(final OffsetDateTime expirationDate) {
         if (expirationDate == null) {
             logic.deleteAll();
         } else {
diff --git a/core/idm/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/RemediationServiceImpl.java b/core/idm/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/RemediationServiceImpl.java
index f60eaec..d226519 100644
--- a/core/idm/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/RemediationServiceImpl.java
+++ b/core/idm/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/RemediationServiceImpl.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.rest.cxf.service;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.tuple.Pair;
@@ -101,11 +101,11 @@ public class RemediationServiceImpl extends AbstractService implements Remediati
                 anyDAO = anyObjectDAO;
         }
 
-        Date etagDate = anyDAO.findLastChange(anyKey);
-        if (etagDate == null) {
+        OffsetDateTime etag = anyDAO.findLastChange(anyKey);
+        if (etag == null) {
             throw new NotFoundException(remediation.getAnyType() + " for " + key);
         }
-        checkETag(String.valueOf(etagDate.getTime()));
+        checkETag(String.valueOf(etag.toInstant().toEpochMilli()));
     }
 
     @Override
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractExecutableLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractExecutableLogic.java
index 36f76ba..db6447e 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractExecutableLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractExecutableLogic.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.logic;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.to.EntityTO;
@@ -36,7 +36,7 @@ public abstract class AbstractExecutableLogic<T extends EntityTO> extends Abstra
         super(jobManager, scheduler);
     }
 
-    public abstract ExecTO execute(String key, Date startAt, boolean dryRun);
+    public abstract ExecTO execute(String key, OffsetDateTime startAt, boolean dryRun);
 
     public abstract Pair<Integer, List<ExecTO>> listExecutions(
             String key, int page, int size, List<OrderByClause> orderByClauses);
@@ -46,7 +46,11 @@ public abstract class AbstractExecutableLogic<T extends EntityTO> extends Abstra
     public abstract ExecTO deleteExecution(String executionKey);
 
     public abstract List<BatchResponseItem> deleteExecutions(
-            String key, Date startedBefore, Date startedAfter, Date endedBefore, Date endedAfter);
+            String key,
+            OffsetDateTime startedBefore,
+            OffsetDateTime startedAfter,
+            OffsetDateTime endedBefore,
+            OffsetDateTime endedAfter);
 
     public abstract JobTO getJob(String key);
 
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractJobLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractJobLogic.java
index 2adb824..c887885 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractJobLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractJobLogic.java
@@ -26,6 +26,7 @@ import org.apache.syncope.common.lib.to.JobTO;
 import org.apache.syncope.common.lib.types.JobAction;
 import org.apache.syncope.common.lib.types.JobType;
 import org.apache.syncope.core.provisioning.api.job.JobManager;
+import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
 import org.apache.syncope.core.provisioning.java.job.AbstractInterruptableJob;
 import org.apache.syncope.core.provisioning.java.job.SystemLoadReporterJob;
 import org.apache.syncope.core.provisioning.java.job.TaskJob;
@@ -84,7 +85,7 @@ abstract class AbstractJobLogic<T extends EntityTO> extends AbstractTransactiona
                     jobTO.setScheduled(false);
                 } else {
                     jobTO.setScheduled(true);
-                    jobTO.setStart(jobTriggers.get(0).getStartTime());
+                    jobTO.setStart(jobTriggers.get(0).getStartTime().toInstant().atOffset(FormatUtils.DEFAULT_OFFSET));
                 }
 
                 jobTO.setRunning(jobManager.isRunning(jobKey));
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AccessTokenLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AccessTokenLogic.java
index 5b978e2..936c13a 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AccessTokenLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AccessTokenLogic.java
@@ -19,8 +19,8 @@
 package org.apache.syncope.core.logic;
 
 import java.lang.reflect.Method;
+import java.time.OffsetDateTime;
 import java.util.Collections;
-import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.tuple.Pair;
@@ -74,7 +74,7 @@ public class AccessTokenLogic extends AbstractTransactionalLogic<AccessTokenTO>
     }
 
     @PreAuthorize("isAuthenticated()")
-    public Pair<String, Date> login() {
+    public Pair<String, OffsetDateTime> login() {
         if (securityProperties.getAnonymousUser().equals(AuthContextUtils.getUsername())) {
             SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidRequest);
             sce.getElements().add(securityProperties.getAnonymousUser() + " cannot be granted an access token");
@@ -89,7 +89,7 @@ public class AccessTokenLogic extends AbstractTransactionalLogic<AccessTokenTO>
     }
 
     @PreAuthorize("isAuthenticated()")
-    public Pair<String, Date> refresh() {
+    public Pair<String, OffsetDateTime> refresh() {
         AccessToken accessToken = accessTokenDAO.findByOwner(AuthContextUtils.getUsername());
         if (accessToken == null) {
             throw new NotFoundException("AccessToken for " + AuthContextUtils.getUsername());
@@ -133,5 +133,4 @@ public class AccessTokenLogic extends AbstractTransactionalLogic<AccessTokenTO>
 
         throw new UnresolvedReferenceException();
     }
-
 }
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
index 098b4d2..2e2279a 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
@@ -19,8 +19,8 @@
 package org.apache.syncope.core.logic;
 
 import java.lang.reflect.Method;
+import java.time.OffsetDateTime;
 import java.util.Collection;
-import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -445,7 +445,7 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupCR, GroupUR> {
         result.setJobType(JobType.TASK);
         result.setRefKey(task.getKey());
         result.setRefDesc(taskDataBinder.buildRefDesc(task));
-        result.setStart(new Date());
+        result.setStart(OffsetDateTime.now());
         result.setStatus("JOB_FIRED");
         result.setMessage("Job fired; waiting for results...");
 
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
index 75aa53c..bfda1a4 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
@@ -22,8 +22,8 @@ import java.io.ByteArrayInputStream;
 import java.io.OutputStream;
 import java.lang.reflect.Method;
 import java.nio.charset.StandardCharsets;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -172,7 +172,7 @@ public class ReportLogic extends AbstractExecutableLogic<ReportTO> {
 
     @PreAuthorize("hasRole('" + IdRepoEntitlement.REPORT_EXECUTE + "')")
     @Override
-    public ExecTO execute(final String key, final Date startAt, final boolean dryRun) {
+    public ExecTO execute(final String key, final OffsetDateTime startAt, final boolean dryRun) {
         Report report = reportDAO.find(key);
         if (report == null) {
             throw new NotFoundException("Report " + key);
@@ -204,7 +204,7 @@ public class ReportLogic extends AbstractExecutableLogic<ReportTO> {
         result.setJobType(JobType.REPORT);
         result.setRefKey(report.getKey());
         result.setRefDesc(binder.buildRefDesc(report));
-        result.setStart(new Date());
+        result.setStart(OffsetDateTime.now());
         result.setStatus(ReportExecStatus.STARTED.name());
         result.setMessage("Job fired; waiting for results...");
         result.setExecutor(AuthContextUtils.getUsername());
@@ -353,7 +353,10 @@ public class ReportLogic extends AbstractExecutableLogic<ReportTO> {
     @Override
     public List<BatchResponseItem> deleteExecutions(
             final String key,
-            final Date startedBefore, final Date startedAfter, final Date endedBefore, final Date endedAfter) {
+            final OffsetDateTime startedBefore,
+            final OffsetDateTime startedAfter,
+            final OffsetDateTime endedBefore,
+            final OffsetDateTime endedAfter) {
 
         Report report = reportDAO.find(key);
         if (report == null) {
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
index 904491f..f787d40 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
@@ -19,8 +19,8 @@
 package org.apache.syncope.core.logic;
 
 import java.lang.reflect.Method;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -240,12 +240,12 @@ public class TaskLogic extends AbstractExecutableLogic<TaskTO> {
 
     @PreAuthorize("hasRole('" + IdRepoEntitlement.TASK_EXECUTE + "')")
     @Override
-    public ExecTO execute(final String key, final Date startAt, final boolean dryRun) {
+    public ExecTO execute(final String key, final OffsetDateTime startAt, final boolean dryRun) {
         Task task = taskDAO.find(key);
         if (task == null) {
             throw new NotFoundException("Task " + key);
         }
-        if (startAt != null && startAt.before(new Date())) {
+        if (startAt != null && startAt.isBefore(OffsetDateTime.now())) {
             SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Scheduling);
             sce.getElements().add("Cannot schedule in the past");
             throw sce;
@@ -311,7 +311,7 @@ public class TaskLogic extends AbstractExecutableLogic<TaskTO> {
                 result.setJobType(JobType.TASK);
                 result.setRefKey(task.getKey());
                 result.setRefDesc(binder.buildRefDesc(task));
-                result.setStart(new Date());
+                result.setStart(OffsetDateTime.now());
                 result.setExecutor(executor);
                 result.setStatus("JOB_FIRED");
                 result.setMessage("Job fired; waiting for results...");
@@ -392,10 +392,10 @@ public class TaskLogic extends AbstractExecutableLogic<TaskTO> {
     @Override
     public List<BatchResponseItem> deleteExecutions(
             final String key,
-            final Date startedBefore,
-            final Date startedAfter,
-            final Date endedBefore,
-            final Date endedAfter) {
+            final OffsetDateTime startedBefore,
+            final OffsetDateTime startedAfter,
+            final OffsetDateTime endedBefore,
+            final OffsetDateTime endedAfter) {
 
         Task task = taskDAO.find(key);
         if (task == null) {
@@ -475,12 +475,14 @@ public class TaskLogic extends AbstractExecutableLogic<TaskTO> {
 
     @PreAuthorize("hasRole('" + IdRepoEntitlement.TASK_DELETE + "')")
     public List<PropagationTaskTO> purgePropagations(
-            final Date since,
+            final OffsetDateTime since,
             final List<ExecStatus> statuses,
             final List<String> resources) {
+
         return taskDAO.purgePropagations(since, statuses, Optional.ofNullable(resources).
-                map(r -> r.stream().map(resourceDAO::find).filter(Objects::nonNull).collect(Collectors.toList()))
-                .orElse(null));
+                map(r -> r.stream().map(resourceDAO::find).
+                filter(Objects::nonNull).collect(Collectors.toList())).
+                orElse(null));
     }
 
     @Override
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/IdRepoRESTCXFContext.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/IdRepoRESTCXFContext.java
index 71b12d4..6d28e97 100644
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/IdRepoRESTCXFContext.java
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/IdRepoRESTCXFContext.java
@@ -40,7 +40,7 @@ import org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor;
 import org.apache.cxf.transport.common.gzip.GZIPInInterceptor;
 import org.apache.cxf.transport.common.gzip.GZIPOutInterceptor;
 import org.apache.cxf.validation.BeanValidationProvider;
-import org.apache.syncope.common.lib.jackson.SyncopeObjectMapper;
+import org.apache.syncope.common.lib.jackson.SyncopeJsonMapper;
 import org.apache.syncope.common.lib.jackson.SyncopeXmlMapper;
 import org.apache.syncope.common.lib.jackson.SyncopeYAMLMapper;
 import org.apache.syncope.common.lib.search.SyncopeFiqlParser;
@@ -155,25 +155,19 @@ public class IdRepoRESTCXFContext {
     @ConditionalOnMissingBean
     @Bean
     public JacksonJsonProvider jsonProvider() {
-        JacksonJsonProvider jsonProvider = new JacksonJsonProvider();
-        jsonProvider.setMapper(new SyncopeObjectMapper());
-        return jsonProvider;
+        return new JacksonJsonProvider(new SyncopeJsonMapper());
     }
 
     @ConditionalOnMissingBean
     @Bean
     public JacksonXMLProvider xmlProvider() {
-        JacksonXMLProvider xmlProvider = new JacksonXMLProvider();
-        xmlProvider.setMapper(new SyncopeXmlMapper());
-        return xmlProvider;
+        return new JacksonXMLProvider(new SyncopeXmlMapper());
     }
 
     @ConditionalOnMissingBean
     @Bean
     public JacksonYAMLProvider yamlProvider() {
-        JacksonYAMLProvider yamlProvider = new JacksonYAMLProvider();
-        yamlProvider.setMapper(new SyncopeYAMLMapper());
-        return yamlProvider;
+        return new JacksonYAMLProvider(new SyncopeYAMLMapper());
     }
 
     @ConditionalOnMissingBean
@@ -342,7 +336,7 @@ public class IdRepoRESTCXFContext {
     @ConditionalOnMissingBean
     @Bean
     public AnyObjectService anyObjectService(final AnyObjectDAO anyObjectDAO, final AnyObjectLogic anyObjectLogic,
-                                             final SearchCondVisitor searchCondVisitor) {
+            final SearchCondVisitor searchCondVisitor) {
         return new AnyObjectServiceImpl(searchCondVisitor, anyObjectDAO, anyObjectLogic);
     }
 
@@ -385,7 +379,7 @@ public class IdRepoRESTCXFContext {
     @ConditionalOnMissingBean
     @Bean
     public GroupService groupService(final GroupDAO groupDAO, final GroupLogic groupLogic,
-                                     final SearchCondVisitor searchCondVisitor) {
+            final SearchCondVisitor searchCondVisitor) {
         return new GroupServiceImpl(searchCondVisitor, groupDAO, groupLogic);
     }
 
@@ -482,7 +476,7 @@ public class IdRepoRESTCXFContext {
     @ConditionalOnMissingBean
     @Bean
     public UserService userService(final UserDAO userDAO, final UserLogic userLogic,
-                                   final SearchCondVisitor searchCondVisitor) {
+            final SearchCondVisitor searchCondVisitor) {
         return new UserServiceImpl(searchCondVisitor, userDAO, userLogic);
     }
 }
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
index b1ab5bf..f821a81 100644
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.rest.cxf.service;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
@@ -155,8 +155,8 @@ public abstract class AbstractAnyService<TO extends AnyTO, CR extends AnyCR, UR
         }
     }
 
-    protected Date findLastChange(final String key) {
-        Date lastChange = getAnyDAO().findLastChange(key);
+    protected OffsetDateTime findLastChange(final String key) {
+        OffsetDateTime lastChange = getAnyDAO().findLastChange(key);
         if (lastChange == null) {
             throw new NotFoundException("User, Group or Any Object for " + key);
         }
@@ -166,8 +166,8 @@ public abstract class AbstractAnyService<TO extends AnyTO, CR extends AnyCR, UR
 
     protected Response doUpdate(final UR updateReq) {
         updateReq.setKey(getActualKey(getAnyDAO(), updateReq.getKey()));
-        Date etagDate = findLastChange(updateReq.getKey());
-        checkETag(String.valueOf(etagDate.getTime()));
+        OffsetDateTime etag = findLastChange(updateReq.getKey());
+        checkETag(String.valueOf(etag.toInstant().toEpochMilli()));
 
         ProvisioningResult<TO> updated = getAnyLogic().update(updateReq, isNullPriorityAsync());
         return modificationResponse(updated);
@@ -218,8 +218,8 @@ public abstract class AbstractAnyService<TO extends AnyTO, CR extends AnyCR, UR
     public Response delete(final String key) {
         String actualKey = getActualKey(getAnyDAO(), key);
 
-        Date etagDate = findLastChange(actualKey);
-        checkETag(String.valueOf(etagDate.getTime()));
+        OffsetDateTime etag = findLastChange(actualKey);
+        checkETag(String.valueOf(etag.toInstant().toEpochMilli()));
 
         ProvisioningResult<TO> deleted = getAnyLogic().delete(actualKey, isNullPriorityAsync());
         return modificationResponse(deleted);
@@ -227,8 +227,8 @@ public abstract class AbstractAnyService<TO extends AnyTO, CR extends AnyCR, UR
 
     @Override
     public Response deassociate(final ResourceDR req) {
-        Date etagDate = findLastChange(req.getKey());
-        checkETag(String.valueOf(etagDate.getTime()));
+        OffsetDateTime etag = findLastChange(req.getKey());
+        checkETag(String.valueOf(etag.toInstant().toEpochMilli()));
 
         ProvisioningResult<TO> updated;
         switch (req.getAction()) {
@@ -304,8 +304,8 @@ public abstract class AbstractAnyService<TO extends AnyTO, CR extends AnyCR, UR
 
     @Override
     public Response associate(final ResourceAR req) {
-        Date etagDate = findLastChange(req.getKey());
-        checkETag(String.valueOf(etagDate.getTime()));
+        OffsetDateTime etag = findLastChange(req.getKey());
+        checkETag(String.valueOf(etag.toInstant().toEpochMilli()));
 
         ProvisioningResult<TO> updated;
         switch (req.getAction()) {
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractExecutableService.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractExecutableService.java
index 4d80156..5a71598 100644
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractExecutableService.java
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractExecutableService.java
@@ -29,8 +29,8 @@ import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.batch.BatchPayloadGenerator;
 import org.apache.syncope.common.rest.api.batch.BatchResponseItem;
 import org.apache.syncope.common.rest.api.beans.ExecDeleteQuery;
-import org.apache.syncope.common.rest.api.beans.ExecQuery;
-import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
+import org.apache.syncope.common.rest.api.beans.ExecListQuery;
+import org.apache.syncope.common.rest.api.beans.ExecSpecs;
 import org.apache.syncope.common.rest.api.service.ExecutableService;
 import org.apache.syncope.common.rest.api.service.JAXRSService;
 import org.apache.syncope.core.logic.AbstractExecutableLogic;
@@ -41,7 +41,7 @@ public abstract class AbstractExecutableService extends AbstractService implemen
     protected abstract AbstractExecutableLogic<?> getExecutableLogic();
 
     @Override
-    public PagedResult<ExecTO> listExecutions(final ExecQuery query) {
+    public PagedResult<ExecTO> listExecutions(final ExecListQuery query) {
         Pair<Integer, List<ExecTO>> result = getExecutableLogic().listExecutions(
                 query.getKey(),
                 query.getPage(),
@@ -77,7 +77,7 @@ public abstract class AbstractExecutableService extends AbstractService implemen
     }
 
     @Override
-    public ExecTO execute(final ExecuteQuery query) {
+    public ExecTO execute(final ExecSpecs query) {
         return getExecutableLogic().execute(query.getKey(), query.getStartAt(), query.getDryRun());
     }
 
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AccessTokenServiceImpl.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AccessTokenServiceImpl.java
index c1b80b8..baff80d 100644
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AccessTokenServiceImpl.java
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AccessTokenServiceImpl.java
@@ -18,10 +18,10 @@
  */
 package org.apache.syncope.core.rest.cxf.service;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.List;
 import javax.ws.rs.core.Response;
-import org.apache.commons.lang3.time.DateFormatUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.to.AccessTokenTO;
 import org.apache.syncope.common.lib.to.PagedResult;
@@ -42,21 +42,19 @@ public class AccessTokenServiceImpl extends AbstractService implements AccessTok
 
     @Override
     public Response login() {
-        Pair<String, Date> login = logic.login();
+        Pair<String, OffsetDateTime> login = logic.login();
         return Response.noContent().
                 header(RESTHeaders.TOKEN, login.getLeft()).
-                header(RESTHeaders.TOKEN_EXPIRE,
-                        DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.format(login.getRight())).
+                header(RESTHeaders.TOKEN_EXPIRE, DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(login.getRight())).
                 build();
     }
 
     @Override
     public Response refresh() {
-        Pair<String, Date> refresh = logic.refresh();
+        Pair<String, OffsetDateTime> refresh = logic.refresh();
         return Response.noContent().
                 header(RESTHeaders.TOKEN, refresh.getLeft()).
-                header(RESTHeaders.TOKEN_EXPIRE,
-                        DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.format(refresh.getRight())).
+                header(RESTHeaders.TOKEN_EXPIRE, DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(refresh.getRight())).
                 build();
     }
 
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SyncopeServiceImpl.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SyncopeServiceImpl.java
index 4d7c1e2..be2a2e7 100644
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SyncopeServiceImpl.java
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SyncopeServiceImpl.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.rest.cxf.service;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import javax.ws.rs.InternalServerErrorException;
 import javax.ws.rs.NotFoundException;
@@ -137,7 +137,7 @@ public class SyncopeServiceImpl extends AbstractService implements SyncopeServic
         // prepare for batch processing
         Batch batch = entityFactory.newEntity(Batch.class);
         batch.setKey(boundary);
-        batch.setExpiryTime(new Date(System.currentTimeMillis() + 5 * 60 * 1000));
+        batch.setExpiryTime(OffsetDateTime.now().plusMinutes(5));
         batchDAO.save(batch);
 
         BatchProcess batchProcess = ApplicationContextProvider.getBeanFactory().createBean(BatchProcess.class);
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
index 3177cdd..960bca9 100644
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.core.rest.cxf.service;
 
 import java.net.URI;
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import javax.ws.rs.BadRequestException;
 import javax.ws.rs.core.Response;
@@ -98,12 +98,15 @@ public class TaskServiceImpl extends AbstractExecutableService implements TaskSe
     }
 
     @Override
-    public Response purgePropagations(final Date since, final List<ExecStatus> statuses, final List<String> resources) {
+    public Response purgePropagations(
+            final OffsetDateTime since,
+            final List<ExecStatus> statuses,
+            final List<String> resources) {
+
         if (since == null && CollectionUtils.isEmpty(statuses) && CollectionUtils.isEmpty(resources)) {
             return Response.status(Response.Status.PRECONDITION_FAILED).build();
         }
 
         return Response.ok(logic.purgePropagations(since, statuses, resources)).build();
     }
-
 }
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
index 4c51698..2b48e5b 100644
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.rest.cxf.service;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.common.lib.request.StatusR;
 import org.apache.syncope.common.lib.request.UserCR;
@@ -78,8 +78,8 @@ public class UserServiceImpl extends AbstractAnyService<UserTO, UserCR, UserUR>
 
     @Override
     public Response status(final StatusR statusR) {
-        Date etagDate = findLastChange(statusR.getKey());
-        checkETag(String.valueOf(etagDate.getTime()));
+        OffsetDateTime etag = findLastChange(statusR.getKey());
+        checkETag(String.valueOf(etag.toInstant().toEpochMilli()));
 
         ProvisioningResult<UserTO> updated = logic.status(statusR, isNullPriorityAsync());
         return modificationResponse(updated);
diff --git a/core/idrepo/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceTest.java b/core/idrepo/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceTest.java
index 2d30c95..e5213bd 100644
--- a/core/idrepo/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceTest.java
+++ b/core/idrepo/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceTest.java
@@ -75,7 +75,7 @@ import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 import org.apache.syncope.core.persistence.api.search.SearchCondVisitor;
 import org.apache.syncope.core.rest.cxf.AddETagFilter;
 import org.apache.syncope.core.rest.cxf.RestServiceExceptionMapper;
-import org.apache.syncope.common.lib.jackson.SyncopeObjectMapper;
+import org.apache.syncope.common.lib.jackson.SyncopeJsonMapper;
 import org.apache.syncope.common.lib.jackson.SyncopeXmlMapper;
 import org.apache.syncope.common.lib.jackson.SyncopeYAMLMapper;
 import org.junit.jupiter.api.BeforeEach;
@@ -234,7 +234,7 @@ public class AnyObjectServiceTest {
     public void jsonList() throws IOException {
         InputStream in = list(MediaType.APPLICATION_JSON_TYPE);
 
-        PagedResult<AnyObjectTO> list = new SyncopeObjectMapper().
+        PagedResult<AnyObjectTO> list = new SyncopeJsonMapper().
                 readValue(IOUtils.toString(in), new TypeReference<>() {
                 });
         checkList(list);
diff --git a/core/idrepo/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/IdRepoRESTCXFTestContext.java b/core/idrepo/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/IdRepoRESTCXFTestContext.java
index 05e0e30..add3f15 100644
--- a/core/idrepo/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/IdRepoRESTCXFTestContext.java
+++ b/core/idrepo/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/IdRepoRESTCXFTestContext.java
@@ -29,7 +29,7 @@ import org.apache.cxf.validation.BeanValidationProvider;
 import org.apache.syncope.common.rest.api.DateParamConverterProvider;
 import org.apache.syncope.core.rest.cxf.AddETagFilter;
 import org.apache.syncope.core.rest.cxf.RestServiceExceptionMapper;
-import org.apache.syncope.common.lib.jackson.SyncopeObjectMapper;
+import org.apache.syncope.common.lib.jackson.SyncopeJsonMapper;
 import org.apache.syncope.common.lib.jackson.SyncopeXmlMapper;
 import org.apache.syncope.common.lib.jackson.SyncopeYAMLMapper;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -50,23 +50,17 @@ public class IdRepoRESTCXFTestContext {
 
     @Bean
     public JacksonXMLProvider xmlProvider() {
-        JacksonXMLProvider xmlProvider = new JacksonXMLProvider();
-        xmlProvider.setMapper(new SyncopeXmlMapper());
-        return xmlProvider;
+        return new JacksonXMLProvider(new SyncopeXmlMapper());
     }
 
     @Bean
     public JacksonJsonProvider jsonProvider() {
-        JacksonJsonProvider jsonProvider = new JacksonJsonProvider();
-        jsonProvider.setMapper(new SyncopeObjectMapper());
-        return jsonProvider;
+        return new JacksonJsonProvider(new SyncopeJsonMapper());
     }
 
     @Bean
     public JacksonYAMLProvider yamlProvider() {
-        JacksonYAMLProvider yamlProvider = new JacksonYAMLProvider();
-        yamlProvider.setMapper(new SyncopeYAMLMapper());
-        return yamlProvider;
+        return new JacksonYAMLProvider(new SyncopeYAMLMapper());
     }
 
     @Bean
@@ -75,8 +69,7 @@ public class IdRepoRESTCXFTestContext {
     }
 
     @Bean
-    public JAXRSBeanValidationInInterceptor validationInInterceptor(
-        final BeanValidationProvider validationProvider) {
+    public JAXRSBeanValidationInInterceptor validationInInterceptor(final BeanValidationProvider validationProvider) {
         JAXRSBeanValidationInInterceptor validationInInterceptor = new JAXRSBeanValidationInInterceptor();
         validationInInterceptor.setProvider(validationProvider);
         return validationInInterceptor;
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
index fb888eb..63089a4 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
@@ -18,8 +18,8 @@
  */
 package org.apache.syncope.core.persistence.api.dao;
 
+import java.time.OffsetDateTime;
 import java.util.Collection;
-import java.util.Date;
 import java.util.List;
 import java.util.Optional;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
@@ -39,7 +39,7 @@ public interface AnyDAO<A extends Any<?>> extends DAO<A> {
 
     List<A> findByKeys(List<String> keys);
 
-    Date findLastChange(String key);
+    OffsetDateTime findLastChange(String key);
 
     A authFind(String key);
 
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ReportExecDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ReportExecDAO.java
index 61c7cfc..7fda0cd 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ReportExecDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ReportExecDAO.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.dao;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.entity.Report;
@@ -38,7 +38,12 @@ public interface ReportExecDAO extends DAO<ReportExec> {
 
     List<ReportExec> findAll(Report report, int page, int itemsPerPage, List<OrderByClause> orderByClauses);
 
-    List<ReportExec> findAll(Report report, Date startedBefore, Date startedAfter, Date endedBefore, Date endedAfter);
+    List<ReportExec> findAll(
+            Report report,
+            OffsetDateTime startedBefore,
+            OffsetDateTime startedAfter,
+            OffsetDateTime endedBefore,
+            OffsetDateTime endedAfter);
 
     ReportExec save(ReportExec execution);
 
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskDAO.java
index 8cd5f73..244084b 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskDAO.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.dao;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import org.apache.syncope.common.lib.to.PropagationTaskTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -77,7 +77,7 @@ public interface TaskDAO extends DAO<Task> {
     void deleteAll(ExternalResource resource, TaskType type);
 
     List<PropagationTaskTO> purgePropagations(
-            Date since, 
+            OffsetDateTime since,
             List<ExecStatus> statuses,
             List<ExternalResource> externalResources);
 }
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskExecDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskExecDAO.java
index e90cc8d..000fdda 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskExecDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskExecDAO.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.dao;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.entity.task.Task;
@@ -39,7 +39,11 @@ public interface TaskExecDAO extends DAO<TaskExec> {
     <T extends Task> List<TaskExec> findAll(T task, int page, int itemsPerPage, List<OrderByClause> orderByClauses);
 
     <T extends Task> List<TaskExec> findAll(
-            T task, Date startedBefore, Date startedAfter, Date endedBefore, Date endedAfter);
+            T task,
+            OffsetDateTime startedBefore,
+            OffsetDateTime startedAfter,
+            OffsetDateTime endedBefore,
+            OffsetDateTime endedAfter);
 
     TaskExec save(TaskExec execution);
 
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccessToken.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccessToken.java
index d956385..3db11c8 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccessToken.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccessToken.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 
 public interface AccessToken extends ProvidedKeyEntity {
 
@@ -26,9 +26,9 @@ public interface AccessToken extends ProvidedKeyEntity {
 
     void setBody(String body);
 
-    Date getExpirationTime();
+    OffsetDateTime getExpirationTime();
 
-    void setExpirationTime(Date expirationTime);
+    void setExpirationTime(OffsetDateTime expirationTime);
 
     String getOwner();
 
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
index a658cd9..ef99a69 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
@@ -18,31 +18,31 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import java.util.List;
 
 public interface Any<P extends PlainAttr<?>> extends Attributable<P>, Entity {
 
-    Date getCreationDate();
+    OffsetDateTime getCreationDate();
 
     String getCreator();
 
     String getCreationContext();
 
-    Date getLastChangeDate();
+    OffsetDateTime getLastChangeDate();
 
     String getLastModifier();
 
     String getLastChangeContext();
 
-    void setCreationDate(Date creationDate);
+    void setCreationDate(OffsetDateTime creationDate);
 
     void setCreator(String creator);
 
     void setCreationContext(String context);
 
-    void setLastChangeDate(Date lastChangeDate);
+    void setLastChangeDate(OffsetDateTime lastChangeDate);
 
     void setLastModifier(String lastModifier);
 
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Batch.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Batch.java
index 86fa647..2269b5a 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Batch.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Batch.java
@@ -18,13 +18,13 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 
 public interface Batch extends ProvidedKeyEntity {
 
-    Date getExpiryTime();
+    OffsetDateTime getExpiryTime();
 
-    void setExpiryTime(Date expiryTime);
+    void setExpiryTime(OffsetDateTime expiryTime);
 
     String getResults();
 
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Delegation.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Delegation.java
index 07c34c5..9c38868 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Delegation.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Delegation.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.Set;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 
@@ -32,13 +32,13 @@ public interface Delegation extends Entity {
 
     void setDelegated(User delegated);
 
-    void setStart(Date start);
+    void setStart(OffsetDateTime start);
 
-    Date getStart();
+    OffsetDateTime getStart();
 
-    void setEnd(Date end);
+    void setEnd(OffsetDateTime end);
 
-    Date getEnd();
+    OffsetDateTime getEnd();
 
     boolean add(Role role);
 
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Exec.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Exec.java
index ca4141d..e18dd81 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Exec.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Exec.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 
 public interface Exec extends Entity {
 
@@ -35,13 +35,13 @@ public interface Exec extends Entity {
 
     String getStatus();
 
-    void setStart(Date start);
+    void setStart(OffsetDateTime start);
 
-    Date getStart();
+    OffsetDateTime getStart();
 
-    void setEnd(Date end);
+    void setEnd(OffsetDateTime end);
 
-    Date getEnd();
+    OffsetDateTime getEnd();
 
     String getExecutor();
 
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PlainAttrValue.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PlainAttrValue.java
index 67282ee..5e101e8 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PlainAttrValue.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PlainAttrValue.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 
 public interface PlainAttrValue extends Entity {
@@ -29,7 +29,7 @@ public interface PlainAttrValue extends Entity {
 
     Boolean getBooleanValue();
 
-    Date getDateValue();
+    OffsetDateTime getDateValue();
 
     Double getDoubleValue();
 
@@ -53,7 +53,7 @@ public interface PlainAttrValue extends Entity {
 
     void setBooleanValue(Boolean booleanValue);
 
-    void setDateValue(Date dateValue);
+    void setDateValue(OffsetDateTime dateValue);
 
     void setDoubleValue(Double doubleValue);
 
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Remediation.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Remediation.java
index 3504a16..599805d 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Remediation.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Remediation.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import org.apache.syncope.common.lib.request.AnyCR;
 import org.apache.syncope.common.lib.request.AnyUR;
 import org.apache.syncope.common.lib.types.ResourceOperation;
@@ -50,9 +50,9 @@ public interface Remediation extends Entity {
 
     void setError(String error);
 
-    Date getInstant();
+    OffsetDateTime getInstant();
 
-    void setInstant(Date instant);
+    void setInstant(OffsetDateTime instant);
 
     PullTask getPullTask();
 
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/SchedTask.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/SchedTask.java
index abddc8b..4174b25 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/SchedTask.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/SchedTask.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.entity.task;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 
 public interface SchedTask extends Task {
@@ -35,9 +35,9 @@ public interface SchedTask extends Task {
 
     Implementation getJobDelegate();
 
-    Date getStartAt();
+    OffsetDateTime getStartAt();
 
-    void setStartAt(Date startAt);
+    void setStartAt(OffsetDateTime startAt);
 
     void setCronExpression(String cronExpression);
 
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
index 8406759..584b9f9 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.entity.user;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import java.util.Optional;
 import org.apache.syncope.core.persistence.api.entity.Role;
@@ -29,7 +29,7 @@ public interface User extends Account, GroupableRelatable<User, UMembership, UPl
 
     String getToken();
 
-    Date getTokenExpireTime();
+    OffsetDateTime getTokenExpireTime();
 
     void generateToken(int tokenLength, int tokenExpireTime);
 
@@ -43,9 +43,9 @@ public interface User extends Account, GroupableRelatable<User, UMembership, UPl
 
     void removeClearPassword();
 
-    Date getChangePwdDate();
+    OffsetDateTime getChangePwdDate();
 
-    void setChangePwdDate(Date changePwdDate);
+    void setChangePwdDate(OffsetDateTime changePwdDate);
 
     List<String> getPasswordHistory();
 
@@ -65,9 +65,9 @@ public interface User extends Account, GroupableRelatable<User, UMembership, UPl
 
     void setFailedLogins(Integer failedLogins);
 
-    Date getLastLoginDate();
+    OffsetDateTime getLastLoginDate();
 
-    void setLastLoginDate(Date lastLoginDate);
+    void setLastLoginDate(OffsetDateTime lastLoginDate);
 
     boolean isMustChangePassword();
 
diff --git a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONAnyDAO.java b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONAnyDAO.java
index b4a1e01..a5c9e9f 100644
--- a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONAnyDAO.java
+++ b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONAnyDAO.java
@@ -18,8 +18,8 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -336,7 +336,7 @@ abstract class AbstractJPAJSONAnyDAO extends AbstractDAO<AbstractEntity> impleme
         }
 
         // update sysInfo - as org.apache.syncope.core.persistence.jpa.entity.PlainAttrListener is not invoked
-        Date now = new Date();
+        OffsetDateTime now = OffsetDateTime.now();
         String username = AuthContextUtils.getUsername();
         LOG.debug("Set last change date '{}' and modifier '{}' for '{}'", now, username, any);
         any.setLastModifier(username);
diff --git a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONLoggerDAO.java b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONLoggerDAO.java
index 7f2a098..6bbb32d 100644
--- a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONLoggerDAO.java
+++ b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONLoggerDAO.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import java.util.ArrayList;
 import java.util.List;
@@ -29,7 +29,7 @@ import org.springframework.util.CollectionUtils;
 
 public abstract class AbstractJPAJSONLoggerDAO extends JPAAuditConfDAO {
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     protected abstract static class JSONMessageCriteriaBuilder extends MessageCriteriaBuilder {
 
diff --git a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONAnySearchDAO.java b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONAnySearchDAO.java
index 9d88bd2..d2ebd89 100644
--- a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONAnySearchDAO.java
+++ b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONAnySearchDAO.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
+import java.time.format.DateTimeFormatter;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
@@ -171,13 +172,13 @@ public class MyJPAJSONAnySearchDAO extends JPAAnySearchDAO {
                 String key = key(schema.getType());
 
                 String value = Optional.ofNullable(attrValue.getDateValue()).
-                        map(v -> String.valueOf(v.getTime())).
+                        map(DateTimeFormatter.ISO_OFFSET_DATE_TIME::format).
                         orElse(cond.getExpression());
 
                 boolean lower = (schema.getType() == AttrSchemaType.String || schema.getType() == AttrSchemaType.Enum)
                         && (cond.getType() == AttrCond.Type.IEQ || cond.getType() == AttrCond.Type.ILIKE);
 
-                query.append("plainSchema = ?").append(setParameter(parameters, cond.getSchema())).
+                query.append("plainSchema=?").append(setParameter(parameters, cond.getSchema())).
                         append(" AND ").
                         append(lower ? "LOWER(" : "").
                         append(schema.isUniqueConstraint()
diff --git a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java
index b8a009e..eb8d631 100644
--- a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java
+++ b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
+import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
@@ -74,6 +75,12 @@ public class PGJPAJSONAnySearchDAO extends JPAAnySearchDAO {
         return output;
     }
 
+    protected static String escapeIfString(final String value, final boolean isStr) {
+        return isStr
+                ? new StringBuilder().append('"').append(value.replace("'", "''")).append('"').toString()
+                : value;
+    }
+
     public PGJPAJSONAnySearchDAO(
             final RealmDAO realmDAO,
             final DynRealmDAO dynRealmDAO,
@@ -139,35 +146,37 @@ public class PGJPAJSONAnySearchDAO extends JPAAnySearchDAO {
             String key = key(schema.getType());
 
             String value = Optional.ofNullable(attrValue.getDateValue()).
-                    map(v -> String.valueOf(v.getTime())).
+                    map(DateTimeFormatter.ISO_OFFSET_DATE_TIME::format).
                     orElse(cond.getExpression());
 
             boolean isStr = true;
-            boolean lower;
+            boolean lower = false;
             if (schema.getType() == AttrSchemaType.String || schema.getType() == AttrSchemaType.Enum) {
                 lower = (cond.getType() == AttrCond.Type.IEQ || cond.getType() == AttrCond.Type.ILIKE);
-            } else {
+            } else if (schema.getType() != AttrSchemaType.Date) {
                 lower = false;
                 try {
                     switch (schema.getType()) {
-                        case Date:
                         case Long:
                             Long.parseLong(value);
                             break;
+
                         case Double:
                             Double.parseDouble(value);
                             break;
+
                         case Boolean:
                             if (!("true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value))) {
                                 throw new IllegalArgumentException();
                             }
                             break;
+
                         default:
                     }
 
                     isStr = false;
                 } catch (Exception nfe) {
-                    // ignore}
+                    // ignore
                 }
             }
 
@@ -202,10 +211,8 @@ public class PGJPAJSONAnySearchDAO extends JPAAnySearchDAO {
                             append("(@.").append(key);
                     if (StringUtils.containsAny(value, POSTGRESQL_REGEX_CHARS) || lower) {
                         query.append(" like_regex \"").append(escapeForLikeRegex(value).replace("'", "''")).append('"');
-                    } else if (isStr) {
-                        query.append(" == \"").append(value.replace("'", "''")).append('"');
                     } else {
-                        query.append(" == ").append(value);
+                        query.append(" == ").append(escapeIfString(value, isStr));
                     }
 
                     query.append(lower ? " flag \"i\"" : "").append(")')");
@@ -214,25 +221,25 @@ public class PGJPAJSONAnySearchDAO extends JPAAnySearchDAO {
                 case GE:
                     query.append("jsonb_path_exists(").append(schema.getKey()).append(", '$[*] ? ").
                             append("(@.").append(key).append(" >= ").
-                            append(value).append(")')");
+                            append(escapeIfString(value, isStr)).append(")')");
                     break;
 
                 case GT:
                     query.append("jsonb_path_exists(").append(schema.getKey()).append(", '$[*] ? ").
                             append("(@.").append(key).append(" > ").
-                            append(value).append(")')");
+                            append(escapeIfString(value, isStr)).append(")')");
                     break;
 
                 case LE:
                     query.append("jsonb_path_exists(").append(schema.getKey()).append(", '$[*] ? ").
                             append("(@.").append(key).append(" <= ").
-                            append(value).append(")')");
+                            append(escapeIfString(value, isStr)).append(")')");
                     break;
 
                 case LT:
                     query.append("jsonb_path_exists(").append(schema.getKey()).append(", '$[*] ? ").
                             append("(@.").append(key).append(" < ").
-                            append(value).append(")')");
+                            append(escapeIfString(value, isStr)).append(")')");
                     break;
 
                 default:
diff --git a/core/persistence-jpa-json/src/main/resources/myjson/views.xml b/core/persistence-jpa-json/src/main/resources/myjson/views.xml
index aa0e3c0..8e7da4d 100644
--- a/core/persistence-jpa-json/src/main/resources/myjson/views.xml
+++ b/core/persistence-jpa-json/src/main/resources/myjson/views.xml
@@ -56,7 +56,7 @@ under the License.
     NESTED PATH '$.values[*]' COLUMNS (
     binaryValue LONGBLOB PATH '$.binaryValue',
     booleanValue INT PATH '$.booleanValue',
-    dateValue BIGINT(20) PATH '$.dateValue',
+    dateValue VARCHAR(32) PATH '$.dateValue',
     doubleValue DOUBLE PATH '$.doubleValue',
     longValue BIGINT(20) PATH '$.longValue',
     stringValue VARCHAR(255) PATH '$.stringValue'),
@@ -120,7 +120,7 @@ under the License.
     NESTED PATH '$.values[*]' COLUMNS (
     binaryValue LONGBLOB PATH '$.binaryValue',
     booleanValue INT PATH '$.booleanValue',
-    dateValue BIGINT(20) PATH '$.dateValue',
+    dateValue VARCHAR(32) PATH '$.dateValue',
     doubleValue DOUBLE PATH '$.doubleValue',
     longValue BIGINT(20) PATH '$.longValue',
     stringValue VARCHAR(255) PATH '$.stringValue'),
@@ -164,7 +164,7 @@ under the License.
     NESTED PATH '$.values[*]' COLUMNS (
     binaryValue LONGBLOB PATH '$.binaryValue',
     booleanValue INT PATH '$.booleanValue',
-    dateValue BIGINT(20) PATH '$.dateValue',
+    dateValue VARCHAR(32) PATH '$.dateValue',
     doubleValue DOUBLE PATH '$.doubleValue',
     longValue BIGINT(20) PATH '$.longValue',
     stringValue VARCHAR(255) PATH '$.stringValue'),
diff --git a/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
index 31f115a..54ecf96 100644
--- a/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
@@ -346,26 +346,26 @@ under the License.
                realm_id="c5b75db1-fce7-470f-b780-3b9934d82a9d"
                username="rossini" creator="admin" lastModifier="admin"
                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"
-               plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;G&quot;}],&quot;schema&quot;:&quot;ctype&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Gioacchino&quot;}],&quot;schema&quot;:&quot;firstname&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Rossini&quot;}],&quot;schema&quot;:&quot;surname&quot;},{&quot;values&quot;:[{&quot;dateValue&quot;:1243288800000},{&quot;dateValue&quot;:1274824800000}],&quot;schema&quot;:&quot;loginDate&quot;},{&q [...]
+               plainAttrs='[{"values":[{"stringValue":"G"}],"schema":"ctype"},{"values":[{"stringValue":"Gioacchino"}],"schema":"firstname"},{"values":[{"stringValue":"Rossini"}],"schema":"surname"},{"values":[{"dateValue":"2009-05-26T00:00:00+02:00"},{"dateValue":"2010-05-26T00:00:00+02:00"}],"schema":"loginDate"},{"uniqueValue":{"stringValue":"Gioacchino Rossini"},"schema":"fullname"},{"uniqueValue":{"stringValue":"rossini@apache.org"},"schema":"userId"}]'/>
   <SyncopeUser_SyncopeRole user_id="1417acbe-cbf6-4277-9372-e75e04f97000" role_id="Other"/>
   <SyncopeUser mustChangePassword="0" id="74cd8ece-715a-44a4-a736-e17b46c4e7e6" status="active"
                password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
                username="verdi" creator="admin" lastModifier="admin"
                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"
-               plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Giuseppe&quot;}],&quot;schema&quot;:&quot;firstname&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Verdi&quot;}],&quot;schema&quot;:&quot;surname&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;verdi@syncope.org&quot;}],&quot;schema&quot;:&quot;email&quot;},{&quot;uniqueValue&quot;:{&quot;stringValue&quot;:&quot;Giuseppe Verdi&quot;},&quot;schema&quot;:&quot;fullname&quot;},{&quot;uniqu [...]
+               plainAttrs='[{"values":[{"stringValue":"Giuseppe"}],"schema":"firstname"},{"values":[{"stringValue":"Verdi"}],"schema":"surname"},{"values":[{"stringValue":"verdi@syncope.org"}],"schema":"email"},{"uniqueValue":{"stringValue":"Giuseppe Verdi"},"schema":"fullname"},{"uniqueValue":{"stringValue":"verdi@apache.org"},"schema":"userId"}]'/>
   <SyncopeUser mustChangePassword="0" id="b3cbc78d-32e6-4bd4-92e0-bbe07566a2ee" status="active"
                password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
                username="vivaldi" creator="admin" lastModifier="admin"
                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"
-               plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Antonio&quot;}],&quot;schema&quot;:&quot;firstname&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Vivaldi&quot;}],&quot;schema&quot;:&quot;surname&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;vivaldi@syncope.org&quot;}],&quot;schema&quot;:&quot;email&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;F&quot;}],&quot;schema&quot;:&quot;ctype&quot;},{&quot;uniqueValue&quot;:{&q [...]
+               plainAttrs='[{"values":[{"stringValue":"Antonio"}],"schema":"firstname"},{"values":[{"stringValue":"Vivaldi"}],"schema":"surname"},{"values":[{"stringValue":"vivaldi@syncope.org"}],"schema":"email"},{"values":[{"stringValue":"F"}],"schema":"ctype"},{"uniqueValue":{"stringValue":"Antonio Vivaldi"},"schema":"fullname"},{"uniqueValue":{"stringValue":"vivaldi@apache.org"},"schema":"userId"}]'/>
   <SyncopeUser mustChangePassword="0" id="c9b2dec2-00a7-4855-97c0-d854842b4b24" status="active"
                password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
                username="bellini" creator="admin" lastModifier="admin"
                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"
-               plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Vincenzo&quot;}],&quot;schema&quot;:&quot;firstname&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Bellini&quot;}],&quot;schema&quot;:&quot;surname&quot;},{&quot;values&quot;:[{&quot;dateValue&quot;:1245794400000}],&quot;schema&quot;:&quot;loginDate&quot;},{&quot;values&quot;:[{&quot;booleanValue&quot;:true}],&quot;schema&quot;:&quot;cool&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot; [...]
+               plainAttrs='[{"values":[{"stringValue":"Vincenzo"}],"schema":"firstname"},{"values":[{"stringValue":"Bellini"}],"schema":"surname"},{"values":[{"dateValue":"2009-06-24T00:00:00+02:00"}],"schema":"loginDate"},{"values":[{"booleanValue":true}],"schema":"cool"},{"values":[{"stringValue":"M"}],"schema":"gender"},{"uniqueValue":{"stringValue":"Vincenzo Bellini"},"schema":"fullname"},{"uniqueValue":{"stringValue":"bellini@apache.org"},"schema":"userId"}]'/>
   <SyncopeUser_SyncopeRole user_id="c9b2dec2-00a7-4855-97c0-d854842b4b24" role_id="User reviewer"/>
   <SyncopeUser_SyncopeRole user_id="c9b2dec2-00a7-4855-97c0-d854842b4b24" role_id="User manager"/>
   <SyncopeUser mustChangePassword="0" id="823074dc-d280-436d-a7dd-07399fae48ec" status="active"
@@ -373,7 +373,7 @@ under the License.
                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
                username="puccini" creator="admin" lastModifier="admin" 
                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"
-               plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Giacomo&quot;}],&quot;schema&quot;:&quot;firstname&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Puccini&quot;}],&quot;schema&quot;:&quot;surname&quot;},{&quot;uniqueValue&quot;:{&quot;stringValue&quot;:&quot;Giacomo Puccini&quot;},&quot;schema&quot;:&quot;fullname&quot;},{&quot;uniqueValue&quot;:{&quot;stringValue&quot;:&quot;puccini@apache.org&quot;},&quot;schema&quot;:&quot;userId&quot;}]"/>
+               plainAttrs='[{"values":[{"stringValue":"Giacomo"}],"schema":"firstname"},{"values":[{"stringValue":"Puccini"}],"schema":"surname"},{"uniqueValue":{"stringValue":"Giacomo Puccini"},"schema":"fullname"},{"uniqueValue":{"stringValue":"puccini@apache.org"},"schema":"userId"}]'/>
   <SyncopeUser_SyncopeRole user_id="823074dc-d280-436d-a7dd-07399fae48ec" role_id="Search for realm evenTwo"/>
   <SyncopeUser_SyncopeRole user_id="823074dc-d280-436d-a7dd-07399fae48ec" role_id="Connector and Resource for realm evenTwo"/>
   
@@ -1031,7 +1031,7 @@ under the License.
   <Task DTYPE="PropagationTask" id="1e697572-b896-484c-ae7f-0c8f63fcbc6c" operation="UPDATE"
         objectClassName="__ACCOUNT__" resource_id="ws-target-resource-2" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
         attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"fullname","value":["fullname"]},{"name":"type","value":["type"]}]'/>
-  <TaskExec id="e58ca1c7-178a-4012-8a71-8aa14eaf0655" task_id="1e697572-b896-484c-ae7f-0c8f63fcbc6c" startDate="2015-12-17 09:40:00.506" endDate="2015-12-17 09:42:00.506" status="SUCCESS"/>
+  <TaskExec id="e58ca1c7-178a-4012-8a71-8aa14eaf0655" task_id="1e697572-b896-484c-ae7f-0c8f63fcbc6c" startDate="2015-12-17 09:40:00" endDate="2015-12-17 09:42:00" status="SUCCESS"/>
   <Task DTYPE="PropagationTask" id="b8870cfb-3c1e-4fc4-abcb-2559826232e6" operation="CREATE"
         objectClassName="__ACCOUNT__" resource_id="ws-target-resource-2" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
         attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"fullname","value":["fullname"]},{"name":"type","value":["type"]}]'/>
@@ -1042,7 +1042,7 @@ under the License.
   <Task DTYPE="PropagationTask" id="025c956d-ea88-4bd7-9e44-2f35e0aa7055" operation="UPDATE"
         objectClassName="__ACCOUNT__" resource_id="ws-target-resource-1" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
         attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"fullname","value":["fullname"]},{"name":"type","value":["type"]}]'/>
-  <TaskExec id="c3290f8b-caf9-4a85-84fb-fb619b65cd49" task_id="025c956d-ea88-4bd7-9e44-2f35e0aa7055" startDate="2015-12-17 09:40:00.506" endDate="2015-12-17 09:42:00.506" status="SUCCESS"/>
+  <TaskExec id="c3290f8b-caf9-4a85-84fb-fb619b65cd49" task_id="025c956d-ea88-4bd7-9e44-2f35e0aa7055" startDate="2015-12-17 09:40:00" endDate="2015-12-17 09:42:00" status="SUCCESS"/>
   <Task DTYPE="PullTask" remediation="0" id="c41b9b71-9bfa-4f90-89f2-84787def4c5c" name="CSV (update matching; assign unmatching)" resource_id="resource-csv"
         destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
         pullMode="INCREMENTAL" unmatchingRule="ASSIGN" matchingRule="UPDATE" active="1"
@@ -1064,7 +1064,7 @@ under the License.
   <Task DTYPE="PropagationTask" id="d6c2d6d3-6329-44c1-9187-f1469ead1cfa" operation="UPDATE"
         objectClassName="__ACCOUNT__" resource_id="ws-target-resource-nopropagation" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
         attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"fullname","value":["fullname"]},{"name":"type","value":["type"]}]'/>
-  <TaskExec id="d789462f-e395-424f-bd8e-0db44a93222f" task_id="d6c2d6d3-6329-44c1-9187-f1469ead1cfa" startDate="2015-12-17 09:40:00.506" endDate="2015-12-17 09:42:00.506" status="SUCCESS"/>
+  <TaskExec id="d789462f-e395-424f-bd8e-0db44a93222f" task_id="d6c2d6d3-6329-44c1-9187-f1469ead1cfa" startDate="2015-12-17 09:40:00" endDate="2015-12-17 09:42:00" status="SUCCESS"/>
   <Task DTYPE="PullTask" remediation="0" id="83f7e85d-9774-43fe-adba-ccd856312994" name="TestDB Task" resource_id="resource-testdb"
         destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="1" performUpdate="1" performDelete="0" syncStatus="1" pullMode="FULL_RECONCILIATION"
         unmatchingRule="PROVISION" matchingRule="UPDATE" active="1" jobDelegate_id="PullJobDelegate"/>
diff --git a/core/persistence-jpa/pom.xml b/core/persistence-jpa/pom.xml
index 192a4d8..aa85f76 100644
--- a/core/persistence-jpa/pom.xml
+++ b/core/persistence-jpa/pom.xml
@@ -179,6 +179,7 @@ under the License.
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
           <systemProperties>
+            <h2.returnOffsetDateTime>true</h2.returnOffsetDateTime>
             <CORE_PROPERTIES>classpath:core-test.properties</CORE_PROPERTIES>
           </systemProperties>
         </configuration>
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/BinaryValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/BinaryValidator.java
index 97c2649..0df8bb2 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/BinaryValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/BinaryValidator.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.jpa.attrvalue.validation;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.IOException;
 import javax.ws.rs.core.MediaType;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
@@ -29,7 +29,7 @@ public class BinaryValidator extends AbstractValidator {
 
     private static final long serialVersionUID = 1344152444666540361L;
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private static final Tika TIKA = new Tika();
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/ContentLoaderHandler.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/ContentLoaderHandler.java
index 1673e9b..f07957a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/ContentLoaderHandler.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/ContentLoaderHandler.java
@@ -19,11 +19,10 @@
 package org.apache.syncope.core.persistence.jpa.content;
 
 import java.sql.Types;
-import java.text.ParseException;
+import java.time.format.DateTimeParseException;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
-
 import javax.sql.DataSource;
 import javax.xml.bind.DatatypeConverter;
 import org.apache.commons.lang3.StringUtils;
@@ -139,9 +138,11 @@ public class ContentLoaderHandler extends DefaultHandler {
                 case Types.DATE:
                 case Types.TIME:
                 case Types.TIMESTAMP:
+                case Types.TIMESTAMP_WITH_TIMEZONE:
+                case -101:
                     try {
                     parameters[i] = FormatUtils.parseDate(value);
-                } catch (ParseException e) {
+                } catch (DateTimeParseException e) {
                     LOG.error("Unparsable Date '{}'", value);
                     parameters[i] = value;
                 }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/KeymasterConfParamLoader.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/KeymasterConfParamLoader.java
index 0c6e1a7..0ee5988 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/KeymasterConfParamLoader.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/KeymasterConfParamLoader.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.content;
 
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Iterator;
@@ -38,7 +38,7 @@ public class KeymasterConfParamLoader implements ConfParamLoader {
 
     protected static final Logger LOG = LoggerFactory.getLogger(KeymasterConfParamLoader.class);
 
-    protected static final ObjectMapper MAPPER = new ObjectMapper();
+    protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     protected final ConfParamOps confParamOps;
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
index 397bc9b..7958e17 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
@@ -32,9 +32,11 @@ import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.sql.Timestamp;
 import java.sql.Types;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -228,7 +230,8 @@ public class XMLContentExporter implements ContentExporter {
                 case Types.TIMESTAMP:
                     Timestamp timestamp = rs.getTimestamp(columnName);
                     if (timestamp != null) {
-                        res = FormatUtils.format(new Date(timestamp.getTime()));
+                        res = FormatUtils.format(OffsetDateTime.ofInstant(
+                                Instant.ofEpochMilli(timestamp.getTime()), ZoneId.systemDefault()));
                     }
                     break;
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
index 3133c9e..e706221 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
@@ -18,10 +18,13 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
-import java.time.LocalDateTime;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -30,13 +33,12 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.regex.Pattern;
 import javax.persistence.Query;
-import javax.persistence.TemporalType;
 import javax.persistence.TypedQuery;
-
 import org.apache.commons.jexl3.parser.Parser;
 import org.apache.commons.jexl3.parser.ParserConstants;
 import org.apache.commons.jexl3.parser.Token;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.openjpa.persistence.OpenJPAPersistence;
 import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
 import org.apache.syncope.core.persistence.api.dao.AnyDAO;
 import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
@@ -136,23 +138,23 @@ public abstract class AbstractAnyDAO<A extends Any<?>> extends AbstractDAO<A> im
         return result;
     }
 
-    protected Date findLastChange(final String key, final String table) {
-        Query query = entityManager().createNativeQuery(
-                "SELECT creationDate, lastChangeDate FROM " + table + " WHERE id=?");
-        query.setParameter(1, key);
+    protected OffsetDateTime findLastChange(final String key, final String table) {
+        OffsetDateTime creationDate = null;
+        OffsetDateTime lastChangeDate = null;
 
-        @SuppressWarnings("unchecked")
-        List<Object[]> result = query.getResultList();
-
-        Date creationDate = null;
-        Date lastChangeDate = null;
-        if (!result.isEmpty()) {
-            creationDate = result.get(0)[0] instanceof LocalDateTime
-                    ? convert((LocalDateTime) result.get(0)[0])
-                    : (Date) result.get(0)[0];
-            lastChangeDate = result.get(0)[1] instanceof LocalDateTime
-                    ? convert((LocalDateTime) result.get(0)[1])
-                    : (Date) result.get(0)[1];
+        try (Connection conn = (Connection) OpenJPAPersistence.cast(entityManager()).getConnection()) {
+            try (PreparedStatement stmt =
+                    conn.prepareStatement("SELECT creationDate, lastChangeDate FROM " + table + " WHERE id=?")) {
+                stmt.setString(1, key);
+
+                ResultSet rs = stmt.executeQuery();
+                if (rs.next()) {
+                    creationDate = rs.getObject(1, OffsetDateTime.class);
+                    lastChangeDate = rs.getObject(2, OffsetDateTime.class);
+                }
+            }
+        } catch (SQLException e) {
+            LOG.error("While reading {} from {}", key, table, e);
         }
 
         return Optional.ofNullable(lastChangeDate).orElse(creationDate);
@@ -231,7 +233,7 @@ public abstract class AbstractAnyDAO<A extends Any<?>> extends AbstractDAO<A> im
         if (attrValue.getDateValue() == null) {
             query.setParameter("dateValue", null);
         } else {
-            query.setParameter("dateValue", attrValue.getDateValue(), TemporalType.TIMESTAMP);
+            query.setParameter("dateValue", attrValue.getDateValue().toInstant());
         }
         query.setParameter("longValue", attrValue.getLongValue());
         query.setParameter("doubleValue", attrValue.getDoubleValue());
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractDAO.java
index 7277a63..4ad4d9c 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractDAO.java
@@ -18,9 +18,6 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.util.Date;
 import javax.persistence.EntityManager;
 import org.apache.syncope.core.persistence.api.dao.DAO;
 import org.apache.syncope.core.persistence.api.entity.Entity;
@@ -34,10 +31,6 @@ public abstract class AbstractDAO<E extends Entity> implements DAO<E> {
 
     protected static final Logger LOG = LoggerFactory.getLogger(DAO.class);
 
-    protected Date convert(final LocalDateTime localDateTime) {
-        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
-    }
-
     protected EntityManager entityManager() {
         EntityManager entityManager = EntityManagerFactoryUtils.getTransactionalEntityManager(
                 EntityManagerFactoryUtils.findEntityManagerFactory(
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAccessTokenDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAccessTokenDAO.java
index 3753b74..be62292 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAccessTokenDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAccessTokenDAO.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import javax.persistence.NoResultException;
 import javax.persistence.Query;
@@ -134,7 +134,7 @@ public class JPAAccessTokenDAO extends AbstractDAO<AccessToken> implements Acces
         Query query = entityManager().createQuery(
                 "DELETE FROM " + JPAAccessToken.class.getSimpleName() + " e "
                 + "WHERE e.expirationTime < :now");
-        query.setParameter("now", new Date());
+        query.setParameter("now", OffsetDateTime.now());
         return query.executeUpdate();
     }
 }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyMatchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyMatchDAO.java
index 7419751..a0dc2fa 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyMatchDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyMatchDAO.java
@@ -21,8 +21,8 @@ package org.apache.syncope.core.persistence.jpa.dao;
 import java.beans.PropertyDescriptor;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
 import java.util.Optional;
 import java.util.regex.Pattern;
@@ -483,8 +483,8 @@ public class JPAAnyMatchDAO extends AbstractDAO<Any<?>> implements AnyMatchDAO {
                     anyAttrValues.get(0).setDoubleValue((Double) anyAttrValue);
                 } else if (anyAttrValue instanceof Boolean) {
                     anyAttrValues.get(0).setBooleanValue((Boolean) anyAttrValue);
-                } else if (anyAttrValue instanceof Date) {
-                    anyAttrValues.get(0).setDateValue((Date) anyAttrValue);
+                } else if (anyAttrValue instanceof OffsetDateTime) {
+                    anyAttrValues.get(0).setDateValue((OffsetDateTime) anyAttrValue);
                 } else if (anyAttrValue instanceof byte[]) {
                     anyAttrValues.get(0).setBinaryValue((byte[]) anyAttrValue);
                 }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
index 81e9a8f..04c2a49 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
@@ -18,10 +18,10 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -100,7 +100,7 @@ public class JPAAnyObjectDAO extends AbstractAnyDAO<AnyObject> implements AnyObj
 
     @Transactional(readOnly = true)
     @Override
-    public Date findLastChange(final String key) {
+    public OffsetDateTime findLastChange(final String key) {
         return findLastChange(key, JPAAnyObject.TABLE);
     }
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
index 51a4e52..4e2ed07 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
@@ -19,14 +19,12 @@
 package org.apache.syncope.core.persistence.jpa.dao;
 
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 import javax.persistence.Query;
-import javax.persistence.TemporalType;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
@@ -243,9 +241,7 @@ public class JPAAnySearchDAO extends AbstractAnySearchDAO {
 
     protected void fillWithParameters(final Query query, final List<Object> parameters) {
         for (int i = 0; i < parameters.size(); i++) {
-            if (parameters.get(i) instanceof Date) {
-                query.setParameter(i + 1, (Date) parameters.get(i), TemporalType.TIMESTAMP);
-            } else if (parameters.get(i) instanceof Boolean) {
+            if (parameters.get(i) instanceof Boolean) {
                 query.setParameter(i + 1, ((Boolean) parameters.get(i)) ? 1 : 0);
             } else {
                 query.setParameter(i + 1, parameters.get(i));
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPABatchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPABatchDAO.java
index 1ea7dd6..5d785ec 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPABatchDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPABatchDAO.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import javax.persistence.Query;
 import org.apache.syncope.core.persistence.api.dao.BatchDAO;
 import org.apache.syncope.core.persistence.api.entity.Batch;
@@ -53,7 +53,7 @@ public class JPABatchDAO extends AbstractDAO<Batch> implements BatchDAO {
     public int deleteExpired() {
         Query query = entityManager().createQuery(
                 "DELETE FROM " + JPABatch.class.getSimpleName() + " e WHERE e.expiryTime < :now");
-        query.setParameter("now", new Date());
+        query.setParameter("now", OffsetDateTime.now());
         return query.executeUpdate();
     }
 }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADelegationDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADelegationDAO.java
index c3cced3..7a24153 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADelegationDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADelegationDAO.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
@@ -44,7 +44,7 @@ public class JPADelegationDAO extends AbstractDAO<Delegation> implements Delegat
                 + "AND e.start <= :now AND (e.end IS NULL OR e.end >= :now)", Delegation.class);
         query.setParameter("delegating", delegating);
         query.setParameter("delegated", delegated);
-        query.setParameter("now", new Date());
+        query.setParameter("now", OffsetDateTime.now());
         query.setMaxResults(1);
 
         List<Delegation> raw = query.getResultList();
@@ -58,7 +58,7 @@ public class JPADelegationDAO extends AbstractDAO<Delegation> implements Delegat
                 + "WHERE e.delegated.id=:delegated "
                 + "AND e.start <= :now AND (e.end IS NULL OR e.end >= :now)", Delegation.class);
         query.setParameter("delegated", delegated);
-        query.setParameter("now", new Date());
+        query.setParameter("now", OffsetDateTime.now());
 
         return query.getResultList().stream().
                 map(delegation -> delegation.getDelegating().getUsername()).
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
index dc1a86d..b55ba20 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
@@ -18,9 +18,9 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -127,7 +127,7 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
 
     @Transactional(readOnly = true)
     @Override
-    public Date findLastChange(final String key) {
+    public OffsetDateTime findLastChange(final String key) {
         return findLastChange(key, JPAGroup.TABLE);
     }
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportExecDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportExecDAO.java
index 113398d..4d49c67 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportExecDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportExecDAO.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import javax.persistence.Query;
 import javax.persistence.TypedQuery;
@@ -121,7 +121,10 @@ public class JPAReportExecDAO extends AbstractDAO<ReportExec> implements ReportE
     @Override
     public List<ReportExec> findAll(
             final Report report,
-            final Date startedBefore, final Date startedAfter, final Date endedBefore, final Date endedAfter) {
+            final OffsetDateTime startedBefore,
+            final OffsetDateTime startedAfter,
+            final OffsetDateTime endedBefore,
+            final OffsetDateTime endedAfter) {
 
         StringBuilder queryString = new StringBuilder("SELECT e FROM ").append(JPAReportExec.class.getSimpleName()).
                 append(" e WHERE e.report=:report ");
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
index d7d573c..5701468 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
@@ -19,8 +19,8 @@
 package org.apache.syncope.core.persistence.jpa.dao;
 
 import java.lang.reflect.Field;
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
 import javax.persistence.DiscriminatorValue;
@@ -488,9 +488,10 @@ public class JPATaskDAO extends AbstractDAO<Task> implements TaskDAO {
 
     @Override
     public List<PropagationTaskTO> purgePropagations(
-            final Date since, 
-            final List<ExecStatus> statuses, 
+            final OffsetDateTime since,
+            final List<ExecStatus> statuses,
             final List<ExternalResource> externalResources) {
+
         StringBuilder queryString = new StringBuilder("SELECT t.task_id "
                 + "FROM TaskExec t INNER JOIN Task z ON t.task_id=z.id AND z.dtype='PropagationTask' "
                 + "WHERE t.enddate=(SELECT MAX(e.enddate) FROM TaskExec e WHERE e.task_id=t.task_id) ");
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskExecDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskExecDAO.java
index c5863ac..6728acc 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskExecDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskExecDAO.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import javax.persistence.Query;
 import javax.persistence.TypedQuery;
@@ -80,7 +80,10 @@ public class JPATaskExecDAO extends AbstractDAO<TaskExec> implements TaskExecDAO
     @Override
     public <T extends Task> List<TaskExec> findAll(
             final T task,
-            final Date startedBefore, final Date startedAfter, final Date endedBefore, final Date endedAfter) {
+            final OffsetDateTime startedBefore,
+            final OffsetDateTime startedAfter,
+            final OffsetDateTime endedBefore,
+            final OffsetDateTime endedAfter) {
 
         StringBuilder queryString = new StringBuilder("SELECT e FROM ").append(JPATaskExec.class.getSimpleName()).
                 append(" e WHERE e.task=:task ");
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
index 4143c2c..7ecb27a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
@@ -18,9 +18,9 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -130,7 +130,7 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
 
     @Transactional(readOnly = true)
     @Override
-    public Date findLastChange(final String key) {
+    public OffsetDateTime findLastChange(final String key) {
         return findLastChange(key, JPAUser.TABLE);
     }
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
index a667e19..c0ddc0d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
@@ -18,14 +18,11 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
-import java.util.Date;
-import java.util.Optional;
+import java.time.OffsetDateTime;
 import javax.persistence.Column;
 import javax.persistence.FetchType;
 import javax.persistence.ManyToOne;
 import javax.persistence.MappedSuperclass;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.PlainAttr;
 import org.apache.syncope.core.persistence.api.entity.Realm;
@@ -45,8 +42,7 @@ public abstract class AbstractAny<P extends PlainAttr<?>> extends AbstractGenera
     /**
      * Creation date.
      */
-    @Temporal(TemporalType.TIMESTAMP)
-    private Date creationDate;
+    private OffsetDateTime creationDate;
 
     /**
      * Context information about create.
@@ -58,8 +54,7 @@ public abstract class AbstractAny<P extends PlainAttr<?>> extends AbstractGenera
      */
     private String lastModifier;
 
-    @Temporal(TemporalType.TIMESTAMP)
-    private Date lastChangeDate;
+    private OffsetDateTime lastChangeDate;
 
     /**
      * Context information about last update.
@@ -83,13 +78,13 @@ public abstract class AbstractAny<P extends PlainAttr<?>> extends AbstractGenera
     }
 
     @Override
-    public Date getCreationDate() {
-        return Optional.ofNullable(creationDate).map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getCreationDate() {
+        return creationDate;
     }
 
     @Override
-    public void setCreationDate(final Date creationDate) {
-        this.creationDate = Optional.ofNullable(creationDate).map(date -> new Date(date.getTime())).orElse(null);
+    public void setCreationDate(final OffsetDateTime creationDate) {
+        this.creationDate = creationDate;
     }
 
     @Override
@@ -113,19 +108,19 @@ public abstract class AbstractAny<P extends PlainAttr<?>> extends AbstractGenera
     }
 
     @Override
-    public Date getLastChangeDate() {
+    public OffsetDateTime getLastChangeDate() {
         if (lastChangeDate != null) {
-            return new Date(lastChangeDate.getTime());
+            return lastChangeDate;
         } else if (creationDate != null) {
-            return new Date(creationDate.getTime());
+            return creationDate;
         }
 
         return null;
     }
 
     @Override
-    public void setLastChangeDate(final Date lastChangeDate) {
-        this.lastChangeDate = Optional.ofNullable(lastChangeDate).map(date -> new Date(date.getTime())).orElse(null);
+    public void setLastChangeDate(final OffsetDateTime lastChangeDate) {
+        this.lastChangeDate = lastChangeDate;
     }
 
     @Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractExec.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractExec.java
index e2ca193..f334a5a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractExec.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractExec.java
@@ -18,15 +18,11 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.Optional;
-
 import javax.persistence.Column;
-
 import javax.persistence.Lob;
 import javax.persistence.MappedSuperclass;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
 import javax.validation.constraints.NotNull;
 import org.apache.syncope.core.persistence.api.entity.Exec;
 
@@ -51,16 +47,14 @@ public abstract class AbstractExec extends AbstractGeneratedKeyEntity implements
      * Start instant of this execution.
      */
     @NotNull
-    @Temporal(TemporalType.TIMESTAMP)
-    @Column(name = "startDate")
-    protected Date start;
+    @Column(name = "startDate", nullable = false)
+    protected OffsetDateTime start;
 
     /**
      * End instant of this execution.
      */
-    @Temporal(TemporalType.TIMESTAMP)
     @Column(name = "endDate")
-    protected Date end;
+    protected OffsetDateTime end;
 
     @Override
     public String getStatus() {
@@ -93,22 +87,22 @@ public abstract class AbstractExec extends AbstractGeneratedKeyEntity implements
     }
 
     @Override
-    public Date getStart() {
-        return Optional.ofNullable(start).map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getStart() {
+        return start;
     }
 
     @Override
-    public void setStart(final Date start) {
-        this.start = Optional.ofNullable(start).map(date -> new Date(date.getTime())).orElse(null);
+    public void setStart(final OffsetDateTime start) {
+        this.start = start;
     }
 
     @Override
-    public Date getEnd() {
-        return Optional.ofNullable(end).map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getEnd() {
+        return end;
     }
 
     @Override
-    public void setEnd(final Date end) {
-        this.end = Optional.ofNullable(end).map(date -> new Date(date.getTime())).orElse(null);
+    public void setEnd(final OffsetDateTime end) {
+        this.end = end;
     }
 }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractPlainAttrValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractPlainAttrValue.java
index 8bac409..d535dba 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractPlainAttrValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractPlainAttrValue.java
@@ -18,14 +18,12 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
+import java.time.OffsetDateTime;
 import java.util.Base64;
-import java.util.Date;
 import java.util.Optional;
 import java.util.regex.Pattern;
 import javax.persistence.Lob;
 import javax.persistence.MappedSuperclass;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.builder.ToStringBuilder;
@@ -49,8 +47,7 @@ public abstract class AbstractPlainAttrValue extends AbstractGeneratedKeyEntity
 
     private String stringValue;
 
-    @Temporal(TemporalType.TIMESTAMP)
-    private Date dateValue;
+    private OffsetDateTime dateValue;
 
     private Boolean booleanValue;
 
@@ -72,13 +69,13 @@ public abstract class AbstractPlainAttrValue extends AbstractGeneratedKeyEntity
     }
 
     @Override
-    public Date getDateValue() {
-        return Optional.ofNullable(dateValue).map(value -> new Date(value.getTime())).orElse(null);
+    public OffsetDateTime getDateValue() {
+        return dateValue;
     }
 
     @Override
-    public void setDateValue(final Date dateValue) {
-        this.dateValue = Optional.ofNullable(dateValue).map(value -> new Date(value.getTime())).orElse(null);
+    public void setDateValue(final OffsetDateTime dateValue) {
+        this.dateValue = dateValue;
     }
 
     @Override
@@ -170,7 +167,7 @@ public abstract class AbstractPlainAttrValue extends AbstractGeneratedKeyEntity
                 try {
                 this.setDateValue(schema.getConversionPattern() == null
                         ? FormatUtils.parseDate(value)
-                        : new Date(FormatUtils.parseDate(value, schema.getConversionPattern()).getTime()));
+                        : FormatUtils.parseDate(value, schema.getConversionPattern()));
             } catch (Exception pe) {
                 exception = pe;
             }
@@ -284,7 +281,7 @@ public abstract class AbstractPlainAttrValue extends AbstractGeneratedKeyEntity
             case Date:
                 result = schema == null || schema.getConversionPattern() == null
                         ? FormatUtils.format(getDateValue())
-                        : FormatUtils.format(getDateValue(), false, schema.getConversionPattern());
+                        : FormatUtils.format(getDateValue(), schema.getConversionPattern());
                 break;
 
             case Binary:
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAccessToken.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAccessToken.java
index 326c702..42f4887 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAccessToken.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAccessToken.java
@@ -18,16 +18,12 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
-import java.util.Date;
-import java.util.Optional;
-
+import java.time.OffsetDateTime;
 import javax.persistence.Cacheable;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.Lob;
 import javax.persistence.Table;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.syncope.core.persistence.api.entity.AccessToken;
 
@@ -43,8 +39,7 @@ public class JPAAccessToken extends AbstractProvidedKeyEntity implements AccessT
     @Lob
     private String body;
 
-    @Temporal(TemporalType.TIMESTAMP)
-    private Date expirationTime;
+    private OffsetDateTime expirationTime;
 
     @Column(unique = true)
     private String owner;
@@ -63,13 +58,13 @@ public class JPAAccessToken extends AbstractProvidedKeyEntity implements AccessT
     }
 
     @Override
-    public Date getExpirationTime() {
-        return Optional.ofNullable(expirationTime).map(time -> new Date(time.getTime())).orElse(null);
+    public OffsetDateTime getExpirationTime() {
+        return expirationTime;
     }
 
     @Override
-    public void setExpirationTime(final Date expirationTime) {
-        this.expirationTime = Optional.ofNullable(expirationTime).map(time -> new Date(time.getTime())).orElse(null);
+    public void setExpirationTime(final OffsetDateTime expirationTime) {
+        this.expirationTime = expirationTime;
     }
 
     @Override
@@ -91,5 +86,4 @@ public class JPAAccessToken extends AbstractProvidedKeyEntity implements AccessT
     public void setAuthorities(final byte[] authorities) {
         this.authorities = ArrayUtils.clone(authorities);
     }
-
 }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPABatch.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPABatch.java
index eb2d9c7..859b76b 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPABatch.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPABatch.java
@@ -18,14 +18,10 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
-import java.util.Date;
-import java.util.Optional;
-
+import java.time.OffsetDateTime;
 import javax.persistence.Entity;
 import javax.persistence.Lob;
 import javax.persistence.Table;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
 import org.apache.syncope.core.persistence.api.entity.Batch;
 
 @Entity
@@ -36,24 +32,19 @@ public class JPABatch extends AbstractProvidedKeyEntity implements Batch {
 
     public static final String TABLE = "SyncopeBatch";
 
-    @Temporal(TemporalType.TIMESTAMP)
-    private Date expiryTime;
+    private OffsetDateTime expiryTime;
 
     @Lob
     private String results;
 
     @Override
-    public Date getExpiryTime() {
-        return Optional.ofNullable(expiryTime).map(time -> new Date(time.getTime())).orElse(null);
+    public OffsetDateTime getExpiryTime() {
+        return expiryTime;
     }
 
     @Override
-    public void setExpiryTime(final Date expiryTime) {
-        if (expiryTime == null) {
-            this.expiryTime = null;
-        } else {
-            this.expiryTime = new Date(expiryTime.getTime());
-        }
+    public void setExpiryTime(final OffsetDateTime expiryTime) {
+        this.expiryTime = expiryTime;
     }
 
     @Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADelegation.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADelegation.java
index e49325f..4a14b33 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADelegation.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADelegation.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.HashSet;
 import java.util.Set;
 import javax.persistence.Cacheable;
@@ -27,8 +27,6 @@ import javax.persistence.Entity;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
 import javax.persistence.UniqueConstraint;
 import javax.validation.constraints.NotNull;
 import org.apache.syncope.core.persistence.api.entity.Delegation;
@@ -55,13 +53,11 @@ public class JPADelegation extends AbstractGeneratedKeyEntity implements Delegat
     private JPAUser delegated;
 
     @NotNull
-    @Temporal(TemporalType.TIMESTAMP)
-    @Column(name = "startDate")
-    private Date start;
+    @Column(name = "startDate", nullable = false)
+    private OffsetDateTime start;
 
-    @Temporal(TemporalType.TIMESTAMP)
     @Column(name = "endDate")
-    private Date end;
+    private OffsetDateTime end;
 
     @OneToMany
     private Set<JPARole> roles = new HashSet<>();
@@ -89,31 +85,23 @@ public class JPADelegation extends AbstractGeneratedKeyEntity implements Delegat
     }
 
     @Override
-    public Date getStart() {
-        return start == null
-                ? null
-                : new Date(start.getTime());
+    public OffsetDateTime getStart() {
+        return start;
     }
 
     @Override
-    public void setStart(final Date start) {
-        this.start = start == null
-                ? null
-                : new Date(start.getTime());
+    public void setStart(final OffsetDateTime start) {
+        this.start = start;
     }
 
     @Override
-    public Date getEnd() {
-        return end == null
-                ? null
-                : new Date(end.getTime());
+    public OffsetDateTime getEnd() {
+        return end;
     }
 
     @Override
-    public void setEnd(final Date end) {
-        this.end = end == null
-                ? null
-                : new Date(end.getTime());
+    public void setEnd(final OffsetDateTime end) {
+        this.end = end;
     }
 
     @Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARemediation.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARemediation.java
index 071e5da..538c43c 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARemediation.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARemediation.java
@@ -18,17 +18,13 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
-import java.util.Date;
-import java.util.Optional;
-
+import java.time.OffsetDateTime;
 import javax.persistence.Entity;
 import javax.persistence.EnumType;
 import javax.persistence.Enumerated;
 import javax.persistence.Lob;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
 import javax.validation.constraints.NotNull;
 import org.apache.syncope.common.lib.request.AnyCR;
 import org.apache.syncope.common.lib.request.AnyUR;
@@ -65,8 +61,7 @@ public class JPARemediation extends AbstractGeneratedKeyEntity implements Remedi
     private String error;
 
     @NotNull
-    @Temporal(TemporalType.TIMESTAMP)
-    private Date instant;
+    private OffsetDateTime instant;
 
     @ManyToOne
     private JPAPullTask pullTask;
@@ -136,13 +131,13 @@ public class JPARemediation extends AbstractGeneratedKeyEntity implements Remedi
     }
 
     @Override
-    public Date getInstant() {
-        return Optional.ofNullable(instant).map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getInstant() {
+        return instant;
     }
 
     @Override
-    public void setInstant(final Date instant) {
-        this.instant = Optional.ofNullable(instant).map(date -> new Date(date.getTime())).orElse(null);
+    public void setInstant(final OffsetDateTime instant) {
+        this.instant = instant;
     }
 
     @Override
@@ -165,5 +160,4 @@ public class JPARemediation extends AbstractGeneratedKeyEntity implements Remedi
     public void setRemoteName(final String remoteName) {
         this.remoteName = remoteName;
     }
-
 }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/auth/JPAAuthProfile.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/auth/JPAAuthProfile.java
index 9f00afc..e1e4d03 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/auth/JPAAuthProfile.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/auth/JPAAuthProfile.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.persistence.jpa.entity.auth;
 import com.fasterxml.jackson.core.type.TypeReference;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.Lob;
@@ -48,7 +49,7 @@ public class JPAAuthProfile extends AbstractGeneratedKeyEntity implements AuthPr
     private String owner;
 
     @Lob
-    private String impersonatedAccounts;
+    private String impersonationAccounts;
 
     @Lob
     private String googleMfaAuthAccounts;
@@ -74,67 +75,61 @@ public class JPAAuthProfile extends AbstractGeneratedKeyEntity implements AuthPr
 
     @Override
     public List<GoogleMfaAuthToken> getGoogleMfaAuthTokens() {
-        return googleMfaAuthTokens == null
-                ? new ArrayList<>(0)
-                : POJOHelper.deserialize(googleMfaAuthTokens, new TypeReference<>() {
-        });
+        return Optional.ofNullable(googleMfaAuthTokens).
+                map(v -> POJOHelper.deserialize(v, new TypeReference<List<GoogleMfaAuthToken>>() {
+        })).orElseGet(() -> new ArrayList<>(0));
     }
 
     @Override
     public void setGoogleMfaAuthTokens(final List<GoogleMfaAuthToken> tokens) {
-        this.googleMfaAuthTokens = POJOHelper.serialize(tokens);
+        googleMfaAuthTokens = POJOHelper.serialize(tokens);
     }
 
     @Override
     public List<GoogleMfaAuthAccount> getGoogleMfaAuthAccounts() {
-        return googleMfaAuthAccounts == null
-                ? new ArrayList<>(0)
-                : POJOHelper.deserialize(googleMfaAuthAccounts, new TypeReference<>() {
-        });
+        return Optional.ofNullable(googleMfaAuthAccounts).
+                map(v -> POJOHelper.deserialize(v, new TypeReference<List<GoogleMfaAuthAccount>>() {
+        })).orElseGet(() -> new ArrayList<>(0));
     }
 
     @Override
     public void setGoogleMfaAuthAccounts(final List<GoogleMfaAuthAccount> accounts) {
-        this.googleMfaAuthAccounts = POJOHelper.serialize(accounts);
+        googleMfaAuthAccounts = POJOHelper.serialize(accounts);
     }
 
     @Override
     public List<U2FDevice> getU2FRegisteredDevices() {
-        return u2fRegisteredDevices == null
-                ? new ArrayList<>(0)
-                : POJOHelper.deserialize(u2fRegisteredDevices, new TypeReference<>() {
-        });
+        return Optional.ofNullable(u2fRegisteredDevices).
+                map(v -> POJOHelper.deserialize(v, new TypeReference<List<U2FDevice>>() {
+        })).orElseGet(() -> new ArrayList<>(0));
     }
 
     @Override
     public void setU2FRegisteredDevices(final List<U2FDevice> records) {
-        this.u2fRegisteredDevices = POJOHelper.serialize(records);
+        u2fRegisteredDevices = POJOHelper.serialize(records);
     }
 
     @Override
     public List<ImpersonationAccount> getImpersonationAccounts() {
-        return impersonatedAccounts == null
-                ? new ArrayList<>(0)
-                : POJOHelper.deserialize(impersonatedAccounts, new TypeReference<>() {
-        });
+        return Optional.ofNullable(impersonationAccounts).
+                map(v -> POJOHelper.deserialize(v, new TypeReference<List<ImpersonationAccount>>() {
+        })).orElseGet(() -> new ArrayList<>(0));
     }
 
     @Override
     public void setImpersonationAccounts(final List<ImpersonationAccount> accounts) {
-        this.impersonatedAccounts = POJOHelper.serialize(accounts);
+        impersonationAccounts = POJOHelper.serialize(accounts);
     }
 
     @Override
     public List<WebAuthnDeviceCredential> getWebAuthnDeviceCredentials() {
-        return webAuthnDeviceCredentials == null
-                ? new ArrayList<>(0)
-                : POJOHelper.deserialize(webAuthnDeviceCredentials,
-            new TypeReference<>() {
-            });
+        return Optional.ofNullable(webAuthnDeviceCredentials).
+                map(v -> POJOHelper.deserialize(v, new TypeReference<List<WebAuthnDeviceCredential>>() {
+        })).orElseGet(() -> new ArrayList<>(0));
     }
 
     @Override
     public void setWebAuthnDeviceCredentials(final List<WebAuthnDeviceCredential> credentials) {
-        this.webAuthnDeviceCredentials = POJOHelper.serialize(credentials);
+        webAuthnDeviceCredentials = POJOHelper.serialize(credentials);
     }
 }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java
index e2c722f..89dbdb0 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java
@@ -18,12 +18,10 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity.task;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import javax.persistence.DiscriminatorValue;
 import javax.persistence.Entity;
 import javax.persistence.OneToOne;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
 import javax.validation.constraints.NotNull;
 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
@@ -38,8 +36,7 @@ public class JPASchedTask extends AbstractTask implements SchedTask {
 
     private static final long serialVersionUID = 7596236684832602180L;
 
-    @Temporal(TemporalType.TIMESTAMP)
-    private Date startAt;
+    private OffsetDateTime startAt;
 
     private String cronExpression;
 
@@ -55,20 +52,13 @@ public class JPASchedTask extends AbstractTask implements SchedTask {
     private Boolean active = true;
 
     @Override
-    public Date getStartAt() {
-        if (startAt != null) {
-            return new Date(startAt.getTime());
-        }
-        return null;
+    public OffsetDateTime getStartAt() {
+        return startAt;
     }
 
     @Override
-    public void setStartAt(final Date start) {
-        if (start != null) {
-            this.startAt = new Date(start.getTime());
-        } else {
-            this.startAt = null;
-        }
+    public void setStartAt(final OffsetDateTime startAt) {
+        this.startAt = startAt;
     }
 
     @Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
index 655e64a..3ac88b2 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
@@ -18,9 +18,8 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity.user;
 
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
@@ -40,8 +39,6 @@ import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
 import javax.persistence.Transient;
 import javax.persistence.UniqueConstraint;
 import javax.validation.Valid;
@@ -108,8 +105,7 @@ public class JPAUser
     @Lob
     private String token;
 
-    @Temporal(TemporalType.TIMESTAMP)
-    private Date tokenExpireTime;
+    private OffsetDateTime tokenExpireTime;
 
     @Column(nullable = true)
     @Enumerated(EnumType.STRING)
@@ -137,16 +133,12 @@ public class JPAUser
     /**
      * Last successful login date.
      */
-    @Column(nullable = true)
-    @Temporal(TemporalType.TIMESTAMP)
-    private Date lastLoginDate;
+    private OffsetDateTime lastLoginDate;
 
     /**
      * Change password date.
      */
-    @Column(nullable = true)
-    @Temporal(TemporalType.TIMESTAMP)
-    private Date changePwdDate;
+    private OffsetDateTime changePwdDate;
 
     private Boolean suspended = false;
 
@@ -189,7 +181,7 @@ public class JPAUser
 
     @Transient
     private String clearSecurityAnswer;
-    
+
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "owner")
     @Valid
     private List<JPALinkedAccount> linkedAccounts = new ArrayList<>();
@@ -261,8 +253,8 @@ public class JPAUser
         try {
             this.password = ENCRYPTOR.encode(password, cipherAlgorithm == null
                     ? CipherAlgorithm.valueOf(ApplicationContextProvider.getBeanFactory().getBean(ConfParamOps.class).
-                    get(AuthContextUtils.getDomain(), "password.cipher.algorithm", CipherAlgorithm.AES.name(),
-                            String.class))
+                            get(AuthContextUtils.getDomain(), "password.cipher.algorithm", CipherAlgorithm.AES.name(),
+                                    String.class))
                     : cipherAlgorithm);
             setMustChangePassword(false);
         } catch (Exception e) {
@@ -284,7 +276,7 @@ public class JPAUser
             throw new IllegalArgumentException("Cannot override existing cipher algorithm");
         }
     }
-    
+
     @Override
     public boolean canDecodeSecrets() {
         return this.cipherAlgorithm != null && this.cipherAlgorithm.isInvertible();
@@ -314,10 +306,7 @@ public class JPAUser
     @Override
     public void generateToken(final int tokenLength, final int tokenExpireTime) {
         this.token = SecureRandomUtils.generateRandomPassword(tokenLength);
-
-        Calendar calendar = Calendar.getInstance();
-        calendar.add(Calendar.MINUTE, tokenExpireTime);
-        this.tokenExpireTime = calendar.getTime();
+        this.tokenExpireTime = OffsetDateTime.now().plusMinutes(tokenExpireTime);
     }
 
     @Override
@@ -332,19 +321,22 @@ public class JPAUser
     }
 
     @Override
-    public Date getTokenExpireTime() {
-        return Optional.ofNullable(tokenExpireTime).map(expireTime -> new Date(expireTime.getTime())).orElse(null);
+    public OffsetDateTime getTokenExpireTime() {
+        return tokenExpireTime;
     }
 
     @Override
     public boolean checkToken(final String token) {
-        return Optional.ofNullable(this.token)
-            .map(s -> s.equals(token) && !hasTokenExpired()).orElseGet(() -> token == null);
+        return Optional.ofNullable(this.token).
+                map(s -> s.equals(token) && !hasTokenExpired()).
+                orElseGet(() -> token == null);
     }
 
     @Override
     public boolean hasTokenExpired() {
-        return Optional.ofNullable(tokenExpireTime).filter(expireTime -> expireTime.before(new Date())).isPresent();
+        return Optional.ofNullable(tokenExpireTime).
+                filter(expireTime -> expireTime.isBefore(OffsetDateTime.now())).
+                isPresent();
     }
 
     @Override
@@ -353,14 +345,13 @@ public class JPAUser
     }
 
     @Override
-    public Date getChangePwdDate() {
-        return Optional.ofNullable(changePwdDate).map(pwdDate -> new Date(pwdDate.getTime())).orElse(null);
+    public OffsetDateTime getChangePwdDate() {
+        return changePwdDate;
     }
 
     @Override
-    public void setChangePwdDate(final Date changePwdDate) {
-        this.changePwdDate = Optional.ofNullable(changePwdDate)
-            .map(pwdDate -> new Date(pwdDate.getTime())).orElse(null);
+    public void setChangePwdDate(final OffsetDateTime changePwdDate) {
+        this.changePwdDate = changePwdDate;
     }
 
     @Override
@@ -374,14 +365,13 @@ public class JPAUser
     }
 
     @Override
-    public Date getLastLoginDate() {
-        return Optional.ofNullable(lastLoginDate).map(loginDate -> new Date(loginDate.getTime())).orElse(null);
+    public OffsetDateTime getLastLoginDate() {
+        return lastLoginDate;
     }
 
     @Override
-    public void setLastLoginDate(final Date lastLoginDate) {
-        this.lastLoginDate = Optional.ofNullable(lastLoginDate)
-            .map(loginDate -> new Date(loginDate.getTime())).orElse(null);
+    public void setLastLoginDate(final OffsetDateTime lastLoginDate) {
+        this.lastLoginDate = lastLoginDate;
     }
 
     @Override
@@ -449,8 +439,8 @@ public class JPAUser
         try {
             this.securityAnswer = ENCRYPTOR.encode(securityAnswer, cipherAlgorithm == null
                     ? CipherAlgorithm.valueOf(ApplicationContextProvider.getBeanFactory().getBean(ConfParamOps.class).
-                    get(AuthContextUtils.getDomain(), "password.cipher.algorithm", CipherAlgorithm.AES.name(),
-                            String.class))
+                            get(AuthContextUtils.getDomain(), "password.cipher.algorithm", CipherAlgorithm.AES.name(),
+                                    String.class))
                     : cipherAlgorithm);
         } catch (Exception e) {
             LOG.error("Could not encode security answer", e);
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DelegationValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DelegationValidator.java
index c90eec3..b22c3ae 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DelegationValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DelegationValidator.java
@@ -38,7 +38,7 @@ public class DelegationValidator extends AbstractValidator<DelegationCheck, Dele
             isValid = false;
         }
 
-        if (isValid && delegation.getEnd() != null && !delegation.getEnd().after(delegation.getStart())) {
+        if (isValid && delegation.getEnd() != null && !delegation.getEnd().isAfter(delegation.getStart())) {
             context.buildConstraintViolationWithTemplate(
                     getTemplate(EntityViolationType.Standard, "when end is provided it must to be after start")).
                     addPropertyNode("end").addConstraintViolation();
diff --git a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
index 46827ba..e1778dc 100644
--- a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
+++ b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
@@ -98,41 +98,4 @@ under the License.
       </many-to-one>
     </attributes>
   </entity>
-  
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAPlainAttrUniqueValue">
-    <table>
-      <unique-constraint>
-        <column-name>booleanValue</column-name>
-        <column-name>dateValue</column-name>
-        <column-name>stringValue</column-name>
-        <column-name>doubleValue</column-name>
-        <column-name>longValue</column-name>
-        <column-name>schema_id</column-name>
-      </unique-constraint>
-    </table>
-  </entity>    
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttrUniqueValue">
-    <table>
-      <unique-constraint>
-        <column-name>booleanValue</column-name>
-        <column-name>dateValue</column-name>
-        <column-name>stringValue</column-name>
-        <column-name>doubleValue</column-name>
-        <column-name>longValue</column-name>
-        <column-name>schema_id</column-name>
-      </unique-constraint>
-    </table>
-  </entity>
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGPlainAttrUniqueValue">
-    <table>
-      <unique-constraint>
-        <column-name>booleanValue</column-name>
-        <column-name>dateValue</column-name>
-        <column-name>stringValue</column-name>
-        <column-name>doubleValue</column-name>
-        <column-name>longValue</column-name>
-        <column-name>schema_id</column-name>
-      </unique-constraint>
-    </table>
-  </entity>
 </entity-mappings>
diff --git a/core/persistence-jpa/src/main/resources/oracle_indexes.xml b/core/persistence-jpa/src/main/resources/oracle_indexes.xml
new file mode 100644
index 0000000..6c96039
--- /dev/null
+++ b/core/persistence-jpa/src/main/resources/oracle_indexes.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+  <comment>Additional indexes (in respect to JPA's)</comment>
+
+  <entry key="APlainAttrUniqueValue_U">CREATE UNIQUE INDEX APlainAttrUniqueValue_U on APlainAttrUniqueValue(booleanValue, dateValue, stringValue, doubleValue, longValue, schema_id)</entry>
+  <entry key="UPlainAttrUniqueValue_U">CREATE UNIQUE INDEX UPlainAttrUniqueValue_U on UPlainAttrUniqueValue(booleanValue, dateValue, stringValue, doubleValue, longValue, schema_id)</entry>
+  <entry key="GPlainAttrUniqueValue_U">CREATE UNIQUE INDEX GPlainAttrUniqueValue_U on GPlainAttrUniqueValue(booleanValue, dateValue, stringValue, doubleValue, longValue, schema_id)</entry>
+
+  <entry key="UDynGroupMembers_any_id">CREATE INDEX UDynGroupMembers_any_id ON UDynGroupMembers(any_id)</entry>
+  <entry key="UDynGroupMembers_group_id">CREATE INDEX UDynGroupMembers_group_id ON UDynGroupMembers(group_id)</entry>
+  <entry key="ADynGroupMembers_any_id">CREATE INDEX ADynGroupMembers_any_id ON ADynGroupMembers(any_id)</entry>
+  <entry key="ADynGroupMembers_group_id">CREATE INDEX ADynGroupMembers_group_id ON ADynGroupMembers(group_id)</entry>
+
+  <entry key="DynRoleMembers_any_id">CREATE INDEX DynRoleMembers_any_id ON DynRoleMembers(any_id)</entry>
+  <entry key="DynRoleMembers_role_id">CREATE INDEX DynRoleMembers_role_id ON DynRoleMembers(role_id)</entry>
+
+  <entry key="DynRealmMembers_any_id">CREATE INDEX DynRealmMembers_any_id ON DynRealmMembers(any_id)</entry>
+  <entry key="DynRealmMembers_realm_id">CREATE INDEX DynRealmMembers_dynRealm_id ON DynRealmMembers(dynRealm_id)</entry>
+
+  <entry key="UPlainAttrValue_stringvalueIndex">CREATE INDEX UAttrValue_stringvalueIndex ON UPlainAttrValue(stringvalue)</entry>
+  <entry key="UPlainAttrValue_datevalueIndex">CREATE INDEX UAttrValue_datevalueIndex ON UPlainAttrValue(datevalue)</entry>
+  <entry key="UPlainAttrValue_longvalueIndex">CREATE INDEX UAttrValue_longvalueIndex ON UPlainAttrValue(longvalue)</entry>
+  <entry key="UPlainAttrValue_doublevalueIndex">CREATE INDEX UAttrValue_doublevalueIndex ON UPlainAttrValue(doublevalue)</entry>
+  <entry key="UPlainAttrValue_booleanvalueIndex">CREATE INDEX UAttrValue_booleanvalueIndex ON UPlainAttrValue(booleanvalue)</entry>
+
+  <entry key="APlainAttrValue_stringvalueIndex">CREATE INDEX AAttrValue_stringvalueIndex ON APlainAttrValue(stringvalue)</entry>
+  <entry key="APlainAttrValue_datevalueIndex">CREATE INDEX AAttrValue_datevalueIndex ON APlainAttrValue(datevalue)</entry>
+  <entry key="APlainAttrValue_longvalueIndex">CREATE INDEX AAttrValue_longvalueIndex ON APlainAttrValue(longvalue)</entry>
+  <entry key="APlainAttrValue_doublevalueIndex">CREATE INDEX AAttrValue_doublevalueIndex ON APlainAttrValue(doublevalue)</entry>
+  <entry key="APlainAttrValue_booleanvalueIndex">CREATE INDEX AAttrValue_booleanvalueIndex ON APlainAttrValue(booleanvalue)</entry>
+
+  <entry key="GPlainAttrValue_stringvalueIndex">CREATE INDEX GAttrValue_stringvalueIndex ON GPlainAttrValue(stringvalue)</entry>
+  <entry key="GPlainAttrValue_datevalueIndex">CREATE INDEX GAttrValue_datevalueIndex ON GPlainAttrValue(datevalue)</entry>
+  <entry key="GPlainAttrValue_longvalueIndex">CREATE INDEX GAttrValue_longvalueIndex ON GPlainAttrValue(longvalue)</entry>
+  <entry key="GPlainAttrValue_doublevalueIndex">CREATE INDEX GAttrValue_doublevalueIndex ON GPlainAttrValue(doublevalue)</entry>
+  <entry key="GPlainAttrValue_booleanvalueIndex">CREATE INDEX GAttrValue_booleanvalueIndex ON GPlainAttrValue(booleanvalue)</entry>
+
+  <entry key="UMembership_GroupIndex">CREATE INDEX UMembership_GroupIndex ON UMembership(group_id)</entry>
+  <entry key="UMembership_UserIndex">CREATE INDEX UMembership_UserIndex ON UMembership(user_id)</entry>
+  <entry key="AMembership_GroupIndex">CREATE INDEX AMembership_GroupIndex ON AMembership(group_id)</entry>
+  <entry key="AMembership_AnyObjectIndex">CREATE INDEX AMembership_AnyObjectIndex ON AMembership(anyObject_id)</entry>
+
+  <entry key="URelationship_RightIndex">CREATE INDEX URelationship_RightIndex ON URelationship(anyObject_id)</entry>
+  <entry key="URelationship_LeftIndex">CREATE INDEX URelationship_LeftIndex ON URelationship(user_id)</entry>
+  <entry key="ARelationship_RightIndex">CREATE INDEX ARelationship_RightIndex ON ARelationship(right_anyObject_id)</entry>
+  <entry key="ARelationship_AnyObjectIndex">CREATE INDEX ARelationship_AnyObjectIndex ON ARelationship(left_anyObject_id)</entry>
+
+  <entry key="UPlainAttrValue_attrIndex">CREATE INDEX UPlainAttrValue_attrIndex on UPlainAttrValue(attribute_id)</entry>
+  <entry key="UPAttrUniqueValue_attrIndex">CREATE INDEX UPAttrUniqueValue_attrIndex on UPlainAttrUniqueValue(attribute_id)</entry>
+
+  <entry key="GPlainAttrValue_attrIndex">CREATE INDEX GPlainAttrValue_attrIndex on GPlainAttrValue(attribute_id)</entry>
+  <entry key="GPAttrUniquesValue_attrIndex">CREATE INDEX GPAttrUniqueValue_attrIndex on GPlainAttrUniqueValue(attribute_id)</entry>
+
+  <entry key="APlainAttrValue_attrIndex">CREATE INDEX APlainAttrValue_attrIndex on APlainAttrValue(attribute_id)</entry>
+  <entry key="APAttrUniqueValue_attrIndex">CREATE INDEX APAttrUniqueValue_attrIndex on APlainAttrUniqueValue(attribute_id)</entry>
+
+  <entry key="UPlainAttr_owner_Index">CREATE INDEX UPlainAttr_owner_Index on UPlainAttr(owner_id)</entry>
+  <entry key="UPlainAttr_schema_Index">CREATE INDEX UPlainAttr_schema_Index on UPlainAttr(schema_id)</entry>
+  <entry key="UPlainAttr_membership_Index">CREATE INDEX UPlainAttr_membership_Index on UPlainAttr(membership_id)</entry>
+
+  <entry key="GPlainAttr_owner_Index">CREATE INDEX GPlainAttr_owner_Index on GPlainAttr(owner_id)</entry>
+  <entry key="GPlainAttr_schema_Index">CREATE INDEX GPlainAttr_schema_Index on GPlainAttr(schema_id)</entry>
+
+  <entry key="APlainAttr_owner_Index">CREATE INDEX APlainAttr_owner_Index on APlainAttr(owner_id)</entry>
+  <entry key="APlainAttr_schema_Index">CREATE INDEX APlainAttr_schema_Index on APlainAttr(schema_id)</entry>
+  <entry key="APlainAttr_membership_Index">CREATE INDEX APlainAttr_membership_Index on APlainAttr(membership_id)</entry>
+
+  <entry key="Task_executedIndex">CREATE INDEX Task_executedIndex ON Task(executed)</entry>
+  <entry key="TaskExec_TaskIdIndex">CREATE INDEX TaskExec_TaskIdIndex ON TaskExec(task_id)</entry>
+  <entry key="ATPullTask_PullTaskIndex">CREATE INDEX ATPullTask_PullTaskIndex ON AnyTemplatePullTask(pullTask_id)</entry>
+  <entry key="NT_recipientsIndex">CREATE INDEX NT_recipientsIndex ON NotificationTask_recipients(notificationTask_id)</entry>
+</properties>
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
index 963177c..11df808 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
@@ -32,7 +32,6 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
-import org.apache.commons.lang3.time.DateUtils;
 import java.util.stream.Stream;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -64,6 +63,7 @@ import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
+import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
 import org.junit.jupiter.api.BeforeEach;
 import org.apache.syncope.core.provisioning.api.utils.RealmUtils;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
@@ -107,7 +107,7 @@ public class AnySearchTest extends AbstractTest {
         User rossini = userDAO.findByUsername("rossini");
 
         UPlainAttr loginDate = rossini.getPlainAttr("loginDate").get();
-        loginDate.getValues().get(0).setDateValue(DateUtils.parseDate(LOGIN_DATE_VALUE, "yyyy-MM-dd"));
+        loginDate.getValues().get(0).setDateValue(FormatUtils.parseDate(LOGIN_DATE_VALUE, "yyyy-MM-dd"));
 
         userDAO.save(rossini);
     }
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AuthProfileTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AuthProfileTest.java
index 7d27b92..8dd8319 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AuthProfileTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AuthProfileTest.java
@@ -22,7 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
@@ -150,6 +150,7 @@ public class AuthProfileTest extends AbstractTest {
 
         String secret = SecureRandomUtils.generateRandomUUID().toString();
         List<GoogleMfaAuthAccount> googleMfaAuthAccounts = authProfile.getGoogleMfaAuthAccounts();
+        assertFalse(googleMfaAuthAccounts.isEmpty());
         GoogleMfaAuthAccount googleMfaAuthAccount = googleMfaAuthAccounts.get(0);
         googleMfaAuthAccount.setSecretKey(secret);
 
@@ -183,10 +184,7 @@ public class AuthProfileTest extends AbstractTest {
     private AuthProfile createAuthProfileWithToken(final String owner, final Integer otp) {
         AuthProfile profile = entityFactory.newEntity(AuthProfile.class);
         profile.setOwner(owner);
-        GoogleMfaAuthToken token = new GoogleMfaAuthToken.Builder()
-                .issueDate(new Date())
-                .token(otp)
-                .build();
+        GoogleMfaAuthToken token = new GoogleMfaAuthToken.Builder().issueDate(OffsetDateTime.now()).token(otp).build();
         profile.setGoogleMfaAuthTokens(List.of(token));
         return authProfileDAO.save(profile);
     }
@@ -194,7 +192,7 @@ public class AuthProfileTest extends AbstractTest {
     private AuthProfile createAuthProfileWithU2FDevice(final String owner, final String record) {
         AuthProfile profile = entityFactory.newEntity(AuthProfile.class);
         profile.setOwner(owner);
-        U2FDevice device = new U2FDevice.Builder().issueDate(new Date()).record(record).build();
+        U2FDevice device = new U2FDevice.Builder().issueDate(OffsetDateTime.now()).record(record).build();
         profile.setU2FRegisteredDevices(List.of(device));
         return authProfileDAO.save(profile);
     }
@@ -213,7 +211,7 @@ public class AuthProfileTest extends AbstractTest {
         AuthProfile profile = entityFactory.newEntity(AuthProfile.class);
         profile.setOwner(owner);
         GoogleMfaAuthAccount account = new GoogleMfaAuthAccount.Builder()
-                .registrationDate(new Date())
+                .registrationDate(OffsetDateTime.now())
                 .scratchCodes(List.of(1, 2, 3, 4, 5))
                 .secretKey(SecureRandomUtils.generateRandomUUID().toString())
                 .validationCode(123456)
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RemediationTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RemediationTest.java
index 4dfabbd..19e290f 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RemediationTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RemediationTest.java
@@ -24,7 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import java.util.Set;
 import java.util.UUID;
@@ -64,7 +64,7 @@ public class RemediationTest extends AbstractTest {
         remediation.setAnyType(anyTypeDAO.find("PRINTER"));
         remediation.setOperation(ResourceOperation.CREATE);
         remediation.setError("Error");
-        remediation.setInstant(new Date());
+        remediation.setInstant(OffsetDateTime.now());
         remediation.setRemoteName("remote");
         remediation.setPullTask(taskDAO.find("38abbf9e-a1a3-40a1-a15f-7d0ac02f47f1"));
 
@@ -85,7 +85,7 @@ public class RemediationTest extends AbstractTest {
         remediation.setAnyType(anyTypeDAO.find("PRINTER"));
         remediation.setOperation(ResourceOperation.CREATE);
         remediation.setError("Error");
-        remediation.setInstant(new Date());
+        remediation.setInstant(OffsetDateTime.now());
         remediation.setRemoteName("remote");
         remediation.setPullTask(taskDAO.find("38abbf9e-a1a3-40a1-a15f-7d0ac02f47f1"));
         remediation.setPayload(UUID.randomUUID().toString());
@@ -107,7 +107,7 @@ public class RemediationTest extends AbstractTest {
         remediation.setAnyType(anyTypeDAO.find("PRINTER"));
         remediation.setOperation(ResourceOperation.CREATE);
         remediation.setError("Error");
-        remediation.setInstant(new Date());
+        remediation.setInstant(OffsetDateTime.now());
         remediation.setRemoteName("remote");
         remediation.setPullTask(taskDAO.find("38abbf9e-a1a3-40a1-a15f-7d0ac02f47f1"));
         remediation.setPayload(UUID.randomUUID().toString());
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskExecTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskExecTest.java
index 7391026..5bdbc3b 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskExecTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskExecTest.java
@@ -21,8 +21,7 @@ package org.apache.syncope.core.persistence.jpa.inner;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
-import java.util.Calendar;
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import org.apache.syncope.common.lib.types.ExecStatus;
 import org.apache.syncope.core.persistence.api.dao.TaskDAO;
@@ -30,6 +29,7 @@ import org.apache.syncope.core.persistence.api.dao.TaskExecDAO;
 import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
 import org.apache.syncope.core.persistence.api.entity.task.TaskExec;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
+import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
@@ -48,11 +48,9 @@ public class TaskExecTest extends AbstractTest {
         PropagationTask task = taskDAO.find("1e697572-b896-484c-ae7f-0c8f63fcbc6c");
         assertNotNull(task);
 
-        Calendar calendar = Calendar.getInstance();
-        calendar.clear();
-        calendar.set(2015, 11, 18, 0, 0, 0);
+        OffsetDateTime startedBefore = OffsetDateTime.of(2015, 12, 18, 0, 0, 0, 0, FormatUtils.DEFAULT_OFFSET);
 
-        List<TaskExec> execs = taskExecDAO.findAll(task, calendar.getTime(), null, null, null);
+        List<TaskExec> execs = taskExecDAO.findAll(task, startedBefore, null, null, null);
         assertNotNull(execs);
         assertEquals(1, execs.size());
     }
@@ -76,8 +74,8 @@ public class TaskExecTest extends AbstractTest {
         faultyMessage = faultyMessage.replace('a', '\0');
 
         TaskExec exec = entityFactory.newEntity(TaskExec.class);
-        exec.setStart(new Date());
-        exec.setEnd(new Date());
+        exec.setStart(OffsetDateTime.now());
+        exec.setEnd(OffsetDateTime.now());
         exec.setStatus(ExecStatus.SUCCESS.name());
         exec.setMessage(faultyMessage);
         exec.setExecutor("admin");
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java
index fa91f98..a7f5684 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java
@@ -26,7 +26,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
+import java.time.temporal.ChronoUnit;
 import java.util.List;
 import java.util.Optional;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
@@ -207,7 +208,7 @@ public class UserTest extends AbstractTest {
         user.setUsername("username");
         user.setRealm(realmDAO.findByFullPath("/even/two"));
         user.setCreator("admin");
-        user.setCreationDate(new Date());
+        user.setCreationDate(OffsetDateTime.now());
         user.setCipherAlgorithm(CipherAlgorithm.SHA256);
         user.setPassword("pass");
 
@@ -225,7 +226,7 @@ public class UserTest extends AbstractTest {
         user.setUsername("username!");
         user.setRealm(realmDAO.findByFullPath("/even/two"));
         user.setCreator("admin");
-        user.setCreationDate(new Date());
+        user.setCreationDate(OffsetDateTime.now());
         user.setCipherAlgorithm(CipherAlgorithm.SHA256);
         user.setPassword("password123");
 
@@ -243,7 +244,7 @@ public class UserTest extends AbstractTest {
         user.setUsername("username");
         user.setRealm(realmDAO.findByFullPath("/even/two"));
         user.setCreator("admin");
-        user.setCreationDate(new Date());
+        user.setCreationDate(OffsetDateTime.now());
         user.setCipherAlgorithm(CipherAlgorithm.SHA256);
         user.setPassword("password123");
 
@@ -251,7 +252,8 @@ public class UserTest extends AbstractTest {
         assertNotNull(actual);
         assertEquals(1, actual.getPasswordHistory().size());
         assertNotNull(userDAO.findLastChange(actual.getKey()));
-        assertEquals(actual.getLastChangeDate(), userDAO.findLastChange(actual.getKey()));
+        assertTrue(actual.getLastChangeDate().truncatedTo(ChronoUnit.SECONDS).
+                isEqual(userDAO.findLastChange(actual.getKey()).truncatedTo(ChronoUnit.SECONDS)));
     }
 
     @Test
@@ -270,7 +272,7 @@ public class UserTest extends AbstractTest {
         user.setUsername("username");
         user.setRealm(realmDAO.findByFullPath("/even/two"));
         user.setCreator("admin");
-        user.setCreationDate(new Date());
+        user.setCreationDate(OffsetDateTime.now());
 
         user.setCipherAlgorithm(CipherAlgorithm.AES);
         user.setPassword("password123");
@@ -332,7 +334,7 @@ public class UserTest extends AbstractTest {
         user.setUsername("username");
         user.setRealm(realmDAO.findByFullPath("/even/two"));
         user.setCreator("admin");
-        user.setCreationDate(new Date());
+        user.setCreationDate(OffsetDateTime.now());
         user.setCipherAlgorithm(CipherAlgorithm.SSHA256);
         user.setPassword("password123");
         user.setSecurityQuestion(securityQuestionDAO.find("887028ea-66fc-41e7-b397-620d7ea6dfbb"));
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AccessTokenTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AccessTokenTest.java
index f36906f..5277409 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AccessTokenTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AccessTokenTest.java
@@ -22,7 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.UUID;
 import org.apache.syncope.core.persistence.api.dao.AccessTokenDAO;
 import org.apache.syncope.core.persistence.api.entity.AccessToken;
@@ -42,7 +42,7 @@ public class AccessTokenTest extends AbstractTest {
         AccessToken accessToken = entityFactory.newEntity(AccessToken.class);
         accessToken.setKey(UUID.randomUUID().toString());
         accessToken.setBody("pointless body");
-        accessToken.setExpirationTime(new Date());
+        accessToken.setExpirationTime(OffsetDateTime.now());
         accessToken.setOwner("bellini");
 
         accessToken = accessTokenDAO.save(accessToken);
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ReportTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ReportTest.java
index c3bbd24..972ae5b 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ReportTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ReportTest.java
@@ -24,7 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import javax.persistence.EntityExistsException;
 import org.apache.syncope.common.lib.types.ReportExecStatus;
 import org.apache.syncope.core.persistence.api.dao.ReportDAO;
@@ -85,8 +85,8 @@ public class ReportTest extends AbstractTest {
 
         ReportExec reportExec = entityFactory.newEntity(ReportExec.class);
         reportExec.setReport(report);
-        reportExec.setStart(new Date());
-        reportExec.setEnd(new Date());
+        reportExec.setStart(OffsetDateTime.now());
+        reportExec.setEnd(OffsetDateTime.now());
         reportExec.setStatus(ReportExecStatus.SUCCESS);
         reportExec.setExecutor("admin");
 
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java
index 768e7e9..7825c19 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java
@@ -23,10 +23,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -220,7 +220,7 @@ public class RoleTest extends AbstractTest {
         Delegation delegation = entityFactory.newEntity(Delegation.class);
         delegation.setDelegating(bellini);
         delegation.setDelegated(rossini);
-        delegation.setStart(new Date());
+        delegation.setStart(OffsetDateTime.now());
         delegation.add(reviewer);
         delegation = delegationDAO.save(delegation);
 
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/TaskTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/TaskTest.java
index 1516f30..b908a83 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/TaskTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/TaskTest.java
@@ -24,8 +24,8 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -150,7 +150,7 @@ public class TaskTest extends AbstractTest {
         TaskExec execution = entityFactory.newEntity(TaskExec.class);
         execution.setTask(task);
         execution.setStatus(ExecStatus.CREATED.name());
-        execution.setStart(new Date());
+        execution.setStart(OffsetDateTime.now());
         execution.setExecutor("admin");
         task.add(execution);
 
@@ -173,7 +173,7 @@ public class TaskTest extends AbstractTest {
         TaskExec execution = entityFactory.newEntity(TaskExec.class);
         execution.setStatus("Text-free status");
         execution.setTask(task);
-        execution.setStart(new Date());
+        execution.setStart(OffsetDateTime.now());
         execution.setMessage("A message");
         execution.setExecutor("admin");
         task.add(execution);
@@ -197,7 +197,7 @@ public class TaskTest extends AbstractTest {
         TaskExec execution = entityFactory.newEntity(TaskExec.class);
         execution.setStatus("Text-free status");
         execution.setTask(task);
-        execution.setStart(new Date());
+        execution.setStart(OffsetDateTime.now());
         execution.setMessage("A message");
         execution.setExecutor("admin");
         task.add(execution);
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/UserTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/UserTest.java
index c7721f9..2e9762e 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/UserTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/UserTest.java
@@ -25,7 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import java.util.Objects;
 import java.util.UUID;
@@ -340,7 +340,7 @@ public class UserTest extends AbstractTest {
         Delegation delegation = entityFactory.newEntity(Delegation.class);
         delegation.setDelegating(bellini);
         delegation.setDelegated(rossini);
-        delegation.setStart(new Date());
+        delegation.setStart(OffsetDateTime.now());
         delegation.add(reviewer);
         delegation = delegationDAO.save(delegation);
 
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index f6e453a..d4684d3 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -1118,7 +1118,7 @@ under the License.
   <Task DTYPE="PropagationTask" id="1e697572-b896-484c-ae7f-0c8f63fcbc6c" operation="UPDATE"
         objectClassName="__ACCOUNT__" resource_id="ws-target-resource-2" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
         attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"fullname","value":["fullname"]},{"name":"type","value":["type"]}]'/>
-  <TaskExec id="e58ca1c7-178a-4012-8a71-8aa14eaf0655" task_id="1e697572-b896-484c-ae7f-0c8f63fcbc6c" startDate="2015-12-17 09:40:00.506" endDate="2015-12-17 09:42:00.506" status="SUCCESS"/>
+  <TaskExec id="e58ca1c7-178a-4012-8a71-8aa14eaf0655" task_id="1e697572-b896-484c-ae7f-0c8f63fcbc6c" startDate="2015-12-17 09:40:00" endDate="2015-12-17 09:42:00" status="SUCCESS"/>
   <Task DTYPE="PropagationTask" id="b8870cfb-3c1e-4fc4-abcb-2559826232e6" operation="CREATE"
         objectClassName="__ACCOUNT__" resource_id="ws-target-resource-2" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
         attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"fullname","value":["fullname"]},{"name":"type","value":["type"]}]'/>
@@ -1129,7 +1129,7 @@ under the License.
   <Task DTYPE="PropagationTask" id="025c956d-ea88-4bd7-9e44-2f35e0aa7055" operation="UPDATE"
         objectClassName="__ACCOUNT__" resource_id="ws-target-resource-1" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
         attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"fullname","value":["fullname"]},{"name":"type","value":["type"]}]'/>
-  <TaskExec id="c3290f8b-caf9-4a85-84fb-fb619b65cd49" task_id="025c956d-ea88-4bd7-9e44-2f35e0aa7055" startDate="2015-12-17 09:40:00.506" endDate="2015-12-17 09:42:00.506" status="SUCCESS"/>
+  <TaskExec id="c3290f8b-caf9-4a85-84fb-fb619b65cd49" task_id="025c956d-ea88-4bd7-9e44-2f35e0aa7055" startDate="2015-12-17 09:40:00" endDate="2015-12-17 09:42:00" status="SUCCESS"/>
   <Task DTYPE="PullTask" remediation="0" id="c41b9b71-9bfa-4f90-89f2-84787def4c5c" name="CSV (update matching; assign unmatching)" resource_id="resource-csv"
         destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
         pullMode="INCREMENTAL" unmatchingRule="ASSIGN" matchingRule="UPDATE" active="1"
@@ -1151,7 +1151,7 @@ under the License.
   <Task DTYPE="PropagationTask" id="d6c2d6d3-6329-44c1-9187-f1469ead1cfa" operation="UPDATE"
         objectClassName="__ACCOUNT__" resource_id="ws-target-resource-nopropagation" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
         attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"fullname","value":["fullname"]},{"name":"type","value":["type"]}]'/>
-  <TaskExec id="d789462f-e395-424f-bd8e-0db44a93222f" task_id="d6c2d6d3-6329-44c1-9187-f1469ead1cfa" startDate="2015-12-17 09:40:00.506" endDate="2015-12-17 09:42:00.506" status="SUCCESS"/>
+  <TaskExec id="d789462f-e395-424f-bd8e-0db44a93222f" task_id="d6c2d6d3-6329-44c1-9187-f1469ead1cfa" startDate="2015-12-17 09:40:00" endDate="2015-12-17 09:42:00" status="SUCCESS"/>
   <Task DTYPE="PullTask" remediation="0" id="83f7e85d-9774-43fe-adba-ccd856312994" name="TestDB Task" resource_id="resource-testdb"
         destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="1" performUpdate="1" performDelete="0" syncStatus="1" pullMode="FULL_RECONCILIATION"
         unmatchingRule="PROVISION" matchingRule="UPDATE" active="1" jobDelegate_id="PullJobDelegate"/>
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AccessTokenDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AccessTokenDataBinder.java
index d50fc22..a487085 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AccessTokenDataBinder.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AccessTokenDataBinder.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.provisioning.api.data;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.Map;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.to.AccessTokenTO;
@@ -26,12 +26,13 @@ import org.apache.syncope.core.persistence.api.entity.AccessToken;
 
 public interface AccessTokenDataBinder {
 
-    Pair<String, Date> generateJWT(String tokenId, String subject, long duration, Map<String, Object> claims);
+    Pair<String, OffsetDateTime> generateJWT(
+            String tokenId, String subject, long duration, Map<String, Object> claims);
 
-    Pair<String, Date> create(String subject, Map<String, Object> claims, byte[] authorities, boolean replace);
+    Pair<String, OffsetDateTime> create(
+            String subject, Map<String, Object> claims, byte[] authorities, boolean replace);
 
-    Pair<String, Date> update(AccessToken accessToken, byte[] authorities);
+    Pair<String, OffsetDateTime> update(AccessToken accessToken, byte[] authorities);
 
     AccessTokenTO getAccessTokenTO(AccessToken accessToken);
-
 }
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlUtils.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlUtils.java
index 5125963..1945dd8 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlUtils.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlUtils.java
@@ -22,9 +22,9 @@ import java.beans.IntrospectionException;
 import java.beans.Introspector;
 import java.beans.PropertyDescriptor;
 import java.lang.reflect.Field;
+import java.time.temporal.TemporalAccessor;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -174,8 +174,8 @@ public final class JexlUtils {
                 if (fieldValue == null) {
                     fieldValue = StringUtils.EMPTY;
                 } else {
-                    fieldValue = fieldType.equals(Date.class)
-                            ? FormatUtils.format((Date) fieldValue, false)
+                    fieldValue = TemporalAccessor.class.isAssignableFrom(fieldType)
+                            ? FormatUtils.format((TemporalAccessor) fieldValue)
                             : fieldValue;
                 }
 
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/SandboxUberspect.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/SandboxUberspect.java
index 3675fc8..26490fa 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/SandboxUberspect.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/SandboxUberspect.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.provisioning.api.jexl;
 
 import java.time.Instant;
+import java.time.temporal.TemporalAccessor;
 import java.util.Collection;
 import java.util.Date;
 import java.util.List;
@@ -76,7 +77,7 @@ class SandboxUberspect extends Uberspect {
             return super.getMethod(obj, method, args);
         } else if (obj instanceof String) {
             return super.getMethod(obj, method, args);
-        } else if (obj instanceof Date || obj instanceof Instant) {
+        } else if (obj instanceof Date || obj instanceof Instant || obj instanceof TemporalAccessor) {
             return super.getMethod(obj, method, args);
         } else if (obj instanceof Map && MAP_METHODS.contains(method)) {
             return super.getMethod(obj, method, args);
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobManager.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobManager.java
index 1402142..e0182a4 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobManager.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobManager.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.provisioning.api.job;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.Map;
 import org.apache.syncope.core.persistence.api.entity.Report;
 import org.apache.syncope.core.persistence.api.entity.task.SchedTask;
@@ -35,16 +35,17 @@ public interface JobManager {
     String REPORT_KEY = "report";
 
     String DOMAIN_KEY = "domain";
+
     String EXECUTOR_KEY = "executor";
 
     JobKey NOTIFICATION_JOB = new JobKey("notificationJob", Scheduler.DEFAULT_GROUP);
 
     boolean isRunning(JobKey jobKey) throws SchedulerException;
 
-    Map<String, Object> register(SchedTask task, Date startAt, long interruptMaxRetries, String executor)
+    Map<String, Object> register(SchedTask task, OffsetDateTime startAt, long interruptMaxRetries, String executor)
             throws SchedulerException;
 
-    void register(Report report, Date startAt, long interruptMaxRetries, String executor)
+    void register(Report report, OffsetDateTime startAt, long interruptMaxRetries, String executor)
             throws SchedulerException;
 
     void unregister(Task task);
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/serialization/POJOHelper.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/serialization/POJOHelper.java
index af99906..532797c 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/serialization/POJOHelper.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/serialization/POJOHelper.java
@@ -20,8 +20,10 @@ package org.apache.syncope.core.provisioning.api.serialization;
 
 import com.fasterxml.jackson.core.Version;
 import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
 import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
 import org.identityconnectors.common.security.GuardedString;
 import org.identityconnectors.framework.common.objects.Attribute;
@@ -36,7 +38,7 @@ public final class POJOHelper {
 
     private static final Logger LOG = LoggerFactory.getLogger(POJOHelper.class);
 
-    private static final ObjectMapper MAPPER;
+    private static final JsonMapper MAPPER;
 
     static {
         SimpleModule pojoModule = new SimpleModule("POJOModule", new Version(1, 0, 0, null, null, null));
@@ -47,9 +49,12 @@ public final class POJOHelper {
         pojoModule.addDeserializer(Attribute.class, new AttributeDeserializer());
         pojoModule.addDeserializer(SyncToken.class, new SyncTokenDeserializer());
 
-        MAPPER = new ObjectMapper();
-        MAPPER.registerModule(pojoModule);
-        MAPPER.registerModule(new AfterburnerModule());
+        MAPPER = JsonMapper.builder().
+                addModule(pojoModule).
+                addModule(new JavaTimeModule()).
+                addModule(new AfterburnerModule()).
+                disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS).
+                build();
     }
 
     public static String serialize(final Object object) {
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/utils/FormatUtils.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/utils/FormatUtils.java
index 5210084..ffb14a9 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/utils/FormatUtils.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/utils/FormatUtils.java
@@ -21,94 +21,123 @@ package org.apache.syncope.core.provisioning.api.utils;
 import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
 import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.temporal.ChronoUnit;
+import java.time.temporal.TemporalAccessor;
+import java.util.Arrays;
 import java.util.Locale;
-import org.apache.commons.lang3.time.DateUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
 
 /**
- * Utility class for parsing / formatting date and numbers.
+ * Utility class for parsing / formatting dates and numbers.
  */
 public final class FormatUtils {
 
-    private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT = ThreadLocal.withInitial(SimpleDateFormat::new);
+    private static final String NO_CONVERSION_PATTERN = "#,##0.###";
 
     private static final ThreadLocal<DecimalFormat> DECIMAL_FORMAT = ThreadLocal.withInitial(() -> {
-        DecimalFormat df = new DecimalFormat();
+        DecimalFormat df = new DecimalFormat(NO_CONVERSION_PATTERN);
         df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH));
         return df;
     });
 
-    public static String format(final Date date) {
-        return format(date, true);
-    }
+    public static final ZoneOffset DEFAULT_OFFSET = OffsetDateTime.now().getOffset();
 
-    public static String format(final Date date, final boolean lenient) {
-        return format(date, lenient, null);
+    public static String format(final TemporalAccessor temporal) {
+        return OffsetDateTime.from(temporal).
+                truncatedTo(ChronoUnit.SECONDS).
+                format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
     }
 
-    public static String format(final Date date, final boolean lenient, final String conversionPattern) {
-        SimpleDateFormat sdf = DATE_FORMAT.get();
-
-        if (conversionPattern == null) {
-            sdf.applyPattern(SyncopeConstants.DEFAULT_DATE_PATTERN);
-        } else {
-            sdf.applyPattern(conversionPattern);
-        }
-
-        sdf.setLenient(lenient);
-
-        return sdf.format(date);
+    public static String format(final TemporalAccessor temporal, final String conversionPattern) {
+        return OffsetDateTime.from(temporal).format(DateTimeFormatter.ofPattern(conversionPattern));
     }
 
     public static String format(final long number) {
-        return format(number, null);
+        return format(number, NO_CONVERSION_PATTERN);
     }
 
     public static String format(final long number, final String conversionPattern) {
         DecimalFormat df = DECIMAL_FORMAT.get();
 
         String previous = df.toPattern();
-        if (conversionPattern != null) {
+        if (!previous.equals(conversionPattern)) {
             df.applyPattern(conversionPattern);
         }
 
         String formatted = df.format(number);
 
-        df.applyPattern(previous);
+        if (!previous.equals(conversionPattern)) {
+            df.applyPattern(previous);
+        }
 
         return formatted;
     }
 
     public static String format(final double number) {
-        return format(number, null);
+        return format(number, NO_CONVERSION_PATTERN);
     }
 
     public static String format(final double number, final String conversionPattern) {
         DecimalFormat df = DECIMAL_FORMAT.get();
 
         String previous = df.toPattern();
-        if (conversionPattern != null) {
+        if (!previous.equals(conversionPattern)) {
             df.applyPattern(conversionPattern);
         }
 
         String formatted = df.format(number);
 
-        df.applyPattern(previous);
+        if (!previous.equals(conversionPattern)) {
+            df.applyPattern(previous);
+        }
 
         return formatted;
     }
 
-    public static Date parseDate(final String source) throws ParseException {
-        return DateUtils.parseDate(source, SyncopeConstants.DATE_PATTERNS);
+    public static OffsetDateTime parseDate(final String source)
+            throws DateTimeParseException {
+
+        for (String pattern : SyncopeConstants.DATE_PATTERNS) {
+            try {
+                return parseDate(source, pattern);
+            } catch (DateTimeParseException e) {
+                // ignore
+            }
+        }
+
+        throw new DateTimeParseException(
+                "Could not parse with any of " + Arrays.asList(SyncopeConstants.DATE_PATTERNS), source, 0);
     }
 
-    public static Date parseDate(final String source, final String conversionPattern) throws ParseException {
-        SimpleDateFormat sdf = DATE_FORMAT.get();
-        sdf.applyPattern(conversionPattern);
-        sdf.setLenient(false);
-        return sdf.parse(source);
+    public static OffsetDateTime parseDate(final String source, final String conversionPattern)
+            throws DateTimeParseException {
+
+        DateTimeParseException dtpe;
+
+        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(conversionPattern);
+        try {
+            if (StringUtils.containsIgnoreCase(conversionPattern, "Z")) {
+                return OffsetDateTime.parse(source, dtf);
+            } else {
+                return LocalDateTime.parse(source, dtf).atZone(DEFAULT_OFFSET).toOffsetDateTime();
+            }
+        } catch (DateTimeParseException e) {
+            dtpe = e;
+        }
+        try {
+            return LocalDate.parse(source, dtf).atStartOfDay(DEFAULT_OFFSET).toOffsetDateTime();
+        } catch (DateTimeParseException e) {
+            dtpe = e;
+        }
+
+        throw dtpe;
     }
 
     public static Number parseNumber(final String source, final String conversionPattern) throws ParseException {
@@ -118,7 +147,6 @@ public final class FormatUtils {
     }
 
     public static void clear() {
-        DATE_FORMAT.remove();
         DECIMAL_FORMAT.remove();
     }
 
diff --git a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/utils/FormatUtilsTest.java b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/utils/FormatUtilsTest.java
index 61c2657..d869d3f 100644
--- a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/utils/FormatUtilsTest.java
+++ b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/utils/FormatUtilsTest.java
@@ -20,44 +20,44 @@ package org.apache.syncope.core.provisioning.api.utils;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
+import java.security.SecureRandom;
 import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
 import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
+import java.time.LocalDate;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
 import java.util.Locale;
-import org.apache.commons.lang3.time.DateUtils;
-import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.core.provisioning.api.AbstractTest;
 import org.junit.jupiter.api.Test;
 
 public class FormatUtilsTest extends AbstractTest {
 
-    private final Calendar calendar = Calendar.getInstance();
+    private static final SecureRandom RANDOM = new SecureRandom();
 
-    private final Date date = calendar.getTime();
-
-    private String conversionPattern;
+    private static final OffsetDateTime DATE = OffsetDateTime.now();
 
     @Test
     public void formatDate() {
-        assertEquals(new SimpleDateFormat(SyncopeConstants.DEFAULT_DATE_PATTERN).format(date),
-                FormatUtils.format(date));
+        assertEquals(
+                DATE.truncatedTo(ChronoUnit.SECONDS).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME),
+                FormatUtils.format(DATE));
 
-        conversionPattern = "dd/MM/yyyy";
-        assertEquals(new SimpleDateFormat(conversionPattern).format(date),
-                FormatUtils.format(date, false, conversionPattern));
+        String conversionPattern = "dd/MM/yyyy";
+        assertEquals(
+                DATE.format(DateTimeFormatter.ofPattern(conversionPattern)),
+                FormatUtils.format(DATE, conversionPattern));
     }
 
     @Test
     public void formatLongNumber() {
-        long number = date.getTime();
+        long number = RANDOM.nextLong();
         DecimalFormat df = new DecimalFormat();
         df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH));
         assertEquals(df.format(number), FormatUtils.format(number));
 
-        conversionPattern = "###,###";
+        String conversionPattern = "###,###";
         df = new DecimalFormat(conversionPattern);
         df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH));
         assertEquals(df.format(number), FormatUtils.format(number, conversionPattern));
@@ -65,12 +65,12 @@ public class FormatUtilsTest extends AbstractTest {
 
     @Test
     public void formatDoubleNumber() {
-        double number = date.getTime();
+        double number = RANDOM.nextDouble();
         DecimalFormat df = new DecimalFormat();
         df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH));
         assertEquals(df.format(number), FormatUtils.format(number));
 
-        conversionPattern = "###,###";
+        String conversionPattern = "###,###";
         df = new DecimalFormat(conversionPattern);
         df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH));
         assertEquals(df.format(number), FormatUtils.format(number, conversionPattern));
@@ -78,20 +78,23 @@ public class FormatUtilsTest extends AbstractTest {
 
     @Test
     public void parseDate() throws ParseException {
-        String source = new SimpleDateFormat(SyncopeConstants.DEFAULT_DATE_PATTERN).format(date);
-        assertEquals(DateUtils.parseDate(source, SyncopeConstants.DATE_PATTERNS),
+        String source = DATE.truncatedTo(ChronoUnit.SECONDS).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+        assertEquals(
+                OffsetDateTime.parse(source, DateTimeFormatter.ISO_OFFSET_DATE_TIME),
                 FormatUtils.parseDate(source));
 
-        conversionPattern = "dd-MM-yyyy";
-        source = new SimpleDateFormat(conversionPattern).format(date);
-        assertEquals(DateUtils.parseDate(source, conversionPattern),
+        String conversionPattern = "dd-MM-yyyy";
+        source = DATE.format(DateTimeFormatter.ofPattern(conversionPattern));
+        assertEquals(
+                LocalDate.parse(source, DateTimeFormatter.ofPattern(conversionPattern)).
+                        atStartOfDay(FormatUtils.DEFAULT_OFFSET).toOffsetDateTime(),
                 FormatUtils.parseDate(source, conversionPattern));
     }
 
     @Test
     public void parseNumber() throws ParseException {
-        String source = String.valueOf(date.getTime());
-        conversionPattern = "###,###";
+        String source = String.valueOf(RANDOM.nextLong());
+        String conversionPattern = "###,###";
         assertEquals(Long.valueOf(source), FormatUtils.parseNumber(source, conversionPattern));
     }
 }
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java
index 880f72e..5c21976 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java
@@ -18,8 +18,8 @@
  */
 package org.apache.syncope.core.provisioning.java;
 
+import java.time.OffsetDateTime;
 import java.util.Arrays;
-import java.util.Date;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.common.lib.audit.AuditEntry;
@@ -92,7 +92,7 @@ public class DefaultAuditManager implements AuditManager {
         AuditEntry auditEntry = new AuditEntry();
         auditEntry.setWho(who);
         auditEntry.setLogger(new AuditLoggerName(type, category, subcategory, event, Result.SUCCESS));
-        auditEntry.setDate(new Date());
+        auditEntry.setDate(OffsetDateTime.now());
 
         AuditConf auditConf = auditConfDAO.find(auditEntry.getLogger().toAuditKey());
         boolean auditRequested = auditConf != null && auditConf.isActive();
@@ -149,7 +149,7 @@ public class DefaultAuditManager implements AuditManager {
             AuditEntry auditEntry = new AuditEntry();
             auditEntry.setWho(who);
             auditEntry.setLogger(auditLoggerName);
-            auditEntry.setDate(new Date());
+            auditEntry.setDate(OffsetDateTime.now());
             auditEntry.setBefore(POJOHelper.serialize((maskSensitive(before))));
             if (throwable == null) {
                 auditEntry.setOutput(POJOHelper.serialize((maskSensitive(output))));
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultMappingManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultMappingManager.java
index e69fa4a..a4c90bd 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultMappingManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultMappingManager.java
@@ -20,9 +20,9 @@ package org.apache.syncope.core.provisioning.java;
 
 import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
 import java.text.ParseException;
+import java.time.temporal.TemporalAccessor;
 import java.util.ArrayList;
 import java.util.Base64;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
@@ -34,7 +34,6 @@ import org.apache.commons.jexl3.MapContext;
 import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.reflect.FieldUtils;
-import org.apache.commons.lang3.time.DateFormatUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
@@ -104,6 +103,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.transaction.annotation.Transactional;
 import org.apache.syncope.core.provisioning.api.data.ItemTransformer;
 import org.apache.syncope.core.provisioning.api.jexl.JexlUtils;
+import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
 import org.identityconnectors.framework.common.objects.Name;
 import org.identityconnectors.framework.common.objects.Uid;
 
@@ -763,10 +763,9 @@ public class DefaultMappingManager implements MappingManager {
                     default:
                         try {
                         Object fieldValue = FieldUtils.readField(ref, intAttrName.getField(), true);
-                        if (fieldValue instanceof Date) {
+                        if (fieldValue instanceof TemporalAccessor) {
                             // needed because ConnId does not natively supports the Date type
-                            attrValue.setStringValue(DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.
-                                    format((Date) fieldValue));
+                            attrValue.setStringValue(FormatUtils.format((TemporalAccessor) fieldValue));
                         } else if (Boolean.TYPE.isInstance(fieldValue)) {
                             attrValue.setBooleanValue((Boolean) fieldValue);
                         } else if (Double.TYPE.isInstance(fieldValue) || Float.TYPE.isInstance(fieldValue)) {
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccessToken.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractExecutableDatabinder.java
similarity index 64%
copy from core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccessToken.java
copy to core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractExecutableDatabinder.java
index d956385..ab939e7 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccessToken.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractExecutableDatabinder.java
@@ -16,25 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.core.persistence.api.entity;
+package org.apache.syncope.core.provisioning.java.data;
 
+import java.time.OffsetDateTime;
 import java.util.Date;
+import java.util.Optional;
+import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
 
-public interface AccessToken extends ProvidedKeyEntity {
+public abstract class AbstractExecutableDatabinder {
 
-    String getBody();
-
-    void setBody(String body);
-
-    Date getExpirationTime();
-
-    void setExpirationTime(Date expirationTime);
-
-    String getOwner();
-
-    void setOwner(String owner);
-
-    byte[] getAuthorities();
-
-    void setAuthorities(byte[] authorities);
+    protected OffsetDateTime toOffsetDateTime(final Date date) {
+        return Optional.ofNullable(date).
+                map(d -> d.toInstant().atOffset(FormatUtils.DEFAULT_OFFSET)).
+                orElse(null);
+    }
 }
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AccessTokenDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AccessTokenDataBinderImpl.java
index d420eb7..053b4ff 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AccessTokenDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AccessTokenDataBinderImpl.java
@@ -23,7 +23,7 @@ import com.nimbusds.jose.JWSHeader;
 import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.SignedJWT;
 import java.text.ParseException;
-import java.util.Calendar;
+import java.time.OffsetDateTime;
 import java.util.Date;
 import java.util.Map;
 import org.apache.commons.lang3.tuple.Pair;
@@ -72,7 +72,7 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder {
     }
 
     @Override
-    public Pair<String, Date> generateJWT(
+    public Pair<String, OffsetDateTime> generateJWT(
             final String tokenId,
             final String subject,
             final long duration,
@@ -80,19 +80,18 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder {
 
         credentialChecker.checkIsDefaultJWSKeyInUse();
 
-        Date currentTime = new Date();
+        OffsetDateTime currentTime = OffsetDateTime.now();
+        Date issueTime = new Date(currentTime.toInstant().toEpochMilli());
 
-        Calendar expiration = Calendar.getInstance();
-        expiration.setTime(currentTime);
-        expiration.add(Calendar.MINUTE, (int) duration);
+        OffsetDateTime expiration = currentTime.plusMinutes(duration);
 
         JWTClaimsSet.Builder claimsSet = new JWTClaimsSet.Builder().
                 jwtID(tokenId).
                 subject(subject).
-                issueTime(currentTime).
                 issuer(securityProperties.getJwtIssuer()).
-                expirationTime(expiration.getTime()).
-                notBeforeTime(currentTime);
+                issueTime(issueTime).
+                expirationTime(new Date(expiration.toInstant().toEpochMilli())).
+                notBeforeTime(issueTime);
         claims.forEach(claimsSet::claim);
 
         SignedJWT jwt = new SignedJWT(new JWSHeader(jwsSigner.getJwsAlgorithm()), claimsSet.build());
@@ -103,7 +102,7 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder {
             sce.getElements().add(e.getMessage());
             throw sce;
         }
-        return Pair.of(jwt.serialize(), expiration.getTime());
+        return Pair.of(jwt.serialize(), expiration);
     }
 
     private AccessToken replace(
@@ -112,7 +111,7 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder {
             final byte[] authorities,
             final AccessToken accessToken) {
 
-        Pair<String, Date> generated = generateJWT(
+        Pair<String, OffsetDateTime> generated = generateJWT(
                 accessToken.getKey(),
                 subject,
                 confParamOps.get(AuthContextUtils.getDomain(), "jwt.lifetime.minutes", 120L, Long.class),
@@ -130,7 +129,7 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder {
     }
 
     @Override
-    public Pair<String, Date> create(
+    public Pair<String, OffsetDateTime> create(
             final String subject,
             final Map<String, Object> claims,
             final byte[] authorities,
@@ -143,8 +142,9 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder {
             accessToken.setKey(SecureRandomUtils.generateRandomUUID().toString());
 
             accessToken = replace(subject, claims, authorities, accessToken);
-        } else if (replace || accessToken.getExpirationTime() == null
-                || accessToken.getExpirationTime().before(new Date())) {
+        } else if (replace
+                || accessToken.getExpirationTime() == null
+                || accessToken.getExpirationTime().isBefore(OffsetDateTime.now())) {
 
             // AccessToken found, but either replace was requested or it is expired: update existing
             accessToken = replace(subject, claims, authorities, accessToken);
@@ -154,22 +154,20 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder {
     }
 
     @Override
-    public Pair<String, Date> update(final AccessToken accessToken, final byte[] authorities) {
+    public Pair<String, OffsetDateTime> update(final AccessToken accessToken, final byte[] authorities) {
         credentialChecker.checkIsDefaultJWSKeyInUse();
 
         long duration = confParamOps.get(AuthContextUtils.getDomain(), "jwt.lifetime.minutes", 120L, Long.class);
 
-        Date currentTime = new Date();
+        OffsetDateTime currentTime = OffsetDateTime.now();
 
-        Calendar expiration = Calendar.getInstance();
-        expiration.setTime(currentTime);
-        expiration.add(Calendar.MINUTE, (int) duration);
+        OffsetDateTime expiration = currentTime.plusMinutes(duration);
 
         SignedJWT jwt;
         try {
-            JWTClaimsSet.Builder claimsSet =
-                    new JWTClaimsSet.Builder(SignedJWT.parse(accessToken.getBody()).getJWTClaimsSet()).
-                            expirationTime(expiration.getTime());
+            JWTClaimsSet.Builder claimsSet = new JWTClaimsSet.Builder(
+                    SignedJWT.parse(accessToken.getBody()).getJWTClaimsSet()).
+                    expirationTime(new Date(expiration.toInstant().toEpochMilli()));
 
             jwt = new SignedJWT(new JWSHeader(jwsSigner.getJwsAlgorithm()), claimsSet.build());
             jwt.sign(jwsSigner);
@@ -181,7 +179,7 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder {
         String body = jwt.serialize();
 
         accessToken.setBody(body);
-        accessToken.setExpirationTime(expiration.getTime());
+        accessToken.setExpirationTime(expiration);
 
         if (!securityProperties.getAdminUser().equals(accessToken.getOwner())) {
             accessToken.setAuthorities(authorities);
@@ -189,7 +187,7 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder {
 
         accessTokenDAO.save(accessToken);
 
-        return Pair.of(body, expiration.getTime());
+        return Pair.of(body, expiration);
     }
 
     @Override
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ReportDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ReportDataBinderImpl.java
index 8669929..f266f25 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ReportDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ReportDataBinderImpl.java
@@ -43,7 +43,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.scheduling.quartz.SchedulerFactoryBean;
 
-public class ReportDataBinderImpl implements ReportDataBinder {
+public class ReportDataBinderImpl extends AbstractExecutableDatabinder implements ReportDataBinder {
 
     protected static final Logger LOG = LoggerFactory.getLogger(ReportDataBinder.class);
 
@@ -123,10 +123,9 @@ public class ReportDataBinderImpl implements ReportDataBinder {
         String triggerName = JobNamer.getTriggerName(JobNamer.getJobKey(report).getName());
         try {
             Trigger trigger = scheduler.getScheduler().getTrigger(new TriggerKey(triggerName, Scheduler.DEFAULT_GROUP));
-
             if (trigger != null) {
-                reportTO.setLastExec(trigger.getPreviousFireTime());
-                reportTO.setNextExec(trigger.getNextFireTime());
+                reportTO.setLastExec(toOffsetDateTime(trigger.getPreviousFireTime()));
+                reportTO.setNextExec(toOffsetDateTime(trigger.getNextFireTime()));
             }
         } catch (SchedulerException e) {
             LOG.warn("While trying to get to " + triggerName, e);
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
index 5b23028..424e081 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
@@ -73,7 +73,7 @@ import org.springframework.scheduling.quartz.SchedulerFactoryBean;
 import org.apache.syncope.core.persistence.api.entity.task.PushTaskAnyFilter;
 import org.apache.syncope.core.persistence.api.entity.task.TaskUtilsFactory;
 
-public class TaskDataBinderImpl implements TaskDataBinder {
+public class TaskDataBinderImpl extends AbstractExecutableDatabinder implements TaskDataBinder {
 
     protected static final Logger LOG = LoggerFactory.getLogger(TaskDataBinder.class);
 
@@ -340,10 +340,9 @@ public class TaskDataBinderImpl implements TaskDataBinder {
         String triggerName = JobNamer.getTriggerName(JobNamer.getJobKey(schedTask).getName());
         try {
             Trigger trigger = scheduler.getScheduler().getTrigger(new TriggerKey(triggerName, Scheduler.DEFAULT_GROUP));
-
             if (trigger != null) {
-                schedTaskTO.setLastExec(trigger.getPreviousFireTime());
-                schedTaskTO.setNextExec(trigger.getNextFireTime());
+                schedTaskTO.setLastExec(toOffsetDateTime(trigger.getPreviousFireTime()));
+                schedTaskTO.setNextExec(toOffsetDateTime(trigger.getNextFireTime()));
             }
         } catch (SchedulerException e) {
             LOG.warn("While trying to get to " + triggerName, e);
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
index 879b454..0d4a345 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.provisioning.java.data;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Optional;
@@ -327,7 +327,7 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
             LOG.debug("Password was not provided or not required to be stored");
         } else {
             setPassword(user, userCR.getPassword(), scce);
-            user.setChangePwdDate(new Date());
+            user.setChangePwdDate(OffsetDateTime.now());
         }
 
         user.setMustChangePassword(userCR.isMustChangePassword());
@@ -485,7 +485,7 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
             } else if (StringUtils.isNotBlank(userUR.getPassword().getValue())) {
                 if (userUR.getPassword().isOnSyncope()) {
                     setPassword(user, userUR.getPassword().getValue(), scce);
-                    user.setChangePwdDate(new Date());
+                    user.setChangePwdDate(OffsetDateTime.now());
                 }
 
                 password = userUR.getPassword().getValue();
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AbstractSchedTaskJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AbstractSchedTaskJobDelegate.java
index 59f93b8..41c7899 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AbstractSchedTaskJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AbstractSchedTaskJobDelegate.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.provisioning.java.job;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.Optional;
 import java.util.concurrent.atomic.AtomicReference;
 import org.apache.syncope.common.lib.types.AuditElements;
@@ -119,7 +119,7 @@ public abstract class AbstractSchedTaskJobDelegate implements SchedTaskJobDelega
         String executor = Optional.ofNullable(context.getMergedJobDataMap().getString(JobManager.EXECUTOR_KEY)).
                 orElse(securityProperties.getAdminUser());
         TaskExec execution = entityFactory.newEntity(TaskExec.class);
-        execution.setStart(new Date());
+        execution.setStart(OffsetDateTime.now());
         execution.setTask(task);
         execution.setExecutor(executor);
 
@@ -138,7 +138,7 @@ public abstract class AbstractSchedTaskJobDelegate implements SchedTaskJobDelega
             execution.setMessage(ExceptionUtils2.getFullStackTrace(e));
             execution.setStatus(TaskJob.Status.FAILURE.name());
         }
-        execution.setEnd(new Date());
+        execution.setEnd(OffsetDateTime.now());
 
         if (hasToBeRegistered(execution)) {
             register(execution);
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/DefaultJobManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/DefaultJobManager.java
index 63c48a5..ab3c1ce 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/DefaultJobManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/DefaultJobManager.java
@@ -22,13 +22,14 @@ import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.time.OffsetDateTime;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
-
 import javax.sql.DataSource;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
@@ -37,17 +38,26 @@ import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.core.persistence.api.DomainHolder;
+import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
+import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
 import org.apache.syncope.core.persistence.api.dao.ReportDAO;
 import org.apache.syncope.core.persistence.api.dao.TaskDAO;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.Report;
+import org.apache.syncope.core.persistence.api.entity.task.PullTask;
 import org.apache.syncope.core.persistence.api.entity.task.PushTask;
 import org.apache.syncope.core.persistence.api.entity.task.SchedTask;
 import org.apache.syncope.core.persistence.api.entity.task.Task;
+import org.apache.syncope.core.provisioning.api.job.JobManager;
 import org.apache.syncope.core.provisioning.api.job.JobNamer;
+import org.apache.syncope.core.provisioning.api.job.SchedTaskJobDelegate;
+import org.apache.syncope.core.provisioning.java.job.notification.NotificationJob;
+import org.apache.syncope.core.provisioning.java.job.report.ReportJob;
+import org.apache.syncope.core.provisioning.java.pushpull.PullJobDelegate;
+import org.apache.syncope.core.provisioning.java.pushpull.PushJobDelegate;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
-import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
-import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
-import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.core.spring.security.SecurityProperties;
+import org.identityconnectors.common.IOUtil;
 import org.quartz.CronScheduleBuilder;
 import org.quartz.Job;
 import org.quartz.JobBuilder;
@@ -55,24 +65,15 @@ import org.quartz.JobDataMap;
 import org.quartz.JobKey;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
+import org.quartz.Trigger;
 import org.quartz.TriggerBuilder;
 import org.quartz.TriggerKey;
+import org.quartz.impl.jdbcjobstore.Constants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.datasource.DataSourceUtils;
 import org.springframework.scheduling.quartz.SchedulerFactoryBean;
 import org.springframework.transaction.annotation.Transactional;
-import org.apache.syncope.core.provisioning.api.job.JobManager;
-import org.identityconnectors.common.IOUtil;
-import org.quartz.impl.jdbcjobstore.Constants;
-import org.springframework.jdbc.datasource.DataSourceUtils;
-import org.apache.syncope.core.persistence.api.entity.task.PullTask;
-import org.apache.syncope.core.provisioning.api.job.SchedTaskJobDelegate;
-import org.apache.syncope.core.provisioning.java.job.notification.NotificationJob;
-import org.apache.syncope.core.provisioning.java.job.report.ReportJob;
-import org.apache.syncope.core.provisioning.java.pushpull.PullJobDelegate;
-import org.apache.syncope.core.provisioning.java.pushpull.PushJobDelegate;
-import org.apache.syncope.core.spring.security.SecurityProperties;
-import org.quartz.Trigger;
 
 public class DefaultJobManager implements JobManager, SyncopeCoreLoader {
 
@@ -154,8 +155,10 @@ public class DefaultJobManager implements JobManager, SyncopeCoreLoader {
     }
 
     protected void registerJob(
-            final String jobName, final Class<? extends Job> jobClass,
-            final String cronExpression, final Date startAt,
+            final String jobName,
+            final Class<? extends Job> jobClass,
+            final String cronExpression,
+            final Date startAt,
             final Map<String, Object> jobMap)
             throws SchedulerException {
 
@@ -197,7 +200,10 @@ public class DefaultJobManager implements JobManager, SyncopeCoreLoader {
     }
 
     @Override
-    public Map<String, Object> register(final SchedTask task, final Date startAt, final long interruptMaxRetries,
+    public Map<String, Object> register(
+            final SchedTask task,
+            final OffsetDateTime startAt,
+            final long interruptMaxRetries,
             final String executor)
             throws SchedulerException {
 
@@ -225,19 +231,27 @@ public class DefaultJobManager implements JobManager, SyncopeCoreLoader {
                 JobNamer.getJobKey(task).getName(),
                 TaskJob.class,
                 task.getCronExpression(),
-                startAt,
+                Optional.ofNullable(startAt).map(s -> new Date(s.toInstant().toEpochMilli())).orElse(null),
                 jobMap);
         return jobMap;
     }
 
     @Override
-    public void register(final Report report, final Date startAt, final long interruptMaxRetries,
+    public void register(
+            final Report report,
+            final OffsetDateTime startAt,
+            final long interruptMaxRetries,
             final String executor) throws SchedulerException {
 
         Map<String, Object> jobMap = createJobMapForExecutionContext(executor);
         jobMap.put(JobManager.REPORT_KEY, report.getKey());
 
-        registerJob(JobNamer.getJobKey(report).getName(), ReportJob.class, report.getCronExpression(), startAt, jobMap);
+        registerJob(
+                JobNamer.getJobKey(report).getName(),
+                ReportJob.class,
+                report.getCronExpression(),
+                Optional.ofNullable(startAt).map(s -> new Date(s.toInstant().toEpochMilli())).orElse(null),
+                jobMap);
     }
 
     protected static Map<String, Object> createJobMapForExecutionContext(final String executor) {
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/DefaultNotificationJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/DefaultNotificationJobDelegate.java
index 94a5059..f7f3b4f 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/DefaultNotificationJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/DefaultNotificationJobDelegate.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.provisioning.java.job.notification;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.mail.internet.MimeMessage;
@@ -96,7 +96,7 @@ public class DefaultNotificationJobDelegate implements NotificationJobDelegate {
     public TaskExec executeSingle(final NotificationTask task, final String executor) {
         TaskExec execution = entityFactory.newEntity(TaskExec.class);
         execution.setTask(task);
-        execution.setStart(new Date());
+        execution.setStart(OffsetDateTime.now());
         execution.setExecutor(executor);
         boolean retryPossible = true;
 
@@ -196,7 +196,7 @@ public class DefaultNotificationJobDelegate implements NotificationJobDelegate {
                             "Could not send notification to " + to, e);
                 }
 
-                execution.setEnd(new Date());
+                execution.setEnd(OffsetDateTime.now());
             }
         }
 
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/DefaultReportJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/DefaultReportJobDelegate.java
index 0a46700..8daf068 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/DefaultReportJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/DefaultReportJobDelegate.java
@@ -21,7 +21,7 @@ package org.apache.syncope.core.provisioning.java.job.report;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.Optional;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.zip.Deflater;
@@ -35,17 +35,16 @@ import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.sax.SAXTransformerFactory;
 import javax.xml.transform.sax.TransformerHandler;
 import javax.xml.transform.stream.StreamResult;
-
 import org.apache.syncope.common.lib.types.ReportExecStatus;
-import org.apache.syncope.core.provisioning.api.utils.ExceptionUtils2;
 import org.apache.syncope.core.persistence.api.dao.ReportDAO;
 import org.apache.syncope.core.persistence.api.dao.ReportExecDAO;
 import org.apache.syncope.core.persistence.api.dao.Reportlet;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.Report;
 import org.apache.syncope.core.persistence.api.entity.ReportExec;
-import org.apache.syncope.core.spring.ImplementationManager;
 import org.apache.syncope.core.provisioning.api.job.report.ReportJobDelegate;
+import org.apache.syncope.core.provisioning.api.utils.ExceptionUtils2;
+import org.apache.syncope.core.spring.ImplementationManager;
 import org.quartz.JobExecutionException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -121,7 +120,7 @@ public class DefaultReportJobDelegate implements ReportJobDelegate {
         // 1. create execution
         ReportExec execution = entityFactory.newEntity(ReportExec.class);
         execution.setStatus(ReportExecStatus.STARTED);
-        execution.setStart(new Date());
+        execution.setStart(OffsetDateTime.now());
         execution.setReport(report);
 
         execution.setExecutor(executor);
@@ -220,7 +219,7 @@ public class DefaultReportJobDelegate implements ReportJobDelegate {
 
             execution.setExecResult(baos.toByteArray());
             execution.setMessage(reportExecutionMessage.toString());
-            execution.setEnd(new Date());
+            execution.setEnd(OffsetDateTime.now());
             reportExecDAO.save(execution);
         }
     }
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
index 4ef8d0d..682070d 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
@@ -18,9 +18,9 @@
  */
 package org.apache.syncope.core.provisioning.java.propagation;
 
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -312,7 +312,7 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
 
         List<PropagationActions> actions = getPropagationActions(task.getResource());
 
-        Date start = new Date();
+        OffsetDateTime start = OffsetDateTime.now();
 
         TaskExec execution = entityFactory.newEntity(TaskExec.class);
         execution.setStatus(ExecStatus.CREATED.name());
@@ -426,7 +426,7 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
 
             execution.setStart(start);
             execution.setMessage(taskExecutionMessage);
-            execution.setEnd(new Date());
+            execution.setEnd(OffsetDateTime.now());
 
             LOG.debug("Execution finished: {}", execution);
 
@@ -512,7 +512,7 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
         TaskExec execution = entityFactory.newEntity(TaskExec.class);
         execution.setStatus(ExecStatus.NOT_ATTEMPTED.name());
         execution.setExecutor(executor);
-        execution.setStart(new Date());
+        execution.setStart(OffsetDateTime.now());
         execution.setMessage(rejectReason);
         execution.setEnd(execution.getStart());
 
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
index 6c8de99..02c12df 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
@@ -18,8 +18,8 @@
  */
 package org.apache.syncope.core.provisioning.java.pushpull;
 
+import java.time.OffsetDateTime;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -973,6 +973,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
             final PullTask pullTask,
             final ProvisioningReport result,
             final SyncDelta delta) {
+
         Remediation entity = entityFactory.newEntity(Remediation.class);
 
         entity.setAnyType(anyType);
@@ -985,11 +986,10 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
             entity.setPayload(anyUR);
         }
         entity.setError(result.getMessage());
-        entity.setInstant(new Date());
+        entity.setInstant(OffsetDateTime.now());
         entity.setRemoteName(delta.getObject().getName().getNameValue());
         entity.setPullTask(pullTask);
 
         return remediationDAO.save(entity);
     }
-
 }
diff --git a/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/keymaster/internal/SelfKeymasterInternalConfParamOps.java b/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/keymaster/internal/SelfKeymasterInternalConfParamOps.java
index be93d8f..7f0b5e2 100644
--- a/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/keymaster/internal/SelfKeymasterInternalConfParamOps.java
+++ b/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/keymaster/internal/SelfKeymasterInternalConfParamOps.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.core.keymaster.internal;
 
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
@@ -34,7 +34,7 @@ public class SelfKeymasterInternalConfParamOps implements ConfParamOps {
 
     protected static final Logger LOG = LoggerFactory.getLogger(ConfParamOps.class);
 
-    protected static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     protected final ConfParamLogic logic;
 
diff --git a/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/keymaster/rest/cxf/service/ConfParamServiceImpl.java b/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/keymaster/rest/cxf/service/ConfParamServiceImpl.java
index b908a76..b393686 100644
--- a/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/keymaster/rest/cxf/service/ConfParamServiceImpl.java
+++ b/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/keymaster/rest/cxf/service/ConfParamServiceImpl.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.core.keymaster.rest.cxf.service;
 
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Map;
@@ -37,7 +37,7 @@ public class ConfParamServiceImpl implements ConfParamService {
 
     protected static final Logger LOG = LoggerFactory.getLogger(ConfParamService.class);
 
-    protected static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     protected final ConfParamLogic logic;
 
diff --git a/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/logic/ConfParamLogic.java b/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/logic/ConfParamLogic.java
index 6903e85..5ff8f34 100644
--- a/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/logic/ConfParamLogic.java
+++ b/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/logic/ConfParamLogic.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.logic;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.lang.reflect.Method;
 import java.util.Map;
 import java.util.Optional;
@@ -35,7 +35,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 public class ConfParamLogic extends AbstractTransactionalLogic<EntityTO> {
 
-    protected static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     protected final ConfParamDAO confParamDAO;
 
diff --git a/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConfParam.java b/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConfParam.java
index a5eda65..408bd2f 100644
--- a/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConfParam.java
+++ b/core/self-keymaster-starter/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConfParam.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.persistence.jpa.entity;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.IOException;
 import javax.persistence.Entity;
 import javax.persistence.Lob;
@@ -33,7 +33,7 @@ public class JPAConfParam extends AbstractProvidedKeyEntity implements ConfParam
 
     private static final long serialVersionUID = 8742750097008236475L;
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     public static final String TABLE = "ConfParam";
 
diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java
index 6211f33..484da7a 100644
--- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java
+++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.spring.security;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -258,7 +258,7 @@ public class AuthDataAccessor {
                         SyncopeAuthenticationDetails.class.cast(authentication.getDetails()), user.getKey());
 
                 if (confParamOps.get(domain, "log.lastlogindate", true, Boolean.class)) {
-                    user.setLastLoginDate(new Date());
+                    user.setLastLoginDate(OffsetDateTime.now());
                     userModified = true;
                 }
 
diff --git a/core/starter/src/main/resources/core.properties b/core/starter/src/main/resources/core.properties
index adac19e..5dbd33e 100644
--- a/core/starter/src/main/resources/core.properties
+++ b/core/starter/src/main/resources/core.properties
@@ -42,7 +42,7 @@ persistence.remoteCommitProvider=sjvm
 
 persistence.domain[0].key=Master
 persistence.domain[0].jdbcDriver=org.postgresql.Driver
-persistence.domain[0].jdbcURL=jdbc:postgresql://localhost:5432/syncope
+persistence.domain[0].jdbcURL=jdbc:postgresql://localhost:5432/syncope?stringtype=unspecified
 persistence.domain[0].dbUsername=syncope
 persistence.domain[0].dbPassword=syncope
 persistence.domain[0].databasePlatform=org.apache.openjpa.jdbc.sql.PostgresDictionary
diff --git a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractWorkflowAdapter.java b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractWorkflowAdapter.java
index 1f9ef76..9c2c60b 100644
--- a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractWorkflowAdapter.java
+++ b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractWorkflowAdapter.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.workflow.java;
 
-import java.util.Date;
+import java.time.OffsetDateTime;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
@@ -28,7 +28,7 @@ public abstract class AbstractWorkflowAdapter {
     protected void metadata(final Any<?> any, final String username, final String context) {
         String who = username
                 + AuthContextUtils.getDelegatedBy().map(d -> " [delegated by " + d + "]").orElse(StringUtils.EMPTY);
-        Date now = new Date();
+        OffsetDateTime now = OffsetDateTime.now();
 
         if (any.getCreationDate() == null) {
             any.setCreationDate(now);
diff --git a/docker/core/src/main/resources/core-oracle.properties b/docker/core/src/main/resources/core-oracle.properties
index 88a8df9..041a474 100644
--- a/docker/core/src/main/resources/core-oracle.properties
+++ b/docker/core/src/main/resources/core-oracle.properties
@@ -27,5 +27,7 @@ persistence.domain[0].auditSql=audit_oracle.sql
 persistence.domain[0].poolMaxActive=${DB_POOL_MAX}
 persistence.domain[0].poolMinIdle=${DB_POOL_MIN}
 
+persistence.indexesXML=classpath:oracle_indexes.xml
+
 provisioning.quartz.delegate=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
 provisioning.quartz.sql=tables_oracle.sql
diff --git a/docker/src/main/resources/docker-compose/docker-compose-all.yml b/docker/src/main/resources/docker-compose/docker-compose-all.yml
index d61ba89..e924b70 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-all.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-all.yml
@@ -45,7 +45,7 @@ services:
      restart: always
      environment:
        SPRING_PROFILES_ACTIVE: docker,postgresql
-       DB_URL: jdbc:postgresql://db:5432/syncope
+       DB_URL: jdbc:postgresql://db:5432/syncope?stringtype=unspecified
        DB_USER: syncope
        DB_PASSWORD: syncope
        DB_POOL_MAX: 10
diff --git a/docker/src/main/resources/docker-compose/docker-compose-ha.yml b/docker/src/main/resources/docker-compose/docker-compose-ha.yml
index 348d7ea..474933d 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-ha.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-ha.yml
@@ -38,7 +38,7 @@ services:
      restart: always
      environment:
        SPRING_PROFILES_ACTIVE: docker,postgresql
-       DB_URL: jdbc:postgresql://db:5432/syncope
+       DB_URL: jdbc:postgresql://db:5432/syncope?stringtype=unspecified
        DB_USER: syncope
        DB_PASSWORD: syncope
        DB_POOL_MAX: 10
@@ -60,7 +60,7 @@ services:
      restart: always
      environment:
        SPRING_PROFILES_ACTIVE: docker,postgresql
-       DB_URL: jdbc:postgresql://db:5432/syncope
+       DB_URL: jdbc:postgresql://db:5432/syncope?stringtype=unspecified
        DB_USER: syncope
        DB_PASSWORD: syncope
        DB_POOL_MAX: 10
diff --git a/docker/src/main/resources/docker-compose/docker-compose-postgresql.yml b/docker/src/main/resources/docker-compose/docker-compose-postgresql.yml
index 0333cfd..c3ba54b 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-postgresql.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-postgresql.yml
@@ -37,7 +37,7 @@ services:
      restart: always
      environment:
        SPRING_PROFILES_ACTIVE: docker,postgresql
-       DB_URL: jdbc:postgresql://db:5432/syncope
+       DB_URL: jdbc:postgresql://db:5432/syncope?stringtype=unspecified
        DB_USER: syncope
        DB_PASSWORD: syncope
        DB_POOL_MAX: 10
diff --git a/docker/src/main/resources/kubernetes/syncope/values.yaml b/docker/src/main/resources/kubernetes/syncope/values.yaml
index a6a8513..e30364f 100644
--- a/docker/src/main/resources/kubernetes/syncope/values.yaml
+++ b/docker/src/main/resources/kubernetes/syncope/values.yaml
@@ -16,7 +16,7 @@
 # under the License.
 ### Environment Variables that will be set on all 3 syncope docker containers (core, console, enduser)
 syncopeEnvironment:
-  dbUrl: jdbc:postgresql://postgres:5432/syncope
+  dbUrl: jdbc:postgresql://postgres:5432/syncope?stringtype=unspecified
   dbUser: syncope
   dbPoolMax: 10
   dbPoolMin: 2
diff --git a/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchClientFactoryBean.java b/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchClientFactoryBean.java
index 1a6aae4..192ed81 100644
--- a/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchClientFactoryBean.java
+++ b/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchClientFactoryBean.java
@@ -21,6 +21,8 @@ package org.apache.syncope.ext.elasticsearch.client;
 import co.elastic.clients.elasticsearch.ElasticsearchClient;
 import co.elastic.clients.json.jackson.JacksonJsonpMapper;
 import co.elastic.clients.transport.rest_client.RestClientTransport;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.nio.charset.StandardCharsets;
 import java.util.Base64;
 import java.util.List;
@@ -115,7 +117,10 @@ public class ElasticsearchClientFactoryBean implements FactoryBean<Elasticsearch
                 }
 
                 restClient = builder.build();
-                client = new ElasticsearchClient(new RestClientTransport(restClient, new JacksonJsonpMapper()));
+                client = new ElasticsearchClient(new RestClientTransport(
+                        restClient,
+                        new JacksonJsonpMapper(JsonMapper.builder().
+                                findAndAddModules().disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS).build())));
             }
         }
         return client;
diff --git a/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java b/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
index 26406b8..56d180a 100644
--- a/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
+++ b/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
@@ -76,6 +76,7 @@ import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.Realm;
+import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
 import org.apache.syncope.core.provisioning.api.utils.RealmUtils;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
 import org.apache.syncope.ext.elasticsearch.client.ElasticsearchUtils;
@@ -482,7 +483,7 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
             final AttrCond cond) {
 
         Object value = schema.getType() == AttrSchemaType.Date && attrValue.getDateValue() != null
-                ? attrValue.getDateValue().getTime()
+                ? FormatUtils.format(attrValue.getDateValue())
                 : attrValue.getValue();
 
         Query query = null;
diff --git a/ext/elasticsearch/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/ElasticsearchReindex.java b/ext/elasticsearch/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/ElasticsearchReindex.java
index f7ef590..4627643 100644
--- a/ext/elasticsearch/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/ElasticsearchReindex.java
+++ b/ext/elasticsearch/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/ElasticsearchReindex.java
@@ -115,7 +115,7 @@ public class ElasticsearchReindex extends AbstractSchedTaskJobDelegate {
                             IndexResponse response = client.index(request);
                             LOG.debug("Index successfully created for {}: {}", user, response);
                         } catch (Exception e) {
-                            LOG.error("Could not create index for {} {}", AnyTypeKind.USER, user);
+                            LOG.error("Could not create index for {} {}", AnyTypeKind.USER, user, e);
                         }
                     }
                 }
@@ -133,7 +133,7 @@ public class ElasticsearchReindex extends AbstractSchedTaskJobDelegate {
                             IndexResponse response = client.index(request);
                             LOG.debug("Index successfully created for {}: {}", group, response);
                         } catch (Exception e) {
-                            LOG.error("Could not create index for {} {}", AnyTypeKind.GROUP, group);
+                            LOG.error("Could not create index for {} {}", AnyTypeKind.GROUP, group, e);
                         }
                     }
                 }
@@ -151,7 +151,7 @@ public class ElasticsearchReindex extends AbstractSchedTaskJobDelegate {
                             IndexResponse response = client.index(request);
                             LOG.debug("Index successfully created for {}: {}", anyObject, response);
                         } catch (Exception e) {
-                            LOG.error("Could not create index for {} {}", AnyTypeKind.ANY_OBJECT, anyObject);
+                            LOG.error("Could not create index for {} {}", AnyTypeKind.ANY_OBJECT, anyObject, e);
                         }
                     }
                 }
diff --git a/ext/flowable/client-common-ui/src/main/java/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel.java b/ext/flowable/client-common-ui/src/main/java/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel.java
index cb5e8ec..6a5a169 100644
--- a/ext/flowable/client-common-ui/src/main/java/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel.java
+++ b/ext/flowable/client-common-ui/src/main/java/org/apache/syncope/ext/client/common/ui/panels/UserRequestFormPanel.java
@@ -76,7 +76,7 @@ public abstract class UserRequestFormPanel extends Panel {
             private static final long serialVersionUID = 9101744072914090143L;
 
             @Override
-            @SuppressWarnings({"unchecked", "rawtypes"})
+            @SuppressWarnings({ "unchecked", "rawtypes" })
             protected void populateItem(final ListItem<UserRequestFormProperty> item) {
                 final UserRequestFormProperty prop = item.getModelObject();
 
@@ -92,8 +92,8 @@ public abstract class UserRequestFormPanel extends Panel {
                             @Override
                             public String getObject() {
                                 return StringUtils.isBlank(prop.getValue())
-                                    ? null
-                                    : prop.getValue().equals("true") ? "Yes" : "No";
+                                        ? null
+                                        : prop.getValue().equals("true") ? "Yes" : "No";
                             }
 
                             @Override
@@ -114,8 +114,8 @@ public abstract class UserRequestFormPanel extends Panel {
                             public Date getObject() {
                                 try {
                                     return StringUtils.isBlank(prop.getValue())
-                                        ? null
-                                        : formatter.parse(prop.getValue());
+                                            ? null
+                                            : formatter.parse(prop.getValue());
                                 } catch (ParseException e) {
                                     LOG.error("Unparsable date: {}", prop.getValue(), e);
                                     return null;
@@ -126,53 +126,52 @@ public abstract class UserRequestFormPanel extends Panel {
                             public void setObject(final Date object) {
                                 prop.setValue(formatter.format(object));
                             }
-
                         }, formatter);
                         break;
 
                     case Enum:
                         field = new AjaxDropDownChoicePanel(
-                            "value", label, new PropertyModel<String>(prop, "value"), false).
-                            setChoiceRenderer(new MapChoiceRenderer(prop.getEnumValues().stream().
-                                collect(Collectors.toMap(
-                                    UserRequestFormPropertyValue::getKey,
-                                    UserRequestFormPropertyValue::getValue)))).
-                            setChoices(prop.getEnumValues().stream().
-                                map(UserRequestFormPropertyValue::getKey).collect(Collectors.toList()));
+                                "value", label, new PropertyModel<String>(prop, "value"), false).
+                                setChoiceRenderer(new MapChoiceRenderer(prop.getEnumValues().stream().
+                                        collect(Collectors.toMap(
+                                                UserRequestFormPropertyValue::getKey,
+                                                UserRequestFormPropertyValue::getValue)))).
+                                setChoices(prop.getEnumValues().stream().
+                                        map(UserRequestFormPropertyValue::getKey).collect(Collectors.toList()));
                         break;
 
                     case Dropdown:
                         field = new AjaxDropDownChoicePanel(
-                            "value", label, new PropertyModel<String>(prop, "value"), false).
-                            setChoiceRenderer(new MapChoiceRenderer(prop.getDropdownValues().stream().
-                                collect(Collectors.toMap(
-                                    UserRequestFormPropertyValue::getKey,
-                                    UserRequestFormPropertyValue::getValue)))).
-                            setChoices(prop.getDropdownValues().stream().
-                                map(UserRequestFormPropertyValue::getKey).collect(Collectors.toList()));
+                                "value", label, new PropertyModel<String>(prop, "value"), false).
+                                setChoiceRenderer(new MapChoiceRenderer(prop.getDropdownValues().stream().
+                                        collect(Collectors.toMap(
+                                                UserRequestFormPropertyValue::getKey,
+                                                UserRequestFormPropertyValue::getValue)))).
+                                setChoices(prop.getDropdownValues().stream().
+                                        map(UserRequestFormPropertyValue::getKey).collect(Collectors.toList()));
                         break;
 
                     case Long:
                         field = new AjaxSpinnerFieldPanel.Builder<Long>().build(
-                            "value",
-                            label,
-                            Long.class,
-                            new PropertyModel<>(prop, "value") {
+                                "value",
+                                label,
+                                Long.class,
+                                new PropertyModel<>(prop, "value") {
 
-                                private static final long serialVersionUID = -7688359318035249200L;
+                            private static final long serialVersionUID = -7688359318035249200L;
 
-                                @Override
-                                public Long getObject() {
-                                    return StringUtils.isBlank(prop.getValue())
+                            @Override
+                            public Long getObject() {
+                                return StringUtils.isBlank(prop.getValue())
                                         ? null
                                         : NumberUtils.toLong(prop.getValue());
-                                }
+                            }
 
-                                @Override
-                                public void setObject(final Long object) {
-                                    prop.setValue(String.valueOf(object));
-                                }
-                            });
+                            @Override
+                            public void setObject(final Long object) {
+                                prop.setValue(String.valueOf(object));
+                            }
+                        });
                         break;
 
                     case Password:
diff --git a/ext/flowable/common-lib/src/test/java/org/apache/syncope/common/lib/to/JSONTest.java b/ext/flowable/common-lib/src/test/java/org/apache/syncope/common/lib/to/JSONTest.java
index 16b9305..bd8a292 100644
--- a/ext/flowable/common-lib/src/test/java/org/apache/syncope/common/lib/to/JSONTest.java
+++ b/ext/flowable/common-lib/src/test/java/org/apache/syncope/common/lib/to/JSONTest.java
@@ -19,10 +19,11 @@
 package org.apache.syncope.common.lib.to;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.syncope.common.lib.jackson.SyncopeJsonMapper;
 
 public class JSONTest extends SerializationTest {
 
-    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+    private static final ObjectMapper OBJECT_MAPPER = new SyncopeJsonMapper();
 
     @Override
     protected ObjectMapper objectMapper() {
diff --git a/ext/flowable/common-lib/src/test/java/org/apache/syncope/common/lib/to/YAMLTest.java b/ext/flowable/common-lib/src/test/java/org/apache/syncope/common/lib/to/YAMLTest.java
index 1d589ff..8e97b42 100644
--- a/ext/flowable/common-lib/src/test/java/org/apache/syncope/common/lib/to/YAMLTest.java
+++ b/ext/flowable/common-lib/src/test/java/org/apache/syncope/common/lib/to/YAMLTest.java
@@ -20,10 +20,11 @@ package org.apache.syncope.common.lib.to;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
+import org.apache.syncope.common.lib.jackson.SyncopeYAMLMapper;
 
 public class YAMLTest extends SerializationTest {
 
-    private static final YAMLMapper YAML_MAPPER = new YAMLMapper();
+    private static final YAMLMapper YAML_MAPPER = new SyncopeYAMLMapper();
 
     @Override
     protected ObjectMapper objectMapper() {
diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableBpmnProcessManager.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableBpmnProcessManager.java
index a526863..43d40be 100644
--- a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableBpmnProcessManager.java
+++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableBpmnProcessManager.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.flowable.impl;
 
 import org.apache.syncope.core.flowable.api.BpmnProcessManager;
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import java.io.IOException;
 import java.io.InputStream;
@@ -52,7 +52,7 @@ public class FlowableBpmnProcessManager implements BpmnProcessManager {
 
     protected static final Logger LOG = LoggerFactory.getLogger(BpmnProcessManager.class);
 
-    protected static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+    protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     protected static final String MODEL_DATA_JSON_MODEL = "model";
 
@@ -103,10 +103,10 @@ public class FlowableBpmnProcessManager implements BpmnProcessManager {
         Model model = getModel(FlowableRuntimeUtils.getLatestProcDefByKey(engine, key));
 
         try {
-            ObjectNode modelNode = (ObjectNode) OBJECT_MAPPER.readTree(model.getMetaInfo());
+            ObjectNode modelNode = (ObjectNode) MAPPER.readTree(model.getMetaInfo());
             modelNode.put(ModelDataJsonConstants.MODEL_ID, model.getId());
             modelNode.replace(MODEL_DATA_JSON_MODEL,
-                    OBJECT_MAPPER.readTree(engine.getRepositoryService().getModelEditorSource(model.getId())));
+                    MAPPER.readTree(engine.getRepositoryService().getModelEditorSource(model.getId())));
 
             os.write(modelNode.toString().getBytes());
         } catch (IOException e) {
@@ -157,7 +157,7 @@ public class FlowableBpmnProcessManager implements BpmnProcessManager {
             case JSON:
                 JsonNode definitionNode;
                 try {
-                    definitionNode = OBJECT_MAPPER.readTree(definition);
+                    definitionNode = MAPPER.readTree(definition);
                     if (definitionNode.has(MODEL_DATA_JSON_MODEL)) {
                         definitionNode = definitionNode.get(MODEL_DATA_JSON_MODEL);
                     }
diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableDeployUtils.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableDeployUtils.java
index 115d027..8447c23 100644
--- a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableDeployUtils.java
+++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableDeployUtils.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.flowable.impl;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
@@ -39,7 +39,7 @@ import org.flowable.engine.repository.ProcessDefinition;
 
 public final class FlowableDeployUtils {
 
-    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private static final XMLInputFactory XML_INPUT_FACTORY = XMLInputFactory.newInstance();
 
@@ -62,14 +62,14 @@ public final class FlowableDeployUtils {
     public static void deployModel(final ProcessEngine engine, final ProcessDefinition procDef) {
         XMLStreamReader xtr = null;
         try (InputStream bpmnStream = engine.getRepositoryService().
-                getResourceAsStream(procDef.getDeploymentId(), procDef.getResourceName());
-                InputStreamReader isr = new InputStreamReader(bpmnStream)) {
+                getResourceAsStream(procDef.getDeploymentId(), procDef.getResourceName());  InputStreamReader isr =
+                new InputStreamReader(bpmnStream)) {
 
             xtr = XML_INPUT_FACTORY.createXMLStreamReader(isr);
             BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);
 
             Model model = engine.getRepositoryService().newModel();
-            ObjectNode modelObjectNode = OBJECT_MAPPER.createObjectNode();
+            ObjectNode modelObjectNode = MAPPER.createObjectNode();
             modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, procDef.getName());
             model.setMetaInfo(modelObjectNode.toString());
             model.setName(procDef.getName());
diff --git a/ext/oidcc4ui/client-common-ui/src/main/java/org/apache/syncope/client/ui/commons/resources/oidcc4ui/CodeConsumerResource.java b/ext/oidcc4ui/client-common-ui/src/main/java/org/apache/syncope/client/ui/commons/resources/oidcc4ui/CodeConsumerResource.java
index fbabb3d..e86a4f0 100644
--- a/ext/oidcc4ui/client-common-ui/src/main/java/org/apache/syncope/client/ui/commons/resources/oidcc4ui/CodeConsumerResource.java
+++ b/ext/oidcc4ui/client-common-ui/src/main/java/org/apache/syncope/client/ui/commons/resources/oidcc4ui/CodeConsumerResource.java
@@ -20,7 +20,7 @@ package org.apache.syncope.client.ui.commons.resources.oidcc4ui;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import javax.servlet.http.HttpServletRequest;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.ui.commons.BaseSession;
@@ -44,8 +44,8 @@ public abstract class CodeConsumerResource extends AbstractResource {
 
     protected static final Logger LOG = LoggerFactory.getLogger(CodeConsumerResource.class);
 
-    protected static final ObjectMapper MAPPER =
-            new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+    protected static final JsonMapper MAPPER =
+            JsonMapper.builder().findAndAddModules().serializationInclusion(JsonInclude.Include.NON_EMPTY).build();
 
     protected abstract Class<? extends WebPage> getLoginPageClass();
 
diff --git a/ext/oidcc4ui/common-lib/src/main/java/org/apache/syncope/common/lib/oidc/OIDCLoginResponse.java b/ext/oidcc4ui/common-lib/src/main/java/org/apache/syncope/common/lib/oidc/OIDCLoginResponse.java
index c21fb86..4ba78e0 100644
--- a/ext/oidcc4ui/common-lib/src/main/java/org/apache/syncope/common/lib/oidc/OIDCLoginResponse.java
+++ b/ext/oidcc4ui/common-lib/src/main/java/org/apache/syncope/common/lib/oidc/OIDCLoginResponse.java
@@ -22,7 +22,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import java.io.Serializable;
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.HashSet;
 import java.util.Optional;
 import java.util.Set;
@@ -40,7 +40,7 @@ public class OIDCLoginResponse implements Serializable {
 
     private String accessToken;
 
-    private Date accessTokenExpiryTime;
+    private OffsetDateTime accessTokenExpiryTime;
 
     private final Set<Attr> attrs = new HashSet<>();
 
@@ -76,11 +76,11 @@ public class OIDCLoginResponse implements Serializable {
         this.accessToken = accessToken;
     }
 
-    public Date getAccessTokenExpiryTime() {
+    public OffsetDateTime getAccessTokenExpiryTime() {
         return accessTokenExpiryTime;
     }
 
-    public void setAccessTokenExpiryTime(final Date accessTokenExpiryTime) {
+    public void setAccessTokenExpiryTime(final OffsetDateTime accessTokenExpiryTime) {
         this.accessTokenExpiryTime = accessTokenExpiryTime;
     }
 
diff --git a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UILogic.java b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UILogic.java
index 9e5c7e9..893496b 100644
--- a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UILogic.java
+++ b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UILogic.java
@@ -23,7 +23,7 @@ import com.nimbusds.jwt.SignedJWT;
 import com.nimbusds.oauth2.sdk.AuthorizationCode;
 import java.lang.reflect.Method;
 import java.text.ParseException;
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -241,7 +241,7 @@ public class OIDCC4UILogic extends AbstractTransactionalLogic<EntityTO> {
             LOG.error("Could not fetch authorities", e);
         }
 
-        Pair<String, Date> accessTokenInfo =
+        Pair<String, OffsetDateTime> accessTokenInfo =
                 accessTokenDataBinder.create(loginResponse.getUsername(), claims, authorities, true);
         loginResponse.setAccessToken(accessTokenInfo.getLeft());
         loginResponse.setAccessTokenExpiryTime(accessTokenInfo.getRight());
diff --git a/ext/saml2sp4ui/client-common-ui/src/main/java/org/apache/syncope/client/ui/commons/resources/saml2sp4ui/AssertionConsumerResource.java b/ext/saml2sp4ui/client-common-ui/src/main/java/org/apache/syncope/client/ui/commons/resources/saml2sp4ui/AssertionConsumerResource.java
index 8c3e0bc..dcce21d 100644
--- a/ext/saml2sp4ui/client-common-ui/src/main/java/org/apache/syncope/client/ui/commons/resources/saml2sp4ui/AssertionConsumerResource.java
+++ b/ext/saml2sp4ui/client-common-ui/src/main/java/org/apache/syncope/client/ui/commons/resources/saml2sp4ui/AssertionConsumerResource.java
@@ -20,7 +20,7 @@ package org.apache.syncope.client.ui.commons.resources.saml2sp4ui;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.ui.commons.BaseSession;
 import org.apache.syncope.client.ui.commons.SAML2SP4UIConstants;
@@ -37,8 +37,8 @@ public abstract class AssertionConsumerResource extends AbstractSAML2SP4UIResour
 
     private static final long serialVersionUID = 3858609271031003370L;
 
-    protected static final ObjectMapper MAPPER =
-            new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+    protected static final JsonMapper MAPPER =
+            JsonMapper.builder().findAndAddModules().serializationInclusion(JsonInclude.Include.NON_EMPTY).build();
 
     protected abstract Class<? extends WebPage> getLoginPageClass();
 
diff --git a/ext/saml2sp4ui/common-lib/src/main/java/org/apache/syncope/common/lib/saml2/SAML2LoginResponse.java b/ext/saml2sp4ui/common-lib/src/main/java/org/apache/syncope/common/lib/saml2/SAML2LoginResponse.java
index b22c4c9..7585214 100644
--- a/ext/saml2sp4ui/common-lib/src/main/java/org/apache/syncope/common/lib/saml2/SAML2LoginResponse.java
+++ b/ext/saml2sp4ui/common-lib/src/main/java/org/apache/syncope/common/lib/saml2/SAML2LoginResponse.java
@@ -22,6 +22,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import java.io.Serializable;
+import java.time.OffsetDateTime;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.Optional;
@@ -40,7 +41,7 @@ public class SAML2LoginResponse implements Serializable {
 
     private String accessToken;
 
-    private Date accessTokenExpiryTime;
+    private OffsetDateTime accessTokenExpiryTime;
 
     private String username;
 
@@ -85,13 +86,12 @@ public class SAML2LoginResponse implements Serializable {
         this.accessToken = accessToken;
     }
 
-    public Date getAccessTokenExpiryTime() {
-        return Optional.ofNullable(accessTokenExpiryTime).map(date -> new Date(date.getTime())).orElse(null);
+    public OffsetDateTime getAccessTokenExpiryTime() {
+        return accessTokenExpiryTime;
     }
 
-    public void setAccessTokenExpiryTime(final Date accessTokenExpiryTime) {
-        this.accessTokenExpiryTime = Optional.ofNullable(accessTokenExpiryTime).
-                map(date -> new Date(date.getTime())).orElse(null);
+    public void setAccessTokenExpiryTime(final OffsetDateTime accessTokenExpiryTime) {
+        this.accessTokenExpiryTime = accessTokenExpiryTime;
     }
 
     public String getUsername() {
diff --git a/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/SAML2SP4UILogic.java b/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/SAML2SP4UILogic.java
index 2cd4b07..49b1369 100644
--- a/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/SAML2SP4UILogic.java
+++ b/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/SAML2SP4UILogic.java
@@ -24,6 +24,7 @@ import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.lang.reflect.Method;
 import java.text.ParseException;
+import java.time.OffsetDateTime;
 import java.util.Base64;
 import java.util.Date;
 import java.util.HashMap;
@@ -419,7 +420,7 @@ public class SAML2SP4UILogic extends AbstractTransactionalLogic<EntityTO> {
             LOG.error("Could not fetch authorities", e);
         }
 
-        Pair<String, Date> accessTokenInfo =
+        Pair<String, OffsetDateTime> accessTokenInfo =
                 accessTokenDataBinder.create(loginResp.getUsername(), claims, authorities, true);
         loginResp.setAccessToken(accessTokenInfo.getLeft());
         loginResp.setAccessTokenExpiryTime(accessTokenInfo.getRight());
diff --git a/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/pages/SCIMConfPage.java b/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/pages/SCIMConfPage.java
index cb7563c..19ae259 100644
--- a/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/pages/SCIMConfPage.java
+++ b/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/pages/SCIMConfPage.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.client.console.pages;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.io.Serializable;
 import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
@@ -33,17 +33,13 @@ import org.apache.syncope.common.lib.scim.types.SCIMEntitlement;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 @ExtPage(label = "SCIM 2.0", icon = "fa fa-cloud", listEntitlement = SCIMEntitlement.SCIM_CONF_GET, priority = 500)
 public class SCIMConfPage extends BaseExtPage {
 
-    protected static final Logger LOG = LoggerFactory.getLogger(SCIMConfPage.class);
-
     private static final long serialVersionUID = -8156063343062111770L;
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
 
     private final WebMarkupContainer content;
 
diff --git a/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/panels/SCIMConfGeneralPanel.java b/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/panels/SCIMConfGeneralPanel.java
index bea8c1e..34e9f1b 100644
--- a/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/panels/SCIMConfGeneralPanel.java
+++ b/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/panels/SCIMConfGeneralPanel.java
@@ -19,10 +19,10 @@
 package org.apache.syncope.client.console.panels;
 
 import java.util.Date;
-import org.apache.commons.lang3.time.FastDateFormat;
+import org.apache.commons.lang3.time.DateFormatUtils;
+import org.apache.syncope.client.ui.commons.DateOps;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.scim.SCIMConf;
 import org.apache.syncope.common.lib.scim.SCIMGeneralConf;
 import org.apache.wicket.model.Model;
@@ -48,14 +48,14 @@ public class SCIMConfGeneralPanel extends SCIMConfTabPanel {
 
                     @Override
                     public Date getObject() {
-                        return scimGeneralConf.getCreationDate();
+                        return DateOps.convert(scimGeneralConf.getCreationDate());
                     }
 
                     @Override
                     public void setObject(final Date object) {
-                        scimGeneralConf.setCreationDate(object);
+                        scimGeneralConf.setCreationDate(DateOps.convert(object));
                     }
-                }, FastDateFormat.getInstance(SyncopeConstants.DEFAULT_DATE_PATTERN));
+                }, DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT);
         creationDatePanel.setEnabled(false);
 
         AjaxDateTimeFieldPanel lastChangeDatePanel =
@@ -65,97 +65,97 @@ public class SCIMConfGeneralPanel extends SCIMConfTabPanel {
 
                     @Override
                     public Date getObject() {
-                        return scimGeneralConf.getLastChangeDate();
+                        return DateOps.convert(scimGeneralConf.getLastChangeDate());
                     }
 
                     @Override
                     public void setObject(final Date object) {
-                        scimGeneralConf.setLastChangeDate(object);
+                        scimGeneralConf.setLastChangeDate(DateOps.convert(object));
                     }
-                }, FastDateFormat.getInstance(SyncopeConstants.DEFAULT_DATE_PATTERN));
+                }, DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT);
         lastChangeDatePanel.setEnabled(false);
 
         AjaxTextFieldPanel bulkMaxOperationsPanel =
                 new AjaxTextFieldPanel("bulkMaxOperations", "bulkMaxOperations",
-                    new PropertyModel<>("bulkMaxOperations", "bulkMaxOperations") {
+                        new PropertyModel<>("bulkMaxOperations", "bulkMaxOperations") {
 
-                        private static final long serialVersionUID = -6427731218492117883L;
+                    private static final long serialVersionUID = -6427731218492117883L;
 
-                        @Override
-                        public String getObject() {
-                            return String.valueOf(scimGeneralConf.getBulkMaxOperations());
-                        }
+                    @Override
+                    public String getObject() {
+                        return String.valueOf(scimGeneralConf.getBulkMaxOperations());
+                    }
 
-                        @Override
-                        public void setObject(final String object) {
-                            try {
-                                scimGeneralConf.setBulkMaxOperations(Integer.parseInt(object));
-                            } catch (NumberFormatException e) {
-                                LOG.error("Invalid value provided for 'bulkMaxOperations': {}", object, e);
-                            }
+                    @Override
+                    public void setObject(final String object) {
+                        try {
+                            scimGeneralConf.setBulkMaxOperations(Integer.parseInt(object));
+                        } catch (NumberFormatException e) {
+                            LOG.error("Invalid value provided for 'bulkMaxOperations': {}", object, e);
                         }
-                    });
+                    }
+                });
         bulkMaxOperationsPanel.setChoices(plainSchemaNames);
 
         AjaxTextFieldPanel bulkMaxMaxPayloadSizePanel =
                 new AjaxTextFieldPanel("bulkMaxMaxPayloadSize", "bulkMaxMaxPayloadSize",
-                    new PropertyModel<>("bulkMaxMaxPayloadSize", "bulkMaxMaxPayloadSize") {
+                        new PropertyModel<>("bulkMaxMaxPayloadSize", "bulkMaxMaxPayloadSize") {
 
-                        private static final long serialVersionUID = -6427731218492117883L;
+                    private static final long serialVersionUID = -6427731218492117883L;
 
-                        @Override
-                        public String getObject() {
-                            return String.valueOf(scimGeneralConf.getBulkMaxPayloadSize());
-                        }
+                    @Override
+                    public String getObject() {
+                        return String.valueOf(scimGeneralConf.getBulkMaxPayloadSize());
+                    }
 
-                        @Override
-                        public void setObject(final String object) {
-                            try {
-                                scimGeneralConf.setBulkMaxPayloadSize(Integer.parseInt(object));
-                            } catch (NumberFormatException e) {
-                                LOG.error("Invalid value provided for 'bulkMaxPayloadSize': {}", object, e);
-                            }
+                    @Override
+                    public void setObject(final String object) {
+                        try {
+                            scimGeneralConf.setBulkMaxPayloadSize(Integer.parseInt(object));
+                        } catch (NumberFormatException e) {
+                            LOG.error("Invalid value provided for 'bulkMaxPayloadSize': {}", object, e);
                         }
-                    });
+                    }
+                });
         bulkMaxMaxPayloadSizePanel.setChoices(plainSchemaNames);
 
         AjaxTextFieldPanel filterMaxResultsPanel =
                 new AjaxTextFieldPanel("filterMaxResults", "filterMaxResults",
-                    new PropertyModel<>("filterMaxResults", "filterMaxResults") {
+                        new PropertyModel<>("filterMaxResults", "filterMaxResults") {
 
-                        private static final long serialVersionUID = -6427731218492117883L;
+                    private static final long serialVersionUID = -6427731218492117883L;
 
-                        @Override
-                        public String getObject() {
-                            return String.valueOf(scimGeneralConf.getFilterMaxResults());
-                        }
+                    @Override
+                    public String getObject() {
+                        return String.valueOf(scimGeneralConf.getFilterMaxResults());
+                    }
 
-                        @Override
-                        public void setObject(final String object) {
-                            try {
-                                scimGeneralConf.setFilterMaxResults(Integer.parseInt(object));
-                            } catch (NumberFormatException e) {
-                                LOG.error("Invalid value provided for 'filterMaxResults': {}", object, e);
-                            }
+                    @Override
+                    public void setObject(final String object) {
+                        try {
+                            scimGeneralConf.setFilterMaxResults(Integer.parseInt(object));
+                        } catch (NumberFormatException e) {
+                            LOG.error("Invalid value provided for 'filterMaxResults': {}", object, e);
                         }
-                    });
+                    }
+                });
         filterMaxResultsPanel.setChoices(plainSchemaNames);
 
         AjaxTextFieldPanel eTagValuePanel = new AjaxTextFieldPanel("eTagValue", "eTagValue",
-            new PropertyModel<>("eTagValue", "eTagValue") {
+                new PropertyModel<>("eTagValue", "eTagValue") {
 
-                private static final long serialVersionUID = -6427731218492117883L;
+            private static final long serialVersionUID = -6427731218492117883L;
 
-                @Override
-                public String getObject() {
-                    return scimGeneralConf.getETagValue();
-                }
+            @Override
+            public String getObject() {
+                return scimGeneralConf.getETagValue();
+            }
 
-                @Override
-                public void setObject(final String object) {
-                    // nothing to do
-                }
-            });
+            @Override
+            public void setObject(final String object) {
+                // nothing to do
+            }
+        });
         eTagValuePanel.setEnabled(false);
 
         add(creationDatePanel);
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMGeneralConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMGeneralConf.java
index 7648bc2..47131e0 100644
--- a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMGeneralConf.java
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMGeneralConf.java
@@ -20,7 +20,7 @@ package org.apache.syncope.common.lib.scim;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import java.io.Serializable;
-import java.util.Date;
+import java.time.OffsetDateTime;
 import java.util.Optional;
 
 import org.apache.commons.lang3.StringUtils;
@@ -29,9 +29,9 @@ public class SCIMGeneralConf implements Serializable {
 
     private static final long serialVersionUID = 3228349133950736647L;
 
-    private Date creationDate = new Date();
+    private OffsetDateTime creationDate = OffsetDateTime.now();
 
-    private Date lastChangeDate = new Date();
+    private OffsetDateTime lastChangeDate = OffsetDateTime.now();
 
     private int bulkMaxOperations = 1000;
 
@@ -39,41 +39,29 @@ public class SCIMGeneralConf implements Serializable {
 
     private int filterMaxResults = 200;
 
-    public Date getCreationDate() {
-        if (creationDate != null) {
-            return new Date(creationDate.getTime());
-        }
-        return null;
+    public OffsetDateTime getCreationDate() {
+        return creationDate;
     }
 
-    public void setCreationDate(final Date creationDate) {
-        if (creationDate != null) {
-            this.creationDate = new Date(creationDate.getTime());
-        } else {
-            this.creationDate = null;
-        }
+    public void setCreationDate(final OffsetDateTime creationDate) {
+        this.creationDate = creationDate;
     }
 
-    public Date getLastChangeDate() {
-        if (lastChangeDate != null) {
-            return new Date(lastChangeDate.getTime());
-        }
-        return null;
+    public OffsetDateTime getLastChangeDate() {
+        return lastChangeDate;
     }
 
-    public void setLastChangeDate(final Date lastChangeDate) {
-        if (lastChangeDate != null) {
-            this.lastChangeDate = new Date(lastChangeDate.getTime());
-        } else {
-            this.lastChangeDate = null;
-        }
+    public void setLastChangeDate(final OffsetDateTime lastChangeDate) {
+        this.lastChangeDate = lastChangeDate;
     }
 
     @JsonIgnore
     public String getETagValue() {
-        Date etagDate = getLastChangeDate() == null
+        OffsetDateTime etagDate = getLastChangeDate() == null
                 ? getCreationDate() : getLastChangeDate();
-        return Optional.ofNullable(etagDate).map(date -> String.valueOf(date.getTime())).orElse(StringUtils.EMPTY);
+        return Optional.ofNullable(etagDate).
+                map(date -> String.valueOf(date.toInstant().toEpochMilli())).
+                orElse(StringUtils.EMPTY);
... 1952 lines suppressed ...