Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit dcf26d5

Browse filesBrowse files
authored
Merge pull request hub4j#919 from bitwiseman/task/one-more-date
Fixed and streamlined date parsing
2 parents 4f0d62f + 4d46872 commit dcf26d5
Copy full SHA for dcf26d5

File tree

Expand file treeCollapse file tree

2 files changed

+49
-28
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+49
-28
lines changed

‎src/main/java/org/kohsuke/github/GitHubClient.java

Copy file name to clipboardExpand all lines: src/main/java/org/kohsuke/github/GitHubClient.java
+19-18Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919
import java.net.SocketTimeoutException;
2020
import java.net.URL;
2121
import java.nio.charset.StandardCharsets;
22-
import java.text.ParseException;
23-
import java.text.SimpleDateFormat;
22+
import java.time.Instant;
23+
import java.time.format.DateTimeFormatter;
24+
import java.time.temporal.ChronoUnit;
2425
import java.util.Base64;
2526
import java.util.Date;
2627
import java.util.HashMap;
2728
import java.util.List;
2829
import java.util.Map;
2930
import java.util.Objects;
30-
import java.util.TimeZone;
3131
import java.util.function.Consumer;
3232
import java.util.logging.Logger;
3333

@@ -80,9 +80,8 @@ abstract class GitHubClient {
8080
private static final ObjectMapper MAPPER = new ObjectMapper();
8181
static final String GITHUB_URL = "https://api.github.com";
8282

83-
private static final String[] TIME_FORMATS = { "yyyy/MM/dd HH:mm:ss ZZZZ", "yyyy-MM-dd'T'HH:mm:ss'Z'",
84-
"yyyy-MM-dd'T'HH:mm:ss.S'Z'" // GitHub App endpoints return a different date format
85-
};
83+
private static final DateTimeFormatter DATE_TIME_PARSER_SLASHES = DateTimeFormatter
84+
.ofPattern("yyyy/MM/dd HH:mm:ss Z");
8685

8786
static {
8887
MAPPER.setVisibility(new VisibilityChecker.Std(NONE, NONE, NONE, NONE, ANY));
@@ -652,22 +651,24 @@ static URL parseURL(String s) {
652651
static Date parseDate(String timestamp) {
653652
if (timestamp == null)
654653
return null;
655-
for (String f : TIME_FORMATS) {
656-
try {
657-
SimpleDateFormat df = new SimpleDateFormat(f);
658-
df.setTimeZone(TimeZone.getTimeZone("GMT"));
659-
return df.parse(timestamp);
660-
} catch (ParseException e) {
661-
// try next
662-
}
654+
655+
return Date.from(parseInstant(timestamp));
656+
}
657+
658+
static Instant parseInstant(String timestamp) {
659+
if (timestamp == null)
660+
return null;
661+
662+
if (timestamp.charAt(4) == '/') {
663+
// Unsure where this is used, but retained for compatibility.
664+
return Instant.from(DATE_TIME_PARSER_SLASHES.parse(timestamp));
665+
} else {
666+
return Instant.from(DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(timestamp));
663667
}
664-
throw new IllegalStateException("Unable to parse the timestamp: " + timestamp);
665668
}
666669

667670
static String printDate(Date dt) {
668-
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
669-
df.setTimeZone(TimeZone.getTimeZone("GMT"));
670-
return df.format(dt);
671+
return DateTimeFormatter.ISO_INSTANT.format(Instant.ofEpochMilli(dt.getTime()).truncatedTo(ChronoUnit.SECONDS));
671672
}
672673

673674
/**

‎src/test/java/org/kohsuke/github/GitHubStaticTest.java

Copy file name to clipboardExpand all lines: src/test/java/org/kohsuke/github/GitHubStaticTest.java
+30-10Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import java.text.SimpleDateFormat;
66
import java.time.Instant;
7+
import java.time.format.DateTimeParseException;
78
import java.time.temporal.ChronoUnit;
89
import java.util.Date;
910
import java.util.TimeZone;
@@ -20,25 +21,38 @@ public class GitHubStaticTest extends AbstractGitHubWireMockTest {
2021

2122
@Test
2223
public void timeRoundTrip() throws Exception {
23-
Instant instantNow = Instant.now();
24+
final long stableInstantEpochMilli = 1533721222255L;
25+
Instant instantNow = Instant.ofEpochMilli(stableInstantEpochMilli);
2426

2527
Date instantSeconds = Date.from(instantNow.truncatedTo(ChronoUnit.SECONDS));
2628
Date instantMillis = Date.from(instantNow.truncatedTo(ChronoUnit.MILLIS));
2729

28-
// if we happen to land exactly on zero milliseconds, add 1 milli
29-
if (instantSeconds.equals(instantMillis)) {
30-
instantMillis = Date.from(instantNow.plusMillis(1).truncatedTo(ChronoUnit.MILLIS));
31-
}
30+
String instantFormatSlash = formatZonedDate(instantMillis, "yyyy/MM/dd HH:mm:ss ZZZZ", "PST");
31+
assertThat(instantFormatSlash, equalTo("2018/08/08 02:40:22 -0700"));
3232

33-
// TODO: other formats
34-
String instantFormatSlash = formatDate(instantMillis, "yyyy/MM/dd HH:mm:ss ZZZZ");
3533
String instantFormatDash = formatDate(instantMillis, "yyyy-MM-dd'T'HH:mm:ss'Z'");
34+
assertThat(instantFormatDash, equalTo("2018-08-08T09:40:22Z"));
35+
3636
String instantFormatMillis = formatDate(instantMillis, "yyyy-MM-dd'T'HH:mm:ss.S'Z'");
37+
assertThat(instantFormatMillis, equalTo("2018-08-08T09:40:22.255Z"));
38+
39+
String instantFormatMillisZoned = formatZonedDate(instantMillis, "yyyy-MM-dd'T'HH:mm:ss.SXXX", "PST");
40+
assertThat(instantFormatMillisZoned, equalTo("2018-08-08T02:40:22.255-07:00"));
41+
3742
String instantSecondsFormatMillis = formatDate(instantSeconds, "yyyy-MM-dd'T'HH:mm:ss.S'Z'");
43+
assertThat(instantSecondsFormatMillis, equalTo("2018-08-08T09:40:22.0Z"));
44+
45+
String instantSecondsFormatMillisZoned = formatZonedDate(instantSeconds, "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", "PST");
46+
assertThat(instantSecondsFormatMillisZoned, equalTo("2018-08-08T02:40:22.000-07:00"));
47+
3848
String instantBadFormat = formatDate(instantMillis, "yy-MM-dd'T'HH:mm'Z'");
49+
assertThat(instantBadFormat, equalTo("18-08-08T09:40Z"));
3950

4051
assertThat(GitHubClient.parseDate(GitHubClient.printDate(instantSeconds)),
4152
equalTo(GitHubClient.parseDate(GitHubClient.printDate(instantMillis))));
53+
assertThat(GitHubClient.printDate(instantSeconds), equalTo("2018-08-08T09:40:22Z"));
54+
assertThat(GitHubClient.printDate(GitHubClient.parseDate(instantFormatMillisZoned)),
55+
equalTo("2018-08-08T09:40:22Z"));
4256

4357
assertThat(instantSeconds, equalTo(GitHubClient.parseDate(GitHubClient.printDate(instantSeconds))));
4458

@@ -51,14 +65,16 @@ public void timeRoundTrip() throws Exception {
5165

5266
// This parser does not truncate to the nearest second, so it will be equal
5367
assertThat(instantMillis, equalTo(GitHubClient.parseDate(instantFormatMillis)));
68+
assertThat(instantMillis, equalTo(GitHubClient.parseDate(instantFormatMillisZoned)));
5469

5570
assertThat(instantSeconds, equalTo(GitHubClient.parseDate(instantSecondsFormatMillis)));
71+
assertThat(instantSeconds, equalTo(GitHubClient.parseDate(instantSecondsFormatMillisZoned)));
5672

5773
try {
5874
GitHubClient.parseDate(instantBadFormat);
5975
fail("Bad time format should throw.");
60-
} catch (IllegalStateException e) {
61-
assertThat(e.getMessage(), equalTo("Unable to parse the timestamp: " + instantBadFormat));
76+
} catch (DateTimeParseException e) {
77+
assertThat(e.getMessage(), equalTo("Text '" + instantBadFormat + "' could not be parsed at index 0"));
6278
}
6379
}
6480

@@ -226,8 +242,12 @@ public void testMappingReaderWriter() throws Exception {
226242
}
227243

228244
static String formatDate(Date dt, String format) {
245+
return formatZonedDate(dt, format, "GMT");
246+
}
247+
248+
static String formatZonedDate(Date dt, String format, String timeZone) {
229249
SimpleDateFormat df = new SimpleDateFormat(format);
230-
df.setTimeZone(TimeZone.getTimeZone("GMT"));
250+
df.setTimeZone(TimeZone.getTimeZone(timeZone));
231251
return df.format(dt);
232252
}
233253

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.