Skip to content

Commit 5eecbc8

Browse files
author
TheSnoozer
committed
#674: parse 'project.build.outputTimestamp' formatted as ISO 8601
1 parent e7ec732 commit 5eecbc8

File tree

2 files changed

+148
-13
lines changed

2 files changed

+148
-13
lines changed

src/main/java/pl/project13/maven/git/GitCommitIdMojo.java

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@
2121
import java.io.File;
2222
import java.nio.charset.Charset;
2323
import java.nio.charset.StandardCharsets;
24-
import java.text.DateFormat;
25-
import java.text.ParseException;
2624
import java.text.SimpleDateFormat;
25+
import java.time.Instant;
2726
import java.util.Collections;
2827
import java.util.Date;
2928
import java.util.List;
@@ -33,6 +32,7 @@
3332
import java.util.function.Supplier;
3433
import javax.annotation.Nonnull;
3534
import javax.annotation.Nullable;
35+
import com.google.common.annotations.VisibleForTesting;
3636
import org.apache.maven.execution.MavenSession;
3737
import org.apache.maven.plugin.AbstractMojo;
3838
import org.apache.maven.plugin.MojoExecution;
@@ -44,6 +44,7 @@
4444
import org.apache.maven.plugins.annotations.Parameter;
4545
import org.apache.maven.project.MavenProject;
4646
import org.apache.maven.settings.Settings;
47+
import org.joda.time.DateTime;
4748
import org.sonatype.plexus.build.incremental.BuildContext;
4849
import pl.project13.core.CommitIdGenerationMode;
4950
import pl.project13.core.CommitIdPropertiesOutputFormat;
@@ -1442,32 +1443,26 @@ private Properties getContextProperties(MavenProject project) {
14421443
* href="https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>.
14431444
*
14441445
* <p>Inspired by
1445-
* https://github.com/apache/maven-archiver/blob/a3103d99396cd8d3440b907ef932a33563225265/src/main/java/org/apache/maven/archiver/MavenArchiver.java#L765
1446+
* https://github.com/apache/maven-archiver/blob/7acb1db4a9754beacde3f21a69e5523ee901abd5/src/main/java/org/apache/maven/archiver/MavenArchiver.java#L755
14461447
*
14471448
* @param outputTimestamp the value of <code>${project.build.outputTimestamp}</code> (may be
14481449
* <code>null</code>)
14491450
* @return the parsed timestamp, may be <code>null</code> if <code>null</code> input or input
14501451
* contains only 1 character
14511452
*/
1452-
private Date parseOutputTimestamp(String outputTimestamp) throws GitCommitIdExecutionException {
1453+
@VisibleForTesting
1454+
protected static Date parseOutputTimestamp(String outputTimestamp) {
14531455
if (outputTimestamp != null
14541456
&& !outputTimestamp.trim().isEmpty()
14551457
&& outputTimestamp.chars().allMatch(Character::isDigit)) {
1456-
return new Date(Long.parseLong(outputTimestamp) * 1000);
1458+
return Date.from(Instant.ofEpochSecond(Long.parseLong(outputTimestamp)));
14571459
}
14581460

14591461
if ((outputTimestamp == null) || (outputTimestamp.length() < 2)) {
14601462
// no timestamp configured
14611463
return null;
14621464
}
1463-
1464-
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
1465-
try {
1466-
return df.parse(outputTimestamp);
1467-
} catch (ParseException pe) {
1468-
throw new GitCommitIdExecutionException(
1469-
"Invalid 'project.build.outputTimestamp' value '" + outputTimestamp + "'", pe);
1470-
}
1465+
return new DateTime(outputTimestamp).toDate();
14711466
}
14721467

14731468
private void publishPropertiesInto(Properties propertiesToPublish, Properties propertiesTarget) {

src/test/java/pl/project13/maven/git/GitCommitIdMojoTest.java

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,19 @@
2222

2323
import java.io.File;
2424
import java.io.IOException;
25+
import java.time.Instant;
26+
import java.util.Date;
27+
28+
import junitparams.JUnitParamsRunner;
29+
import junitparams.Parameters;
2530
import org.junit.Test;
31+
import org.junit.runner.RunWith;
2632
import pl.project13.core.PropertiesFileGenerator;
2733

2834
/**
2935
* Testcases to verify that the git-commit-id works properly.
3036
*/
37+
@RunWith(JUnitParamsRunner.class)
3138
public class GitCommitIdMojoTest {
3239
@Test
3340
public void testCraftPropertiesOutputFileWithRelativePath() throws IOException {
@@ -66,4 +73,137 @@ public void testCraftPropertiesOutputFileWithFullPath() throws IOException {
6673
.toFile()
6774
.getCanonicalPath());
6875
}
76+
77+
private Object[] parametersParseOutputTimestamp() {
78+
return new Object[] {
79+
// long since epoch
80+
new Object[] {
81+
"1644689403",
82+
Instant.ofEpochMilli(1644689403000L)
83+
},
84+
// Date only:
85+
new Object[] {
86+
"2022-02",
87+
Instant.ofEpochMilli(1643670000000L)
88+
},
89+
new Object[] {
90+
"2022-02-12",
91+
Instant.ofEpochMilli(1644620400000L)
92+
},
93+
// Date and time:
94+
new Object[] {
95+
"2022-02-12T15:30",
96+
Instant.ofEpochMilli(1644676200000L)
97+
},
98+
new Object[] {
99+
"2022-02-12T15:30:45",
100+
Instant.ofEpochMilli(1644676245000L)
101+
},
102+
// Date and time with timezone:
103+
new Object[] {
104+
"2022-02-12T15:30+00:00",
105+
Instant.ofEpochMilli(1644679800000L)
106+
},
107+
new Object[] {
108+
"2022-02-12T15:30:45-05:00",
109+
Instant.ofEpochMilli(1644697845000L)
110+
},
111+
new Object[] {
112+
"2022-02-12T15:30:00+00:00",
113+
Instant.ofEpochMilli(1644679800000L)
114+
},
115+
new Object[] {
116+
"2023-11-30T09:17:06+05:30",
117+
Instant.ofEpochMilli(1701316026000L)
118+
},
119+
new Object[] {
120+
"2024-08-15T20:45:30-03:00",
121+
Instant.ofEpochMilli(1723765530000L)
122+
},
123+
new Object[] {
124+
"2022-02-12T15:30:00Z",
125+
Instant.ofEpochMilli(1644679800000L)
126+
},
127+
// Not valid according to the ISO 8601 standard. The issue is with the time zone
128+
// representation. ISO 8601 uses a specific format for time zones, either as "Z" for UTC or
129+
// in the format "+HH:MM" or "-HH:MM" for the offset from UTC.
130+
// The time zone "EST" or "PST" does not follow this format.
131+
// new Object[] { "2023-11-30T09:17:06PST", null },
132+
// new Object[] { "2024-08-15T20:45:30EST", null },
133+
new Object[] {
134+
"2023-11-30T09:17:06+0100",
135+
Instant.ofEpochMilli(1701332226000L)
136+
},
137+
// Week date:
138+
new Object[] {
139+
"2022-W06",
140+
Instant.ofEpochMilli(1644188400000L)
141+
},
142+
new Object[] {
143+
"2022-W06-5",
144+
Instant.ofEpochMilli(1644534000000L)
145+
},
146+
// Week date with time:
147+
new Object[] {
148+
"2022-W06-5T15:30",
149+
Instant.ofEpochMilli(1644589800000L)
150+
},
151+
new Object[] {
152+
"2022-W06-5T15:30:45",
153+
Instant.ofEpochMilli(1644589845000L)
154+
},
155+
// https://tc39.es/proposal-uniform-interchange-date-parsing/cases.html
156+
// positive leap second
157+
// not working: new Object[] { "1972-06-30T23:59:60Z", null },
158+
// Too few fractional second digits
159+
new Object[] {
160+
"2019-03-26T14:00:00.9Z",
161+
Instant.ofEpochMilli(1553608800900L)
162+
},
163+
// Too many fractional second digits
164+
new Object[] {
165+
"2019-03-26T14:00:00.4999Z",
166+
Instant.ofEpochMilli(1553608800499L)
167+
},
168+
// Too many fractional second digits (pre-epoch)
169+
new Object[] {
170+
"1969-03-26T14:00:00.4999Z",
171+
Instant.ofEpochMilli(-24227999501L)
172+
},
173+
// Too many fractional second digits (BCE)
174+
new Object[] {
175+
"-000043-03-15T14:00:00.4999Z",
176+
Instant.ofEpochMilli(-63517773599501L)
177+
},
178+
// Lowercase time designator
179+
new Object[] {
180+
"2019-03-26t14:00Z",
181+
Instant.ofEpochMilli(1553608800000L)
182+
},
183+
// Lowercase UTC designator
184+
new Object[] {
185+
"2019-03-26T14:00z",
186+
Instant.ofEpochMilli(1553608800000L)
187+
},
188+
// Hours-only offset
189+
new Object[] {
190+
"2019-03-26T10:00-04",
191+
Instant.ofEpochMilli(1553608800000L)
192+
},
193+
// Fractional minutes
194+
new Object[] {
195+
"2019-03-26T14:00.9Z",
196+
Instant.ofEpochMilli(1553608854000L)
197+
},
198+
// ISO basic format date and time
199+
// not working: new Object[] { "20190326T1400Z", null },
200+
};
201+
}
202+
203+
@Test
204+
@Parameters(method = "parametersParseOutputTimestamp")
205+
public void testParseOutputTimestamp(String input, Instant expected) {
206+
Date actual = GitCommitIdMojo.parseOutputTimestamp(input);
207+
assertThat(actual.toInstant()).isEqualTo(expected);
208+
}
69209
}

0 commit comments

Comments
 (0)