java - DateFormat UnitTest 在 Jenkins 中失败,但在本地失败
问题描述
我对服务进行了单元测试,当我执行 Jenkins 作业时,每个测试方法都正确通过,除了一个。
但是这种测试方法适用于我的机器,无论是使用 Eclipse 还是使用mvn
命令。
// TARGET_RUN_DATE_OF_YEAR = "2018-01-01"
@Test
public void dateToTimestamp() {
Service service = getService();
String df = "YYYY-MM-dd";
String invalid = "INVALID";
// Check success
Timestamp timestamp = service.dateToTimestamp(TARGET_RUN_DATE_OF_YEAR, df);
Assert.assertEquals(service.getTodayTimestamp(), timestamp); // <-- Fail here
// Check failure
Assert.assertNull(service.dateToTimestamp(TARGET_RUN_DATE_OF_YEAR, invalid));
Assert.assertNull(service.dateToTimestamp(invalid, df));
}
该服务有多种方法:
getTodayTimestamp
给今天时间戳,这个方法已经过测试,它可以在我的机器和 Jenkins 上运行。dateToTimestamp
将日期和日期格式作为字符串,并将日期作为时间戳返回,此方法不起作用。
服务中的dateToTimestamp
方法:
private Timestamp dateToTimestamp(String date, DateFormat df) throws ParseException {
return new Timestamp(df.parse(date).getTime());
}
@Override
public Timestamp dateToTimestamp(String date, String dateFormatString) {
try {
DateFormat df = new SimpleDateFormat(dateFormatString);
return dateToTimestamp(date, df);
} catch (Exception e) {
log.warn("Exception during conversion of date to timestamp, exception : {}", e);
return null;
}
}
正如我之前所说,测试在我的电脑上完美运行,但在 Jenkins 上却不行(向@Ignore
这个方法添加注释,使工作成功)。
启动作业时,我收到此错误:
失败的测试:dateToTimestamp(com.test.service.ServiceImplTest):预期:<2018-01-01 00:00:00.0> 但为:<2017-12-31 00:00:00.0>
我可以保证的是,即使在 Jenkins 中,该dateToTimestamp
方法也采用 parameters TARGET_RUN_DATE_OF_YEAR
,即"2018-01-01"
dateFormat String as "YYYY-MM-dd"
。但仍以2017-12-31 00:00:00.0
时间戳的形式返回。
有任何想法吗?
解决方案
java.time
我假设你想要一个Timestamp
用于你的 SQL 数据库。不要Timestamp
在 2019 年使用它。该课程设计不良且早已过时。
- 如果 SQL 端的数据类型是
timestamp with time zone
(它应该是时间戳),请OffsetDateTime
在 Java 中使用。 - 如果在 SQL 方面您只需要一个
timestamp
(没有时区),请LocalDateTime
在 Java 中使用。
代码示例:
String dateString = "2018-01-01";
OffsetDateTime odt = LocalDate.parse(dateString)
.atStartOfDay()
.atOffset(ZoneOffset.UTC);
System.out.println(odt);
输出是:
2018-01-01T00:00Z
现在您可以OffsetDateTime
使用以下方式将您的 JDBC 传递给 JDBC:
yourPreparedStatement.setObject(4, odt);
你的代码出了什么问题?
我相信您遇到了两个问题的组合:
YYYY
在格式模式字符串中使用大写字母是不正确的。大写字母Y
表示基于周的年份,仅对周数有用。对于旧的和麻烦的SimpleDateFormat
,你需要小写y
一年。- (JVM 上)你的机器和 Jenkins 服务器有不同的默认语言环境。
展示:
String dateString = "2018-01-01";
String dateFormatString = "YYYY-MM-dd"; // Incorrect format pattern string
DateFormat df = new SimpleDateFormat(dateFormatString);
System.out.println(df.parseObject(dateString));
我的电脑上的输出(丹麦语言环境,欧洲/哥本哈根时区):
2018 年 1 月 1 日星期一 00:00:00 CET
但是,如果我首先这样做:
Locale.setDefault(Locale.US);
— 那么上面代码段的输出是不同的,即:
2017 年 12 月 31 日星期日 00:00:00 CET
发生的情况是,SimpleDateFormat
放弃从基于周的年、月和月中的某天确定确切日期,而只是为您提供基于周的年的第一个日期。典型的行为是SimpleDateFormat
给你一个不可能正确的结果,却假装一切都好。在某些语言环境中,一周从星期一开始,您会得到 Mon Jan 01,这恰好 与您的字符串一致。在其他地区(例如美国),一周从星期日开始,因此您会得到上一年的 12 月 31 日星期日。
关联
- Oracle 教程:日期时间解释如何使用 java.time。
Y
关于年份大写的相关问题: java parsing string to date
推荐阅读
- windows - PowerShell 调用-AzOperationalInsightsQuery 错误
- java - oracle JDK 8 中的 JavaFx 是否与 openjfx 8 版本相同?oracle jdk 8中的javafx和openjfx8有什么关系?
- hive - 重命名后如何从镶木地板文件中恢复旧列值?
- vaadin14 - 无法在 Vaadin 14.6.8 中导入 ViewFrame
- tcp - 当 TCP 连接只涉及 2 方时,为什么使用“3-way”这个词?
- python - 带有三个单引号的 Python setup.py entry_points 语法
- c# - 如何在 Y 轴上进行局部旋转
- xcode - 解决 Xcode 中的合并冲突,如 VScode
- c# - Xamarin 键盘消失然后出现
- css - 在 VueChartjs 中更改图例标签位置