Skip to content

Commit 7c25e77

Browse files
author
liyong
committed
fix(common): 修复日期解析 int 溢出问题
1 parent 1bcb7b3 commit 7c25e77

2 files changed

Lines changed: 79 additions & 1 deletion

File tree

weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxDateTypeAdapter.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ public Date read(JsonReader in) throws IOException {
3535
in.nextNull();
3636
return null;
3737
case NUMBER:
38-
return new Date(in.nextInt() * 1000);
38+
// 微信返回的是秒级时间戳,需转为毫秒;此处必须用 long 读取并运算,
39+
// 否则 in.nextInt() * 1000 会发生 int 溢出,导致解析出错误的时间
40+
return new Date(in.nextLong() * 1000L);
3941
default:
4042
throw new JsonParseException("Expected NUMBER but was " + peek);
4143
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package me.chanjar.weixin.common.util.json;
2+
3+
import com.google.gson.stream.JsonReader;
4+
import com.google.gson.stream.JsonWriter;
5+
import org.testng.annotations.Test;
6+
7+
import java.io.IOException;
8+
import java.io.StringReader;
9+
import java.io.StringWriter;
10+
import java.util.Date;
11+
12+
import static org.assertj.core.api.Assertions.assertThat;
13+
14+
/**
15+
* WxDateTypeAdapter 的单元测试.
16+
*
17+
* @author liyong
18+
*/
19+
public class WxDateTypeAdapterTest {
20+
21+
private final WxDateTypeAdapter adapter = new WxDateTypeAdapter();
22+
23+
private Date read(String json) throws IOException {
24+
JsonReader reader = new JsonReader(new StringReader(json));
25+
reader.setLenient(true);
26+
return adapter.read(reader);
27+
}
28+
29+
private String write(Date date) throws IOException {
30+
StringWriter out = new StringWriter();
31+
JsonWriter writer = new JsonWriter(out);
32+
writer.setLenient(true);
33+
adapter.write(writer, date);
34+
return out.toString();
35+
}
36+
37+
/**
38+
* 秒级时间戳转成毫秒时如果按 int 运算会溢出,导致解析出的时间错误(甚至早于 1970 年)。
39+
*/
40+
@Test
41+
public void testReadCurrentTimestamp() throws IOException {
42+
long seconds = 1481013459L;
43+
Date date = read(String.valueOf(seconds));
44+
assertThat(date).isNotNull();
45+
assertThat(date.getTime()).isEqualTo(seconds * 1000L);
46+
}
47+
48+
@Test
49+
public void testReadTimestampAfterYear2038() throws IOException {
50+
long seconds = 4102444800L;
51+
Date date = read(String.valueOf(seconds));
52+
assertThat(date).isNotNull();
53+
assertThat(date.getTime()).isEqualTo(seconds * 1000L);
54+
}
55+
56+
@Test
57+
public void testReadNull() throws IOException {
58+
assertThat(read("null")).isNull();
59+
}
60+
61+
@Test
62+
public void testWrite() throws IOException {
63+
long seconds = 1481013459L;
64+
assertThat(write(new Date(seconds * 1000L))).isEqualTo(String.valueOf(seconds));
65+
assertThat(write(null)).isEqualTo("null");
66+
}
67+
68+
/**
69+
* 序列化与反序列化应当可以互相还原。
70+
*/
71+
@Test
72+
public void testWriteThenRead() throws IOException {
73+
Date now = new Date(1600000000L * 1000L);
74+
assertThat(read(write(now))).isEqualTo(now);
75+
}
76+
}

0 commit comments

Comments
 (0)