DateParse.java
package com.alibaba.fastjson2.benchmark;
import com.alibaba.fastjson2.util.DateUtils;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class DateParse {
static final String[] dates = {
"2001-07-01 01:02:03", "2011-06-02 09:02:03",
"2021-11-03 02:02:03", "2001-11-14 07:02:03",
"2002-10-07 16:02:03", "2003-09-12 15:02:03",
"2006-08-16 02:02:03", "2002-01-30 22:02:03",
"2009-02-27 01:02:03", "2011-04-26 11:02:03",
"2012-06-23 01:02:03", "2022-02-18 09:02:03"
};
static ThreadLocal<SimpleDateFormat> formatThreadLocal = ThreadLocal.withInitial(
() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
);
static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
static final ZoneId DEFAULT_ZONE_ID = ZoneId.systemDefault();
static final ZoneId SHANGHAI_ZONE_ID = "Asia/Shanghai".equals(DEFAULT_ZONE_ID.getId()) ? DEFAULT_ZONE_ID : ZoneId.of("Asia/Shanghai");
static final ZoneOffset SHANGHAI_ZONE_OFFSET = SHANGHAI_ZONE_ID
.getRules()
.getOffset(
LocalDateTime.of(
LocalDate.of(1992, 1, 1), LocalTime.MIN
)
);
@Benchmark
public void simpleDateFormat(Blackhole bh) throws Exception {
for (int i = 0; i < dates.length; i++) {
String str = dates[i];
SimpleDateFormat format = formatThreadLocal.get();
bh.consume(
format.parse(str)
);
}
}
@Benchmark
public void dateTimeFormatter(Blackhole bh) throws Exception {
for (int i = 0; i < dates.length; i++) {
String str = dates[i];
LocalDateTime ldt = LocalDateTime.parse(str, formatter);
ZoneOffset offset = DEFAULT_ZONE_ID.getRules().getOffset(ldt);
long millis = ldt.toInstant(offset).toEpochMilli();
bh.consume(new Date(millis));
}
}
@Benchmark
public void localDateTimeParse(Blackhole bh) throws Exception {
for (int i = 0; i < dates.length; i++) {
String str = dates[i];
LocalDateTime ldt = LocalDateTime.parse(str, formatter);
ZoneOffset offset;
if (DEFAULT_ZONE_ID == SHANGHAI_ZONE_ID && ldt.getYear() >= 1992) {
offset = SHANGHAI_ZONE_OFFSET;
} else {
offset = DEFAULT_ZONE_ID.getRules().getOffset(ldt);
}
long millis = ldt.toInstant(offset).toEpochMilli();
bh.consume(new Date(millis));
}
}
@Benchmark
public void parseYYYYMMDDHHMMSS19(Blackhole bh) throws Exception {
for (int i = 0; i < dates.length; i++) {
String str = dates[i];
bh.consume(parseYYYYMMDDHHMMSS19(str));
}
}
public static Date parseYYYYMMDDHHMMSS19(String str) {
if (str == null || str.length() != 19) {
throw new DateTimeParseException("not support input ", str, 0);
}
char c0 = str.charAt(0);
char c1 = str.charAt(1);
char c2 = str.charAt(2);
char c3 = str.charAt(3);
char c4 = str.charAt(4);
char c5 = str.charAt(5);
char c6 = str.charAt(6);
char c7 = str.charAt(7);
char c8 = str.charAt(8);
char c9 = str.charAt(9);
char c10 = str.charAt(10);
char c11 = str.charAt(11);
char c12 = str.charAt(12);
char c13 = str.charAt(13);
char c14 = str.charAt(14);
char c15 = str.charAt(15);
char c16 = str.charAt(16);
char c17 = str.charAt(17);
char c18 = str.charAt(18);
char y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0, s1;
if (c4 == '-' && c7 == '-' && c10 == ' ' && c13 == ':' && c16 == ':') {
y0 = c0;
y1 = c1;
y2 = c2;
y3 = c3;
m0 = c5;
m1 = c6;
d0 = c8;
d1 = c9;
h0 = c11;
h1 = c12;
i0 = c14;
i1 = c15;
s0 = c17;
s1 = c18;
} else {
throw new DateTimeParseException("not support input ", str, 0);
}
int year;
if (y0 >= '0' && y0 <= '9'
&& y1 >= '0' && y1 <= '9'
&& y2 >= '0' && y2 <= '9'
&& y3 >= '0' && y3 <= '9'
) {
year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0');
} else {
throw new DateTimeParseException("not support input ", str, 0);
}
int month;
if (m0 >= '0' && m0 <= '9'
&& m1 >= '0' && m1 <= '9'
) {
month = (m0 - '0') * 10 + (m1 - '0');
} else {
throw new DateTimeParseException("not support input ", str, 0);
}
int dom;
if (d0 >= '0' && d0 <= '9'
&& d1 >= '0' && d1 <= '9'
) {
dom = (d0 - '0') * 10 + (d1 - '0');
} else {
throw new DateTimeParseException("not support input ", str, 0);
}
int hour;
if (h0 >= '0' && h0 <= '9'
&& h1 >= '0' && h1 <= '9'
) {
hour = (h0 - '0') * 10 + (h1 - '0');
} else {
throw new DateTimeParseException("not support input ", str, 0);
}
int minute;
if (i0 >= '0' && i0 <= '9'
&& i1 >= '0' && i1 <= '9'
) {
minute = (i0 - '0') * 10 + (i1 - '0');
} else {
throw new DateTimeParseException("not support input ", str, 0);
}
int second;
if (s0 >= '0' && s0 <= '9'
&& s1 >= '0' && s1 <= '9'
) {
second = (s0 - '0') * 10 + (s1 - '0');
} else {
throw new DateTimeParseException("not support input ", str, 0);
}
long millis;
if (DEFAULT_ZONE_ID == SHANGHAI_ZONE_ID || DEFAULT_ZONE_ID.getRules() == DateUtils.SHANGHAI_ZONE_RULES) {
long seconds = DateUtils.utcSeconds(year, month, dom, hour, minute, second);
int zoneOffsetTotalSeconds = DateUtils.getShanghaiZoneOffsetTotalSeconds(seconds);
seconds -= zoneOffsetTotalSeconds;
millis = seconds * 1000L;
} else {
LocalDate localDate = LocalDate.of(year, month, dom);
LocalTime localTime = LocalTime.of(hour, minute, second, 0);
LocalDateTime ldt = LocalDateTime.of(localDate, localTime);
ZoneOffset offset = DEFAULT_ZONE_ID.getRules().getOffset(ldt);
millis = ldt.toEpochSecond(offset) * 1000;
}
return new Date(millis);
}
public static void main(String[] args) throws Exception {
Options options = new OptionsBuilder()
.include(DateParse.class.getName())
.mode(Mode.Throughput)
.timeUnit(TimeUnit.MILLISECONDS)
.warmupIterations(3)
.forks(1)
.build();
new Runner(options).run();
}
}