起因
public class API {
"/foo") (
List<FooResult> foo(Date beginTime, Date endTime);
}
在另一个系统B中,如下调用feign API。 就像调用本地方法一样,简洁又优雅。
List<FooResult> list = api.foo(new Date(), new Date());
CI/CD同样非常顺滑, 不费什么功夫就顺利通过了测试。 看起来一切都很美好, 不久这一套代码如预期一样顺利上线到了生产环境。 接下来,立马灾难来了, 从B发出的所有请求都400了。
GET /foo?beginTime=Thu%20Jan%2001%2008%3A00%3A00%20CST%201970&endTime=Fri%20Sep%2002%2019%3A01%3A51%20CST%202022和GET /foo?beginTime=Thu%20Jan%2001%2007%3A00%3A00%20WIB%201970&endTime=Fri%20Sep%2002%2018%3A01%3A51%20WIB%202022
public Date(String s) {
this(parse(s));
}
private final static String wtb[] = {
"am", "pm",
"monday", "tuesday", "wednesday", "thursday", "friday",
"saturday", "sunday",
"january", "february", "march", "april", "may", "june",
"july", "august", "september", "october", "november", "december",
"gmt", "ut", "utc", "est", "edt", "cst", "cdt",
"mst", "mdt", "pst", "pdt"
};
如果有的选,避免调用@Deprecated的API,积极拥抱最新的实现。
请保持测试环境与生产环境同样的时区设置,否则出了时区问题会非常不好排查。
java.util.Date里有太多糟糕的实现,我们可以看到大部分方法都被@Deprecated 了,尤其是 Date.toString()和new Date(String),他们都不是使用的ISO格式的日期字符串,更坑的是他们之间不是一对可逆方法。个人偏好在request parameter中使用long类型而不是Date类型。如果要使用Date类型,请一定一定要加上@DateTimeFormat 注解,并且是DateTimeFormat.ISO.DATE_TIME。
如果有系统是因为设置的timezone是Asia/Shanghai而侥幸没有报错的,也不要高兴,因为查询的结果很有可能是有问题的。具体可以试着运行下面的代码,你会发现第4行和第5行的结果不一样了。原因可以自己找一下,反正是Date类的又一个大坑。
Date d0 = new Date();
Date d1 = new Date(d0.toString());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
System.out.println(sdf.format(d0));
System.out.println(sdf.format(d1));
关于领创集团