He hecho una unidad de prueba de un servicio, cuando yo haga el trabajo Jenkins, cada método de prueba pasan correctamente, excepto uno.
Pero este método de ensayo, funciona en mi máquina, tanto con Eclipse y utilizando el mvn
comando.
// 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));
}
El servicio tiene métodos Mulitple:
getTodayTimestamp
Danos hoy Marca de tiempo, se pone a prueba este método, que funciona en mi máquina y en Jenkins.dateToTimestamp
toma una fecha y una dateFormat como cadenas, y devuelve la fecha como una marca de tiempo, este método es el que no trabaja.
El dateToTimestamp
método en el servicio:
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;
}
}
Como ya he dicho anteriormente, el trabajo de prueba perfectamente en mi pc, pero no en Jenkins (añadiendo las @Ignore
anotaciones a este método, hace que el trabajo con éxito).
Al poner en marcha el trabajo, me sale este error:
pruebas fallidas: dateToTimestamp (com.test.service.ServiceImplTest): Se esperaba: <2018-01-01 00: 00: 00.0> <pero fue: 31/12/2017 00: 00: 00.0>
Lo que puedo asegurar, es que incluso en Jenkins, el dateToTimestamp
método toma los parámetros TARGET_RUN_DATE_OF_YEAR
, lo que es "2018-01-01"
y la cadena dateFormart como "YYYY-MM-dd"
. Pero aún así devuelve 2017-12-31 00:00:00.0
como marca de tiempo.
¿Algunas ideas?
java.time
Estoy asumiendo que quería una Timestamp
para usar con su base de datos SQL. No utilice Timestamp
para ello en 2019. Esa clase está mal diseñado y largo obsoleta.
- Si el tipo de datos en el lado de SQL es
timestamp with time zone
(que debería ser para una marca de tiempo), utiliceOffsetDateTime
en Java. - Si en el lado de SQL que necesita un simple
timestamp
(sin zona horaria), el usoLocalDateTime
de Java.
Código de ejemplo:
String dateString = "2018-01-01";
OffsetDateTime odt = LocalDate.parse(dateString)
.atStartOfDay()
.atOffset(ZoneOffset.UTC);
System.out.println(odt);
La salida es:
2018-01-01T00: 00Z
Ahora se puede pasar su OffsetDateTime
a JDBC usando algo como:
yourPreparedStatement.setObject(4, odt);
Lo que salió mal en el código?
Creo que está experimentando la combinación de dos cuestiones:
- El uso de mayúsculas
YYYY
en la cadena de patrón de formato no es correcto. MayúsculaY
es para basada semana del año y sólo es útil con un número de la semana. Con el viejo y problemáticoSimpleDateFormat
que habría necesitado minúsculasy
para el año. - (Las JVM) en su máquina y el servidor Jenkins tienen diferentes lugares predeterminados.
Demostrar:
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));
Salida en mi equipo (configuración regional de Dinamarca, Europa / Copenhague zona horaria):
Mi 01 de enero de 2018 0:00:00 CET
Sin embargo si primero hago esto:
Locale.setDefault(Locale.US);
- a continuación, la salida del fragmento anterior es diferente, a saber:
Dom Dic 31 de 2017 00:00:00 CET
Lo que sucede es que SimpleDateFormat
se da por vencido en la determinación de una fecha exacta del año en función semana, mes y día del mes y en su lugar sólo le da la primera fecha del año en función semana. Es un comportamiento típico de SimpleDateFormat
darle un resultado que no puede ser correcto y, sin embargo, pretender que todo está bien. En algunos lugares la semana comienza el lunes, y se obtiene Lun Ene 01, el cual casualmente está de acuerdo con su cadena. En otros lugares, como los EE.UU., la semana comienza el domingo, así que en vez se obtiene Dom Dic 31 del año anterior.
Enlace
- Oracle tutorial: Fecha Hora que explica cómo utilizar java.time.
- Pregunta relacionada sobre mayúscula
Y
del año: java análisis de cadenas hasta la fecha