Skip to content

Commit fb70034

Browse files
Merge pull request #62 from iron-software/automate-merge-code
Copy from IronPolyglot on 2025-07-24
2 parents 232f5ba + fbf2245 commit fb70034

File tree

12 files changed

+181
-44
lines changed

12 files changed

+181
-44
lines changed

IronPdf.SmokeTests/src/test/java/com/ironsoftware/ironpdf/MetadataTests.java

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import org.junit.jupiter.api.Assertions;
55
import org.junit.jupiter.api.Test;
66

7+
import java.time.LocalDateTime;
8+
import java.time.ZoneOffset;
9+
import java.time.OffsetDateTime;
710
import java.io.IOException;
811

912
public class MetadataTests extends TestBase {
@@ -15,37 +18,41 @@ public final void GetSetMetadataTest() throws IOException {
1518
MetadataManager metadataManager = doc.getMetadata();
1619

1720
AssertNullOrEmpty(metadataManager.getAuthor());
18-
AssertNotNullOrEmpty(metadataManager.getCreationDate());
21+
Assertions.assertNotNull(metadataManager.getCreationDate());
1922
Assertions.assertEquals("PDFium", metadataManager.getCreator());
2023
AssertNullOrEmpty(metadataManager.getKeywords());
2124
AssertNullOrEmpty(metadataManager.getAnyMetadata("Custom"));
22-
// TODO Uncomment below after fixed
23-
// AssertNullOrEmpty(metadataManager.getModifiedDate());
25+
// comment this because modified date return empty string.
26+
//Assertions.assertNotNull(metadataManager.getModifiedDate());
2427
AssertNullOrEmpty(metadataManager.getProducer());
2528
AssertNullOrEmpty(metadataManager.getSubject());
2629
AssertNullOrEmpty(metadataManager.getTitle());
2730

31+
// Create a OffsetDateTime for July 23, 2025, at 10:30 AM in the +07:00 timezone.
32+
OffsetDateTime date = OffsetDateTime.of(
33+
LocalDateTime.of(2025, 7, 23, 10, 30, 0),
34+
ZoneOffset.ofHours(7)
35+
);
36+
2837
metadataManager.setAuthor("1");
29-
metadataManager.setCreationDate("1");
38+
metadataManager.setCreationDate(date);
3039
metadataManager.setCreator("1");
3140
metadataManager.setKeywords("1");
3241
metadataManager.setAnyMetadata("Custom", "1");
33-
metadataManager.setModifiedDate("1");
42+
metadataManager.setModifiedDate(date);
3443
metadataManager.setProducer("1");
3544
metadataManager.setSubject("1");
3645
metadataManager.setTitle("1");
3746

3847
Assertions.assertEquals("1", metadataManager.getAuthor());
39-
Assertions.assertEquals("1", metadataManager.getCreationDate());
48+
Assertions.assertEquals(date, metadataManager.getCreationDate());
4049
Assertions.assertEquals("1", metadataManager.getCreator());
4150
Assertions.assertEquals("1", metadataManager.getKeywords());
4251
Assertions.assertEquals("1", metadataManager.getAnyMetadata("Custom"));
43-
// TODO Uncomment below after fixed
44-
// Assertions.assertEquals("1", metadataManager.getModifiedDate());
52+
Assertions.assertEquals(date, metadataManager.getModifiedDate());
4553
Assertions.assertEquals("1", metadataManager.getProducer());
4654
Assertions.assertEquals("1", metadataManager.getSubject());
4755
Assertions.assertEquals("1", metadataManager.getAuthor());
4856
Assertions.assertEquals("1", metadataManager.getTitle());
4957
}
50-
5158
}

