refactor(core,common,proprietary): Replace Date with Instant/modern Date API alternative for improved time handling (#4497)

This commit is contained in:
Balázs Szücs
2025-09-28 17:41:20 +02:00
committed by GitHub
parent 07392ed25e
commit 133e6d3de6
21 changed files with 244 additions and 125 deletions

View File

@@ -7,16 +7,18 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TimeZone;
import org.apache.commons.io.FileUtils;
import org.apache.pdfbox.Loader;
@@ -564,18 +566,31 @@ public class ConvertPDFToPDFA {
adobePdfSchema.setKeywords(keywords);
}
// Set creation and modification dates
Calendar now = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Calendar originalCreationDate = docInfo.getCreationDate();
if (originalCreationDate == null) {
originalCreationDate = now;
}
docInfo.setCreationDate(originalCreationDate);
xmpBasicSchema.setCreateDate(originalCreationDate);
// Set creation and modification dates using java.time and convert to GregorianCalendar
Instant nowInstant = Instant.now();
ZonedDateTime nowZdt = ZonedDateTime.ofInstant(nowInstant, ZoneId.of("UTC"));
GregorianCalendar nowCal = GregorianCalendar.from(nowZdt);
docInfo.setModificationDate(now);
xmpBasicSchema.setModifyDate(now);
xmpBasicSchema.setMetadataDate(now);
java.util.Calendar originalCreationDate = docInfo.getCreationDate();
GregorianCalendar creationCal;
if (originalCreationDate == null) {
creationCal = nowCal;
} else if (originalCreationDate instanceof GregorianCalendar) {
creationCal = (GregorianCalendar) originalCreationDate;
} else {
// convert other Calendar implementations to GregorianCalendar preserving instant
creationCal =
GregorianCalendar.from(
ZonedDateTime.ofInstant(
originalCreationDate.toInstant(), ZoneId.of("UTC")));
}
docInfo.setCreationDate(creationCal);
xmpBasicSchema.setCreateDate(creationCal);
docInfo.setModificationDate(nowCal);
xmpBasicSchema.setModifyDate(nowCal);
xmpBasicSchema.setMetadataDate(nowCal);
// Serialize the created metadata so it can be attached to the existent metadata
ByteArrayOutputStream xmpOut = new ByteArrayOutputStream();

View File

@@ -1,8 +1,6 @@
package stirling.software.SPDF.controller.api.misc;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Map;
import java.util.Map.Entry;
@@ -25,6 +23,7 @@ import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.misc.MetadataRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.service.PdfMetadataService;
import stirling.software.common.util.WebResponseUtils;
import stirling.software.common.util.propertyeditor.StringToMapPropertyEditor;
@@ -144,30 +143,13 @@ public class MetadataController {
}
}
}
if (creationDate != null && creationDate.length() > 0) {
Calendar creationDateCal = Calendar.getInstance();
try {
creationDateCal.setTime(
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(creationDate));
} catch (ParseException e) {
log.error("exception", e);
}
info.setCreationDate(creationDateCal);
} else {
info.setCreationDate(null);
}
if (modificationDate != null && modificationDate.length() > 0) {
Calendar modificationDateCal = Calendar.getInstance();
try {
modificationDateCal.setTime(
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(modificationDate));
} catch (ParseException e) {
log.error("exception", e);
}
info.setModificationDate(modificationDateCal);
} else {
info.setModificationDate(null);
}
// Set creation date using utility method
Calendar creationDateCal = PdfMetadataService.parseToCalendar(creationDate);
info.setCreationDate(creationDateCal);
// Set modification date using utility method
Calendar modificationDateCal = PdfMetadataService.parseToCalendar(modificationDate);
info.setModificationDate(modificationDateCal);
info.setCreator(creator);
info.setKeywords(keywords);
info.setAuthor(author);

View File

