diff --git a/dbrepo-metadata-service/pom.xml b/dbrepo-metadata-service/pom.xml
index 8d29d42c862d34bb6a129bde5348ef82057c8190..325514d848603f3984aeab03d7a5a3d784d5a5f5 100644
--- a/dbrepo-metadata-service/pom.xml
+++ b/dbrepo-metadata-service/pom.xml
@@ -63,7 +63,8 @@
         <mapstruct.version>1.5.5.Final</mapstruct.version>
         <rabbitmq.version>5.20.0</rabbitmq.version>
         <jackson-datatype.version>2.15.0</jackson-datatype.version>
-        <commons.version>2.11.0</commons.version>
+        <commons-io.version>2.15.0</commons-io.version>
+        <commons-validator.version>1.8.0</commons-validator.version>
         <guava.version>33.0.0-jre</guava.version>
         <jacoco.version>0.8.11</jacoco.version>
         <jwt.version>4.3.0</jwt.version>
@@ -238,7 +239,12 @@
         <dependency>
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
-            <version>${commons.version}</version>
+            <version>${commons-io.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-validator</groupId>
+            <artifactId>commons-validator</artifactId>
+            <version>${commons-validator.version}</version>
         </dependency>
         <!-- AMPQ -->
         <dependency>
diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java
index aac1e1c4ef266fed4be72521518fb5821acb084e..a6d9f56143ea208b62444e7366d6e473e17d5e2d 100644
--- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java
+++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java
@@ -37,6 +37,7 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
 import java.security.Principal;
+import java.time.Instant;
 import java.util.List;
 import java.util.UUID;
 import java.util.stream.Collectors;
@@ -163,6 +164,12 @@ public class IdentifierEndpoint {
             QueryStoreException, QueryNotFoundException, ImageNotSupportedException, UserNotFoundException,
             DatabaseConnectionException, RemoteUnavailableException {
         log.debug("endpoint create identifier, data={}, {}", data, PrincipalUtil.formatForDebug(principal));
+        /* check data */
+        if (!endpointValidator.validatePublicationDate(data)) {
+            log.error("Failed to create identifier: publication date is invalid");
+            throw new IdentifierRequestException("Failed to create identifier: publication date is invalid");
+        }
+        /* check access */
         DatabaseAccess access = null;
         try {
             access = accessService.find(data.getDatabaseId(), UserUtil.getId(principal));
@@ -172,6 +179,7 @@ public class IdentifierEndpoint {
                 throw new NotAllowedException("Failed to create identifier: insufficient role");
             }
         }
+        /* create identifier */
         final Database database = databaseService.find(data.getDatabaseId());
         switch (data.getType()) {
             case VIEW -> {
diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java
index 5fa79263ba6230f2a1dd54483325a28bf66b9faa..6d874dbc9c9849f05ce7b90b2450550078a34c45 100644
--- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java
+++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java
@@ -5,19 +5,19 @@ import at.tuwien.api.database.query.ExecuteStatementDto;
 import at.tuwien.api.database.table.TableCreateDto;
 import at.tuwien.api.database.table.columns.ColumnCreateDto;
 import at.tuwien.api.database.table.columns.ColumnTypeDto;
+import at.tuwien.api.identifier.IdentifierSaveDto;
 import at.tuwien.config.QueryConfig;
 import at.tuwien.entities.database.AccessType;
 import at.tuwien.entities.database.Database;
 import at.tuwien.entities.database.DatabaseAccess;
 import at.tuwien.entities.database.table.Table;
-import at.tuwien.entities.user.User;
 import at.tuwien.exception.*;
-import at.tuwien.repository.mdb.IdentifierRepository;
 import at.tuwien.service.AccessService;
 import at.tuwien.service.DatabaseService;
 import at.tuwien.service.TableService;
 import at.tuwien.utils.UserUtil;
 import lombok.extern.log4j.Log4j2;
+import org.apache.commons.validator.GenericValidator;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -321,4 +321,34 @@ public class EndpointValidator {
         throw new NotAllowedException("Access not allowed: no write access for table with id " + tableId);
     }
 
+    /**
+     * Precondition: identifier.getPublicationYear() is not null
+     *
+     * @param identifier The identifier that will be created.
+     * @return True if the publication date is valid, false otherwise.
+     */
+    public boolean validatePublicationDate(IdentifierSaveDto identifier) {
+        if (identifier.getPublicationMonth() != null && (identifier.getPublicationMonth() < 1 || identifier.getPublicationMonth() > 12)) {
+            log.trace("publication month {} needs to fulfill: 1 >= publicationMonth <= 12", identifier.getPublicationMonth());
+            return false;
+        }
+        if (identifier.getPublicationDay() != null && (identifier.getPublicationDay() < 1 || identifier.getPublicationDay() > 31)) {
+            log.trace("publication day {} needs to fulfill: 1 >= publicationDay <= 31", identifier.getPublicationDay());
+            return false;
+        }
+        if (identifier.getPublicationMonth() != null && identifier.getPublicationDay() != null) {
+            final String paddedMonth = identifier.getPublicationMonth() < 9 ? "0" + identifier.getPublicationMonth() : "" + identifier.getPublicationMonth();
+            final boolean result = GenericValidator.isDate(identifier.getPublicationYear() + "-" + paddedMonth + "-"
+                    + identifier.getPublicationDay(), "yyyy-MM-dd", true);
+            if (!result) {
+                log.trace("publication date {}-{}-{} needs to be valid", identifier.getPublicationYear(), paddedMonth,
+                        identifier.getPublicationDay());
+                return false;
+            }
+            return true;
+        }
+        log.trace("publication date is valid");
+        return true;
+    }
+
 }
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java
index 162b05a4e02eac8f2e15e412ab86fd75ca22ad8e..a937cf531c34b7bbb281972bbaf018c2592a7608 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java
@@ -7,6 +7,7 @@ import at.tuwien.annotations.MockOpensearch;
 import at.tuwien.api.database.table.TableCreateDto;
 import at.tuwien.api.database.table.columns.ColumnCreateDto;
 import at.tuwien.api.database.table.columns.ColumnTypeDto;
+import at.tuwien.api.identifier.IdentifierSaveDto;
 import at.tuwien.entities.database.table.Table;
 import at.tuwien.exception.*;
 import at.tuwien.repository.mdb.IdentifierRepository;
@@ -29,7 +30,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
 import java.util.List;
 import java.util.stream.Stream;
 
-import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.when;
 
@@ -46,9 +47,6 @@ public class EndpointValidatorUnitTest extends BaseUnitTest {
     @MockBean
     private AccessService accessService;
 
-    @MockBean
-    private IdentifierRepository identifierRepository;
-
     @MockBean
     private TableService tableService;
 
@@ -463,4 +461,136 @@ public class EndpointValidatorUnitTest extends BaseUnitTest {
         });
     }
 
+    @Test
+    public void validatePublicationDate_succeeds() {
+        final IdentifierSaveDto request = IdentifierSaveDto.builder()
+                .publicationYear(2024)
+                .publicationMonth(1)
+                .publicationDay(25)
+                .build();
+
+        /* test */
+        assertTrue(endpointValidator.validatePublicationDate(request));
+    }
+
+    @Test
+    public void validatePublicationDate_missingDay_succeeds() {
+        final IdentifierSaveDto request = IdentifierSaveDto.builder()
+                .publicationYear(2024)
+                .publicationMonth(1)
+                .build();
+
+        /* test */
+        assertTrue(endpointValidator.validatePublicationDate(request));
+    }
+
+    @Test
+    public void validatePublicationDate_missingMonth_succeeds() {
+        final IdentifierSaveDto request = IdentifierSaveDto.builder()
+                .publicationYear(2024)
+                .publicationDay(1)
+                .build();
+
+        /* test */
+        assertTrue(endpointValidator.validatePublicationDate(request));
+    }
+
+    @Test
+    public void validatePublicationDate_missingDayMonth_succeeds() {
+        final IdentifierSaveDto request = IdentifierSaveDto.builder()
+                .publicationYear(2024)
+                .build();
+
+        /* test */
+        assertTrue(endpointValidator.validatePublicationDate(request));
+    }
+
+    @Test
+    public void validatePublicationDate_yearEarly_succeeds() {
+        final IdentifierSaveDto request = IdentifierSaveDto.builder()
+                .publicationYear(1300)
+                .build();
+
+        /* test */
+        assertTrue(endpointValidator.validatePublicationDate(request));
+    }
+
+    @Test
+    public void validatePublicationDate_yearLate_succeeds() {
+        final IdentifierSaveDto request = IdentifierSaveDto.builder()
+                .publicationYear(12345)
+                .build();
+
+        /* test */
+        assertTrue(endpointValidator.validatePublicationDate(request));
+    }
+
+    @Test
+    public void validatePublicationDate_monthInvalid1_fails() {
+        final IdentifierSaveDto request = IdentifierSaveDto.builder()
+                .publicationYear(2024)
+                .publicationMonth(0)
+                .build();
+
+        /* test */
+        assertFalse(endpointValidator.validatePublicationDate(request));
+    }
+
+    @Test
+    public void validatePublicationDate_monthInvalid2_fails() {
+        final IdentifierSaveDto request = IdentifierSaveDto.builder()
+                .publicationYear(2024)
+                .publicationMonth(13)
+                .build();
+
+        /* test */
+        assertFalse(endpointValidator.validatePublicationDate(request));
+    }
+
+    @Test
+    public void validatePublicationDate_dayInvalid1_fails() {
+        final IdentifierSaveDto request = IdentifierSaveDto.builder()
+                .publicationYear(2024)
+                .publicationDay(0)
+                .build();
+
+        /* test */
+        assertFalse(endpointValidator.validatePublicationDate(request));
+    }
+
+    @Test
+    public void validatePublicationDate_dayInvalid2_fails() {
+        final IdentifierSaveDto request = IdentifierSaveDto.builder()
+                .publicationYear(2024)
+                .publicationDay(32)
+                .build();
+
+        /* test */
+        assertFalse(endpointValidator.validatePublicationDate(request));
+    }
+
+    @Test
+    public void validatePublicationDate_february29Invalid_fails() {
+        final IdentifierSaveDto request = IdentifierSaveDto.builder()
+                .publicationYear(2023)
+                .publicationMonth(2)
+                .publicationDay(29)
+                .build();
+
+        /* test */
+        assertFalse(endpointValidator.validatePublicationDate(request));
+    }
+
+    @Test
+    public void validatePublicationDate_february29_succeeds() {
+        final IdentifierSaveDto request = IdentifierSaveDto.builder()
+                .publicationYear(2024)
+                .publicationMonth(2)
+                .publicationDay(29)
+                .build();
+
+        /* test */
+        assertTrue(endpointValidator.validatePublicationDate(request));
+    }
+
 }
diff --git a/dbrepo-metadata-service/rest-service/src/test/resources/application.properties b/dbrepo-metadata-service/rest-service/src/test/resources/application.properties
index 0c0fab40c34a920f03a7c48022a4b0bfe4c8de0c..70e4aa0fa0d92a2d9b4ea17aff55a2f104ef50ea 100644
--- a/dbrepo-metadata-service/rest-service/src/test/resources/application.properties
+++ b/dbrepo-metadata-service/rest-service/src/test/resources/application.properties
@@ -17,6 +17,7 @@ spring.jpa.hibernate.ddl-auto=create
 # logging
 logging.level.root=error
 logging.level.at.tuwien.=debug
+logging.level.at.tuwien.validation.=trace
 
 # rabbitmq
 spring.rabbitmq.host=localhost
diff --git a/dbrepo-ui/components/identifier/Persist.vue b/dbrepo-ui/components/identifier/Persist.vue
index e95f644bde687eebe789c19652f5873f2dd946ed..869ac3c5fc5550585693d1b198b4d3e67244b554 100644
--- a/dbrepo-ui/components/identifier/Persist.vue
+++ b/dbrepo-ui/components/identifier/Persist.vue
@@ -13,7 +13,7 @@
           v-if="!isUpdate"
           class="mb-1"
           :loading="loading"
-          :disabled="!formValid || loading"
+          :disabled="!formValid || !validPublicationMonth || !validPublicationDay || loading"
           color="primary"
           @click="save">
           <v-icon left>mdi-content-save-outline</v-icon> Create PID
@@ -286,6 +286,7 @@
                 v-model.number="identifier.publication_day"
                 type="number"
                 label="Publication day"
+                :rules="[validPublicationDay || $t('Invalid day')]"
                 clearable />
             </v-col>
             <v-col cols="2">
@@ -294,6 +295,7 @@
                 v-model.number="identifier.publication_month"
                 type="number"
                 label="Publication month"
+                :rules="[validPublicationMonth || $t('Invalid month')]"
                 clearable />
             </v-col>
             <v-col cols="2">
@@ -649,6 +651,20 @@ export default {
         return 'Table'
       }
       return ''
+    },
+    validPublicationDay () {
+      const day = this.identifier.publication_day
+      if (day === null) {
+        return true
+      }
+      return day >= 1 && day <= 31
+    },
+    validPublicationMonth () {
+      const month = this.identifier.publication_month
+      if (month === null) {
+        return true
+      }
+      return month >= 1 && month <= 12
     }
   },
   watch: {
diff --git a/dbrepo-ui/components/identifier/Summary.vue b/dbrepo-ui/components/identifier/Summary.vue
index e4fe690432a41cd59f84b4f3880907839787214e..a9f16bd347cc5889067dc274369868520d5fdfcd 100644
--- a/dbrepo-ui/components/identifier/Summary.vue
+++ b/dbrepo-ui/components/identifier/Summary.vue
@@ -97,7 +97,7 @@ import IsniIcon from '@/components/icons/IsniIcon.vue'
 import OrcidIcon from '@/components/icons/OrcidIcon.vue'
 import RorIcon from '@/components/icons/RorIcon.vue'
 import Banner from '@/components/identifier/Banner.vue'
-import { formatDateUTC, formatLanguage } from '@/utils'
+import { formatLanguage } from '@/utils'
 
 export default {
   components: {
@@ -167,7 +167,9 @@ export default {
       if (this.identifier.publication_year && !this.identifier.publication_month && !this.identifier.publication_day) {
         return this.identifier.publication_year
       } else if (this.identifier.publication_year && this.identifier.publication_month && this.identifier.publication_day) {
-        return formatDateUTC(this.identifier.publication_year + '-' + this.identifier.publication_month + '-' + this.identifier.publication_day)
+        const month = this.identifier.publication_month
+        const day = this.identifier.publication_day
+        return `${this.identifier.publication_year}-${month < 9 ? '0' + month : month}-${day < 9 ? '0' + day : day}`
       } else {
         return null
       }
diff --git a/dbrepo-ui/dbrepo.config.json b/dbrepo-ui/dbrepo.config.json
index 24ddb9e90f225cc0f8091747c7130d622c4ef3e5..3ec6309002a75fe1bc2a424d5185175db12109b1 100644
--- a/dbrepo-ui/dbrepo.config.json
+++ b/dbrepo-ui/dbrepo.config.json
@@ -1,6 +1,6 @@
 {
   "title": "Database Repository",
-  "version": "1.4.0",
+  "version": "1.4.1",
   "ssl": {
     "force": false
   },