ironpdf-cloud/patch/src/main/java/com/ironsoftware/ironpdf/internal/staticapi/Setting_Api.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public final class Setting_Api {
1919

2020
public static IronPdfEngineConnection connectionMode = IronPdfEngineConnection.configure().withOfficialCloud();
2121

22-
public static final String IRON_PDF_ENGINE_VERSION = "2025.6.5";
22+
public static final String IRON_PDF_ENGINE_VERSION = "2025.7.17";
2323

2424
public static int ironPdfEngineTimeout = 120;
2525

ironpdf-engine-pack/ironpdf-engine-linux-x64/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
<maven.compiler.source>8</maven.compiler.source>
108108
<maven.compiler.target>8</maven.compiler.target>
109109
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
110-
<ironpdf.engine.version>2025.6.5</ironpdf.engine.version>
110+
<ironpdf.engine.version>2025.7.17</ironpdf.engine.version>
111111
</properties>
112112

113113
<build>

ironpdf-engine-pack/ironpdf-engine-macos-arm64/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
<maven.compiler.source>8</maven.compiler.source>
108108
<maven.compiler.target>8</maven.compiler.target>
109109
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
110-
<ironpdf.engine.version>2025.6.5</ironpdf.engine.version>
110+
<ironpdf.engine.version>2025.7.17</ironpdf.engine.version>
111111
</properties>
112112

113113
<build>

ironpdf-engine-pack/ironpdf-engine-macos-x64/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
<maven.compiler.source>8</maven.compiler.source>
108108
<maven.compiler.target>8</maven.compiler.target>
109109
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
110-
<ironpdf.engine.version>2025.6.5</ironpdf.engine.version>
110+
<ironpdf.engine.version>2025.7.17</ironpdf.engine.version>
111111
</properties>
112112

113113
<build>

ironpdf-engine-pack/ironpdf-engine-windows-x64/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
<maven.compiler.source>8</maven.compiler.source>
108108
<maven.compiler.target>8</maven.compiler.target>
109109
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
110-
<ironpdf.engine.version>2025.6.5</ironpdf.engine.version>
110+
<ironpdf.engine.version>2025.7.17</ironpdf.engine.version>
111111
</properties>
112112

113113
<build>

ironpdf-engine-pack/ironpdf-engine-windows-x86/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
<maven.compiler.source>8</maven.compiler.source>
108108
<maven.compiler.target>8</maven.compiler.target>
109109
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
110-
<ironpdf.engine.version>2025.6.5</ironpdf.engine.version>
110+
<ironpdf.engine.version>2025.7.17</ironpdf.engine.version>
111111
</properties>
112112

113113
<build>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
package com.ironsoftware.ironpdf.internal.staticapi;
22
class BuildInfo {
3-
static final String BUILD_TIMESTAMP = "07/09/2025";
3+
static final String BUILD_TIMESTAMP = "10/16/2024";
44
}

ironpdf/src/main/java/com/ironsoftware/ironpdf/internal/staticapi/Setting_Api.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public final class Setting_Api {
1919

2020
public static IronPdfEngineConnection connectionMode = IronPdfEngineConnection.configure().withSubprocess();
2121

22-
public static final String IRON_PDF_ENGINE_VERSION = "2025.6.5";
22+
public static final String IRON_PDF_ENGINE_VERSION = "2025.7.17";
2323

2424
public static int ironPdfEngineTimeout = 120;
2525

ironpdf/src/main/java/com/ironsoftware/ironpdf/metadata/MetadataManager.java

Lines changed: 114 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
import com.ironsoftware.ironpdf.internal.staticapi.InternalPdfDocument;
55
import com.ironsoftware.ironpdf.internal.staticapi.Metadata_Api;
66

7+
import java.time.OffsetDateTime;
8+
import java.time.ZoneOffset;
9+
import java.time.format.DateTimeFormatter;
10+
import java.time.format.DateTimeFormatterBuilder;
11+
import java.time.temporal.ChronoField;
712
/**
813
* Class used to read and edit MetaData in a {@link com.ironsoftware.ironpdf.PdfDocument}.
914
* <p> See: {@link com.ironsoftware.ironpdf.PdfDocument#getMetadata()} </p>
@@ -63,39 +68,59 @@ public void setAnyMetadata(String key, String value) {
6368
/**
6469
* Gets the PDF file creation DateTime.
6570
*
66-
* @return the creation date
71+
* @return the creation date as OffsetDateTime object.
6772
*/
68-
public String getCreationDate() {
69-
return getAnyMetadata("CreationDate");
73+
public OffsetDateTime getCreationDate() {
74+
return ConvertPdfDateFormatStringToOffsetDateTime(getAnyMetadata("CreationDate"));
7075
}
7176

7277
/**
73-
* Sets the PDF file creation DateTime.
74-
*
75-
* @param value the value
78+
* @deprecated As of version 2025.7.17, replaced by {@link #setCreationDate()}.
79+
* This method will be removed in a future release. Please use the new
80+
* method to provide an OffsetDateTime object instead of a String.
7681
*/
82+
@Deprecated
7783
public void setCreationDate(String value) {
7884
setAnyMetadata("CreationDate", value);
7985
}
8086

8187
/**
82-
* Gets the PDF file last-modified DateTime.
88+
* Sets the PDF file creation DateTime.
8389
*
84-
* @return the modified date
90+
* @param value the DateTime value.
8591
*/
86-
public String setModifiedDate() {
87-
return getAnyMetadata("ModDate");
92+
public void setCreationDate(OffsetDateTime value) {
93+
setAnyMetadata("CreationDate", ConvertOffsetDateTimeToPdfDateFormat(value, "yyyyMMddHHmmss"));
8894
}
8995

9096
/**
91-
* Sets the PDF file last-modified DateTime.
97+
* Gets the PDF file last-modified DateTime.
9298
*
93-
* @param value the value
99+
* @return the modified date as OffsetDateTime object.
100+
*/
101+
public OffsetDateTime getModifiedDate() {
102+
return ConvertPdfDateFormatStringToOffsetDateTime(getAnyMetadata("ModDate"));
103+
}
104+
105+
/**
106+
* @deprecated As of version 2025.7.17, replaced by {@link #setModifiedDate()}.
107+
* This method will be removed in a future release. Please use the new
108+
* method to provide an OffsetDateTime object instead of a String.
94109
*/
110+
@Deprecated
95111
public void setModifiedDate(String value) {
96112
setAnyMetadata("ModDate", value);
97113
}
98114

115+
/**
116+
* Sets the PDF file last-modified DateTime.
117+
*
118+
* @param value the DateTime value.
119+
*/
120+
public void setModifiedDate(OffsetDateTime value) {
121+
setAnyMetadata("ModDate", ConvertOffsetDateTimeToPdfDateFormat(value, "yyyyMMddHHmmss"));
122+
}
123+
99124
/**
100125
* Gets the Creator of the document.
101126
*
@@ -192,6 +217,82 @@ public void setTitle(String value) {
192217
setAnyMetadata("Title", value);
193218
}
194219

220+
/**
221+
* Convert a OffsetDateTime object to date format defined in the PDF specification (ISO 32000).
222+
* Returns date and time formatted according to the PDF specification as String:
223+
* "D:YYYYMMDDHHMMSS+TZ", where the timezone offset is expressed as "+HH'mm'".
224+
*
225+
* Example output: "D:20250627162947+06'00'"
226+
*
227+
* @param dateTime the date value as OffsetDateTime object.
228+
* @param pattern the pattern value of DateTimeFormatter as String.
229+
*/
230+
private String ConvertOffsetDateTimeToPdfDateFormat(OffsetDateTime dateTime, String pattern) {
231+
if (dateTime == null) {
232+
return "";
233+
}
234+
235+
// 1. Format the date and time part without the offset.
236+
DateTimeFormatter baseFormatter = DateTimeFormatter.ofPattern(pattern);
237+
String dateTimePart = dateTime.format(baseFormatter);
238+
239+
// 2. Get the offset from the dateTime object.
240+
ZoneOffset offset = dateTime.getOffset();
241+
String offsetPart;
242+
243+
// 3. Manually format the offset. The PDF specification requires 'Z' for UTC.
244+
if (offset.getTotalSeconds() == 0) {
245+
offsetPart = "Z";
246+
} else {
247+
// For all other offsets, build the +HH'mm' string.
248+
int totalSeconds = offset.getTotalSeconds();
249+
// Calculate hours and minutes from the total seconds.
250+
long hours = totalSeconds / 3600;
251+
long minutes = (Math.abs(totalSeconds) / 60) % 60;
252+
// Format to the required pattern, e.g., +06'00' or -05'00'.
253+
offsetPart = String.format("%+03d'%02d'", hours, minutes);
254+
}
255+
256+
// 4. Combine the parts with the 'D:' prefix.
257+
return "D:" + dateTimePart + offsetPart;
258+
}
259+
260+
/**
261+
* Convert a date format String defined in the PDF specification (ISO 32000)
262+
* to a OffsetDateTime object. The method can parse formats like
263+
* "D:YYYYMMDDHHMMSS+TZ", where the timezone offset is expressed as "+HH'mm'".
264+
*
265+
* @param dateTime The date string from the PDF, e.g., "D:20250627162947+06'00'".
266+
*/
267+
private OffsetDateTime ConvertPdfDateFormatStringToOffsetDateTime(String dateTime) {
268+
if (dateTime == null || dateTime.isEmpty()) {
269+
return null;
270+
}
271+
272+
String parsableDateTime = dateTime;
273+
if (parsableDateTime.startsWith("D:")) {
274+
parsableDateTime = parsableDateTime.substring(2);
275+
}
276+
277+
// Simply remove apostrophes to convert non-standard +07'00' into standard +0700
278+
parsableDateTime = parsableDateTime.replace("'", "");
279+
280+
// Build a single, flexible formatter that can handle inputs with or without an offset
281+
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
282+
.appendPattern("yyyyMMddHHmmss")
283+
// Make the offset section optional
284+
.optionalStart()
285+
// The 'X' pattern handles offsets like 'Z' or '+0700'
286+
.appendPattern("X")
287+
.optionalEnd()
288+
// If the optional offset was not found, default to UTC
289+
.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
290+
.toFormatter();
291+
292+
// Parse the cleaned string directly to an OffsetDateTime
293+
return OffsetDateTime.parse(parsableDateTime, formatter);
294+
}
295+
195296
/**
196297
* Method for removing Metadata property by its name.
197298
*
@@ -200,5 +301,4 @@ public void setTitle(String value) {
200301
public void removeMetadata(String key) {
201302
Metadata_Api.removeMetadata(static_pdfDocument, key);
202303
}
203-
204-
}
304+
}

0 commit comments

Comments
 (0)