@@ -120,7 +120,7 @@ public class CertSignController {
signature.setName(name);
signature.setLocation(location);
signature.setReason(reason);
signature.setSignDate(Calendar.getInstance());
signature.setSignDate(Calendar.getInstance()); // PDFBox requires Calendar
if (Boolean.TRUE.equals(showSignature)) {
SignatureOptions signatureOptions = new SignatureOptions();
signatureOptions.setVisualSignature(

View File

@@ -3,7 +3,9 @@ package stirling.software.SPDF.controller.api.security;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import org.apache.pdfbox.cos.COSInputStream;
@@ -817,8 +819,10 @@ public class GetInfoOnPDF {
private String formatDate(Calendar calendar) {
if (calendar != null) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(calendar.getTime());
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
ZonedDateTime zonedDateTime =
ZonedDateTime.ofInstant(calendar.toInstant(), ZoneId.systemDefault());
return zonedDateTime.format(formatter);
} else {
return null;
}

View File

@@ -7,8 +7,8 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.pdfbox.pdmodel.PDDocument;
@@ -134,11 +134,12 @@ public class ValidateSignatureController {
: certValidationService.validateTrustStore(cert));
result.setNotRevoked(!certValidationService.isRevoked(cert));
result.setNotExpired(!cert.getNotAfter().before(new Date()));
result.setNotExpired(
Instant.now().isBefore(cert.getNotAfter().toInstant()));
// Set basic signature info
result.setSignerName(sig.getName());
result.setSignatureDate(sig.getSignDate().getTime().toString());
result.setSignatureDate(sig.getSignDate().toInstant().toString());
result.setReason(sig.getReason());
result.setLocation(sig.getLocation());

View File

@@ -3,6 +3,9 @@ package stirling.software.SPDF.service;
import static stirling.software.common.util.AttachmentUtils.setCatalogViewerPreferences;
import java.io.IOException;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
@@ -54,8 +57,13 @@ public class AttachmentService implements AttachmentServiceInterface {
PDEmbeddedFile embeddedFile =
new PDEmbeddedFile(document, attachment.getInputStream());
embeddedFile.setSize((int) attachment.getSize());
embeddedFile.setCreationDate(new GregorianCalendar());
embeddedFile.setModDate(new GregorianCalendar());
// use java.time.Instant and convert to GregorianCalendar for PDFBox
Instant now = Instant.now();
GregorianCalendar nowCal =
GregorianCalendar.from(
ZonedDateTime.ofInstant(now, ZoneId.systemDefault()));
embeddedFile.setCreationDate(nowCal);
embeddedFile.setModDate(nowCal);
String contentType = attachment.getContentType();
if (StringUtils.isNotBlank(contentType)) {
embeddedFile.setSubtype(contentType);

View File

@@ -7,6 +7,8 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import org.apache.pdfbox.pdmodel.PDDocument;
@@ -81,6 +83,12 @@ class PdfMetadataServiceBasicTest {
// Act
PdfMetadata metadata = pdfMetadataService.extractMetadataFromPdf(testDocument);
// Convert Calendar to ZonedDateTime for comparison
ZonedDateTime expectedCreationDate =
ZonedDateTime.ofInstant(creationDate.toInstant(), ZoneId.systemDefault());
ZonedDateTime expectedModificationDate =
ZonedDateTime.ofInstant(modificationDate.toInstant(), ZoneId.systemDefault());
// Assert
assertEquals(testAuthor, metadata.getAuthor(), "Author should match");
assertEquals(testProducer, metadata.getProducer(), "Producer should match");
@@ -88,9 +96,12 @@ class PdfMetadataServiceBasicTest {
assertEquals(testCreator, metadata.getCreator(), "Creator should match");
assertEquals(testSubject, metadata.getSubject(), "Subject should match");
assertEquals(testKeywords, metadata.getKeywords(), "Keywords should match");
assertEquals(creationDate, metadata.getCreationDate(), "Creation date should match");
assertEquals(
modificationDate, metadata.getModificationDate(), "Modification date should match");
expectedCreationDate, metadata.getCreationDate(), "Creation date should match");
assertEquals(
expectedModificationDate,
metadata.getModificationDate(),
"Modification date should match");
}
@Test

View File

@@ -7,6 +7,8 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import org.apache.pdfbox.pdmodel.PDDocument;
@@ -84,6 +86,12 @@ class PdfMetadataServiceTest {
// Act
PdfMetadata metadata = pdfMetadataService.extractMetadataFromPdf(testDocument);
// Convert Calendar to ZonedDateTime for comparison
ZonedDateTime expectedCreationDate =
ZonedDateTime.ofInstant(creationDate.toInstant(), ZoneId.systemDefault());
ZonedDateTime expectedModificationDate =
ZonedDateTime.ofInstant(modificationDate.toInstant(), ZoneId.systemDefault());
// Assert
assertEquals(testAuthor, metadata.getAuthor(), "Author should match");
assertEquals(testProducer, metadata.getProducer(), "Producer should match");
@@ -91,9 +99,12 @@ class PdfMetadataServiceTest {
assertEquals(testCreator, metadata.getCreator(), "Creator should match");
assertEquals(testSubject, metadata.getSubject(), "Subject should match");
assertEquals(testKeywords, metadata.getKeywords(), "Keywords should match");
assertEquals(creationDate, metadata.getCreationDate(), "Creation date should match");
assertEquals(
modificationDate, metadata.getModificationDate(), "Modification date should match");
expectedCreationDate, metadata.getCreationDate(), "Creation date should match");
assertEquals(
expectedModificationDate,
metadata.getModificationDate(),
"Modification date should match");
}
@Test
@@ -190,6 +201,8 @@ class PdfMetadataServiceTest {
// Prepare test metadata with existing creation date
Calendar existingCreationDate = Calendar.getInstance();
existingCreationDate.add(Calendar.DAY_OF_MONTH, -1); // Yesterday
ZonedDateTime existingCreationDateZdt =
ZonedDateTime.ofInstant(existingCreationDate.toInstant(), ZoneId.systemDefault());
PdfMetadata testMetadata =
PdfMetadata.builder()
@@ -197,7 +210,7 @@ class PdfMetadataServiceTest {
.title("Test Title")
.subject("Test Subject")
.keywords("Test Keywords")
.creationDate(existingCreationDate)
.creationDate(existingCreationDateZdt)
.build();
// Act