Java - 日期减少一天,随机序列化和反序列化该日期



我在生产中遇到了一个奇怪的问题:Java.util.Date字段完全随机地减少了一天。 它很少发生,但有时出现问题并且生产日期减少。

尝试创建自定义序列化程序和反序列化程序没有帮助。

这是代码:

// UserData class
package mypackage;
import myotherpackage.DataDefaultPatternDeserializer;
import myotherpackage.DataDefaultPatternSerializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;
import java.util.Date;
@Data
public class UserData {
//Random problems in production - date decreased by one day
@JsonSerialize(using = DataDefaultPatternSerializer.class)
@JsonDeserialize(using = DataDefaultPatternDeserializer.class)
private Date dateOfBirth;
}

// ----------------------------------------------------------------------------------------
// DataDefaultPatternSerializer class
package myotherpackage;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.util.Date;
import java.util.Locale;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class DataDefaultPatternSerializer extends JsonSerializer<Date> {
public DataDefaultPatternSerializer() {
}
public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyyMMdd").withLocale(Locale.ITALY);
jsonGenerator.writeString(formatter.print(new DateTime(date)));
}
}

// ----------------------------------------------------------------------------------------
// DataDefaultPatternDeserializer class
package myotherpackage;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.util.Date;
import java.util.Locale;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class DataDefaultPatternDeserializer extends JsonDeserializer<Date> {
public DataDefaultPatternDeserializer() {
}
public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyyMMdd").withLocale(Locale.ITALY);
String dateString = jsonParser.getText();
return formatter.parseDateTime(dateString).toDate();
}
}

有什么解决办法吗?

错误类型

切勿使用Date类中的任何一个。这些糟糕的类在几年前就被JSR 310中定义的现代java.time类所取代。

此外,java.util.Date表示一个时刻,一个日期,其时间以 UTC 表示,偏移量为零命中-分钟-秒。您尝试将仅日期值(出生日期)放入 UTC 中具有时间的日期类型中。

时区

日期和时间在java.util.Date上似乎发生变化的原因是,该类在其众多设计缺陷中存在一个toString方法,该方法在生成文本时动态应用 JVM 的当前默认时区。当将一个时刻调整到另一个时区时,一天中的时间甚至日期都可能会"改变"。现在,在我写这篇文章的时候,它是日本东京的"明天",同时在美国俄亥俄州托莱多是"昨天"。

日本东京 现在 05:53:08 上午 于 2022-03-19 星期六

美国俄亥俄州托莱多 现在 2022-03-18 星期五下午 04:53:08

此问题的最佳解决方案是 (a) 不使用旧版java.util.Date类,以及 (b) 不使用 UTC 中具有时间的日期类型来表示仅日期值。

java.time.LocalDate

对于出生日期,请使用仅日期类型LocalDate

LocalDate ld = LocalDate.parse( "1969-01-23" ) ;

要生成标准 ISO 8601 格式的文本,请调用toString

String outputISO8601 = ld.toString() ;

序列 化

将日期时间值序列化为文本时,请使用 ISO 8601 格式。

Jackson 支持java.time类型。

数据库

在类似于 SQL 标准类型DATE类型的列中写入数据库:

myPreparedStatement.setObject( … , ld ) ; 

检索。

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;

最新更新