YARN-11116. Migrate Times util from SimpleDateFormat to thread-safe DateTimeFormatter class (#4242)
Co-authored-by: Jonathan Eagles <jeagles@verizonmedia.com>
Signed-off-by: Akira Ajisaka <aajisaka@apache.org>
(cherry picked from commit d4a91bd0c0
)
This commit is contained in:
parent
7f08b96bcd
commit
6daa369bcf
|
@ -19,8 +19,9 @@
|
|||
package org.apache.hadoop.yarn.util;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
@ -30,23 +31,16 @@ import org.apache.hadoop.classification.InterfaceAudience.Private;
|
|||
public class Times {
|
||||
private static final Log LOG = LogFactory.getLog(Times.class);
|
||||
|
||||
static final String ISO8601DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
|
||||
static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
|
||||
|
||||
// This format should match the one used in yarn.dt.plugins.js
|
||||
static final ThreadLocal<SimpleDateFormat> dateFormat =
|
||||
new ThreadLocal<SimpleDateFormat>() {
|
||||
@Override protected SimpleDateFormat initialValue() {
|
||||
return new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");
|
||||
}
|
||||
};
|
||||
static final DateTimeFormatter DATE_FORMAT =
|
||||
DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss Z yyyy").withZone(
|
||||
ZoneId.systemDefault());
|
||||
|
||||
static final ThreadLocal<SimpleDateFormat> isoFormat =
|
||||
new ThreadLocal<SimpleDateFormat>() {
|
||||
@Override
|
||||
protected SimpleDateFormat initialValue() {
|
||||
return new SimpleDateFormat(ISO8601DATEFORMAT);
|
||||
}
|
||||
};
|
||||
static final DateTimeFormatter ISO_OFFSET_DATE_TIME =
|
||||
DateTimeFormatter.ofPattern(ISO8601_DATE_FORMAT).withZone(
|
||||
ZoneId.systemDefault());
|
||||
|
||||
public static long elapsed(long started, long finished) {
|
||||
return Times.elapsed(started, finished, true);
|
||||
|
@ -82,8 +76,7 @@ public class Times {
|
|||
}
|
||||
|
||||
public static String format(long ts) {
|
||||
return ts > 0 ? String.valueOf(dateFormat.get().format(new Date(ts)))
|
||||
: "N/A";
|
||||
return ts > 0 ? DATE_FORMAT.format(Instant.ofEpochMilli(ts)) : "N/A";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,7 +86,7 @@ public class Times {
|
|||
* @return ISO 8601 formatted string.
|
||||
*/
|
||||
public static String formatISO8601(long ts) {
|
||||
return isoFormat.get().format(new Date(ts));
|
||||
return ISO_OFFSET_DATE_TIME.format(Instant.ofEpochMilli(ts));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,6 +101,6 @@ public class Times {
|
|||
if (isoString == null) {
|
||||
throw new ParseException("Invalid input.", -1);
|
||||
}
|
||||
return isoFormat.get().parse(isoString).getTime();
|
||||
return Instant.from(ISO_OFFSET_DATE_TIME.parse(isoString)).toEpochMilli();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,12 @@ package org.apache.hadoop.yarn.util;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.apache.hadoop.yarn.util.Times.ISO8601_DATE_FORMAT;
|
||||
|
||||
public class TestTimes {
|
||||
|
||||
@Test
|
||||
|
@ -61,4 +67,15 @@ public class TestTimes {
|
|||
elapsed = Times.elapsed(Long.MAX_VALUE, 0, true);
|
||||
Assert.assertEquals("Elapsed time is not -1", -1, elapsed);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateISO() throws IOException {
|
||||
SimpleDateFormat isoFormat = new SimpleDateFormat(ISO8601_DATE_FORMAT);
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
long now = System.currentTimeMillis();
|
||||
String instant = Times.formatISO8601(now);
|
||||
String date = isoFormat.format(new Date(now));
|
||||
Assert.assertEquals(date, instant);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue